「security」カテゴリーアーカイブ

subjectAltNameが設定されていない証明書はChromeで NET::ERR_CERT_COMMON_NAME_INVALID エラー

開発環境用に自己署名のSSL証明書を使っているサイトにChromeでアクセスしたら、
「この接続ではプライバシーが保護されません NET::ERR_CERT_COMMON_NAME_INVALID」というエラーになった。

自己署名証明書(Self-signed certificate)だが、クライアント側はMacではキーチェーンアクセスに登録してx.509基本ポリシーを「常に信頼」にしているし、Windowsでは「コンピューター証明書の管理」で「信頼されたルート証明機関」に登録してある。
CN(Common Name)とアクセスしているホスト名も一致している。

Chrome以外のブラウザでは問題ない。
Chromeでも問題なくアクセスできていたが、急にエラーになるようになった。

エラーメッセージに「このサーバーのセキュリティ証明書は[missing_subjectAltName]から発行されています。」とあるので、証明書にsubjectAltNameが設定されていないことが関係しているようだ。

原因

Chrome 58 以降で、ドメイン名と証明書の照合にcommonNameが使われず、subjectAlternativeNameのみを使用するようになった。(ただし、Chrome 65 までは、EnableCommonNameFallbackForLocalAnchorsを設定すればcommonNameを使用できるらしい。)

https://support.google.com/chrome/a/answer/7391219?hl=en

解決方法

subjectAltNameを設定した自己署名証明書を作成する

openssl.cnfをコピーしたファイルにsubjectAltNameを設定して証明書作成時に指定する。

  1. openssl.cnfをコピー(下記はRedHat系の例。openssl.cnfの場所は環境によって読み替える。Ubuntuは/etc/ssl/openssl.cnf、MacPortsなら/opt/local/etc/openssl/openssl.cnf)
    $ cp /etc/pki/tls/openssl.cnf my-server.example.com.cnf
    
  2. コピーした設定ファイルのreqセクションのx509_extensionsがv3_caになっているので、v3_caセクションにsubjectAltNameを追加すればよさそうだ。
    $ vi my-server.example.com.cnf
    
    [ req ]
    ...
    x509_extensions = v3_ca # The extentions to add to the self signed cert
    ...
    

    v3_caセクションにsubjectAltNameを設定

    [ v3_ca ]
    ...
    subjectAltName=DNS.1:my-server.example.com
    ...
    

    subjectAltNameを複数設定することもできる。

    subjectAltName=DNS.1:my-server.example.com,DNS.2:my-server2.example.com
    

    詳しくは、`man 5 x509v3_config` を参照。

  3. 秘密鍵の作成
    $ openssl genrsa -out my-server.example.com.key 2048
    
  4. 証明書の作成(-configに作成した設定ファイルを指定する
    $ openssl req -new -x509 -days 36500 -sha256 -config my-server.example.com.cnf -key my-server.example.com.key -out my-server.example.com.crt
    

SSHでパスワード認証が無効になっていることを確認する

SSHで公開鍵認証にしてパスワード認証を無効に設定した後、確かにパスワード認証が無効になっていることを確認するため、あえてパスワード認証での接続を試行したい。

-o オプションで、PreferredAuthentications=passwordを指定する。

$ ssh -o PreferredAuthentications=password xxxx@example.com
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Permission deniedになればOK。

OpenSSLコマンドで証明書のチェック

発行したSSLサーバ証明書と中間CA証明書を実際にApache等にインストールする前に、正しいかどうか検証したいことがある。
その場合は、OpenSSLのopensslコマンドで検証することができる。

openssl s_serverでサーバを起動

s_serverは、リモートのクライアントからのSSL/TLSの接続を受け入れる一般的なSSL/TLSサーバを実装している。

openssl s_server -cert <サーバ証明書ファイル> -key <秘密鍵ファイル> -CAfile <中間証明書ファイル>

実行例:

$ openssl s_server -cert server.crt -key server.key -CAfile intermediate.crt 
Using default temp DH parameters
Using default temp ECDH parameters
ACCEPT

openssl s_clientでチェック

起動したサーバに openssl s_client で接続して、証明書を検証する。
s_clientは、リモートのサーバに対するSSL/TLSの接続を確立する一般的なSSL/TLSクライアントを実装している。

openssl s_client -connect localhost:4433 -CAfile <CA証明書ファイル>

CA証明書ファイルの例:

  • Mac OS X
    /etc/openssl/cert.pem
    /opt/local/etc/openssl/cert.pem、/opt/local/share/curl/curl-ca-bundle.crt (MacPortsの場合)
  • Ubuntu (ca-certificates をインストールしておく)
    /etc/ssl/certs/ca-certificates.crt
  • CentOS
    /etc/pki/tls/certs/ca-bundle.crt にあるが、指定しなくても大丈夫。

実行例:

$ openssl s_client -connect localhost:4433 -CAfile /opt/local/share/curl/curl-ca-bundle.crt
CONNECTED(00000003)
depth=3 (略)
verify return:1
depth=2 (略)
verify return:1
depth=1 (略)
verify return:1
depth=0 (略)
verify return:1
---
Certificate chain
 0 s:(略)
   i:(略)
 1 s:(略)
   i:(略)
 2 s:(略)
   i:(略)
 3 s:(略)
   i:(略)
---
Server certificate
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
subject=(略)
issuer=(略)
---
No client certificate CA names sent
---
SSL handshake has read 4744 bytes and written 443 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: (略)
    Session-ID-ctx: 
    Master-Key: (略)
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    (略)
    Compression: 1 (zlib compression)
    Start Time: 1421023132
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

実際にサーバにインストールしたら、s_clientで以下のように証明書をチェックする。
-servername は、SNI(Server Name Indication)のために必要。

実行例:

  • Mac OS X
    (CAfileはMacPortsの場合)

    $ openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts -CAfile /opt/local/etc/openssl/cert.pem
    
  • CentOS

    $ openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts
    
  • Ubuntu
    (ca-certificates をインストールしておく)

    $ openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts -CAfile /etc/ssl/certs/ca-certificates.crt
    

証明書の有効期限をチェックしたい場合は、

$ echo | openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts 2>/dev/null | openssl x509 -noout -dates

電子署名でダウンロードファイルを検証

gnupgがインストールされているか確認。

$ yum list installed gnupg
Loaded plugins: fastestmirror
Installed Packages
gnupg.x86_64                     1.4.5-14.el5_5.1                      installed

インストールされていなければインストール

$ sudo yum install gnupg

※Mac OS X の場合は、MacPortsでgnupgをインストールできる。
設定ファイルを初期化する。
--list-keysはgpgに登録されている公開鍵を表示するコマンド。
初回実行時に設定ファイルが自動的に作成される。

$ gpg --list-key
gpg: ディレクトリー「/home/pistolfly/.gnupg」ができました
gpg: 新しい構成ファイル「/home/pistolfly/.gnupg/gpg.conf」ができました
gpg: 警告: 「/home/pistolfly/.gnupg/gpg.conf」のオプションは起動している間、有効になりません
gpg: 鍵輪「/home/pistolfly/.gnupg/pubring.gpg」ができました
gpg: /home/pistolfly/.gnupg/trustdb.gpg: 信用データベースができました

~/.gnupg/gpg.conf を編集。

$ vi ~/.gnupg/gpg.conf 

以下の部分のコメントを外して、公開鍵を鍵サーバから自動的に取得できるようにする。

#keyserver-options auto-key-retrieve

 ↓

keyserver-options auto-key-retrieve

ダウンロードファイルの真正性を確認する

gpg --verify <電子署名ファイル>

例:

$ ls emacs*
emacs-23.3a.tar.gz emacs-23.3a.tar.gz.sig
$ gpg --verify emacs-23.3a.tar.gz.sig 
gpg: 2011年08月03日 00時39分07秒 JSTにDSA鍵ID BC40251Cで施された署名
gpg: 鍵BC40251Cをhkpからサーバーsubkeys.pgp.netに要求
gpg: 鍵BC40251C: 公開鍵"Chong Yidong <cyd@stupidchicken.com>"を読み込みました
gpg: 絶対的に信用する鍵が見つかりません
gpg:     処理数の合計: 1
gpg:           読込み: 1
gpg: "Chong Yidong <cyd@stupidchicken.com>"からの正しい署名
gpg: 警告: この鍵は信用できる署名で証明されていません!
gpg:       この署名が所有者のものかどうかの検証手段がありません。
主鍵の指紋: AF1A 0574 841E 0F2D EDE2  829A 764D A716 BC40 251C

gpg: "Chong Yidong <cyd@stupidchicken.com>"からの正しい署名
とあるので、OK。
gpg: 警告: この鍵は信用できる署名で証明されていません!
は、公開鍵を信頼していない状態なので表示されている。

rsync and sudo over SSH

rsync and sudo over SSH « crashingdaily
sudo + rsync | きぬろぐ
rsyncでリモートサーバのバックアップを取る場合に、バックアップするユーザに権限がないファイルやディレクトリのバックアップが取れない。
取れるようにするためには、rsyncをsudoで実行すればよい。
まずバックアップされるサーバ側で、バックアップユーザがsudoできるようにする。

# visudo

で、/etc/suduersに以下を加える。

backup ALL= NOPASSWD:/usr/bin/rsync

バックアップされるサーバ側で、.ssh/authorized_keysのcommandオプションでsshで実行できるコマンドを制限している場合は、
sudo\ rsync\ --server
も許可するようにする。
そして、rsync実行時のオプションに

--rsync-path="sudo rsync"

を追加する。
さて、これで設定はOKなはずなので、この状態でバックアップサーバからバックアップを実行すると、、、

sudo: sorry, you must have a tty to run sudo

というエラーになる。
これは、バックアップされるサーバ側の/etc/sudoers ファイルで、'requiretty' フラグがデフォルトで設定されているから。このフラグが設定されている場合、ログインしているユーザ以外はsudoできない。つまり、sshやrsh経由のリモートでのsudoコマンドの実行が許可されない。
Red Hat Knowledgebase: ssh 経由で sudo コマンドを実行すると、tty エラーとなります。
これを回避するには、sudoersでrequirettyフラグを設定しないようにする。

# visudo

で、/etc/sudoers の以下の行をコメントアウト。

#Defaults    requiretty

これで、OK。

Poderosaで公開鍵認証

Tips&Tricks » Poderosaで公開鍵認証
PoderosaではOpenSSHの秘密鍵ファイルは変換しないと使えない。
puttygenで、OpenSSHの秘密鍵をインポート→SECSH(ssh.com)でエクスポートすることで、変換できる。
puttygenでの変換方法。

  1. puttygenを起動。
  2. メニューのConversions > Import keyでOpenSSH(またはSECSH)の秘密鍵を開く。
  3. メニューのConversions > Export ssh.com key(またはExport OpenSSH key)でエクスポート。

sshの公開鍵はいろんな種類があるみたい - blog@longkey1.net
SSHクライアントの秘密鍵/公開鍵についてまとめ : ひろ式めもちょう
端っこなひとの備忘録: PoderosaのSSH2の秘密鍵をOpenSSHで使う