* Apache+openSSLでクライアント認証 [#a8f7da3a] #setlinebreak(on); #contents -- 関連 --- [[クライアント認証付きのHTTPSリクエスト発行]] --- [[Javaでhttps通信時の証明書検証について]] --- [[ApacheでSSL(SNI)設定]] ** 手順 [#cceec743] #html(<div style="padding-left:10px;">) + プライベートCAの作成 + サーバ証明書の作成 + クライアント証明書の作成 + Apacheの設定変更 #html(</div>) ** プライベートCAの作成 [#f6bb94ec] #html(<div style="padding-left:10px;">) *** プライベートCA用のディレクトリなどを作成 [#p43ae54c] #html(<div style="padding-left:10px;">) #myterm2(){{ mkdir -p /var/certs/myCA cd /var/certs/myCA mkdir private mkdir newcerts chmod 700 private echo 01>serial touch index.txt sudo openssl req -new -x509 -newkey rsa:2048 -out myca.crt -keyout private/myca.key -days 365 -sha256 ・ いろいろ聞かれるので入力する ・ }} #html(</div>) *** openssl.cnf の作成 [#zbca8b9f] #html(<div style="padding-left:10px;">) オリジナルをコピーしてくる #myterm2(){{ cd /var/certs cp /etc/ssl/openssl.cnf ./ }} 以下の通り編集 /var/certs/openssl.cnf #mycode2(){{ [ca] default_ca = my_ca_default [my_ca_default] new_certs_dir = ./myCA/newcerts database = ./myCA/index.txt serial = ./myCA/serial policy = my_ca_policy default_md = md5 default_days = 365 [my_ca_policy] commonName = supplied countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional emailAddress = optional }} URLにIPアドレスを指定してアクセスする場合は、証明書の Subject Alternative Name もチェックされるので、これを含む証明書を作成する必要がある。 ※作成方法は [[Javaでhttps通信時の証明書検証について]] を参照 #html(</div>) #html(</div>) ** サーバ証明書の作成 [#t9e47755] #html(<div style="padding-left:10px;">) *** 鍵の作成 [#z4d5ea66] #html(<div style="padding-left:10px;">) #myterm2(){{ openssl genrsa -des3 -out example_com.key 1024 Generating RSA private key, 1024 bit long modulus .++++++ ...............++++++ e is 65537 (0x10001) Enter pass phrase for example_com.key: Verifying - Enter pass phrase for example_com.key: }} #html(</div>) *** 鍵のパスフレーズを解除(Apache自動起動用) [#xae96aae] #html(<div style="padding-left:10px;">) #myterm2(){{ openssl rsa -in example_com.key -out example_com_nopass.key Enter pass phrase for example_com.key: writing RSA key }} #html(</div>) *** 証明書への署名要求の作成 [#g6c248f7] #html(<div style="padding-left:10px;">) #myterm2(){{ openssl req -new -sha256 -key example_com.key -out example_com.csr ・ ・ いろいろ聞かれるので入力する。 (注意) Common Name、Organization Name は 実際のドメイン名と合わせておく事。(IPアドレスでアクセスする場合はIPアドレスをそのまま入力) ・ ・ }} #html(</div>) *** プライベートCAで署名 [#s57aee41] #html(<div style="padding-left:10px;">) #myterm2(){{ sudo openssl ca -config ./openssl.cnf -md sha256 -cert myCA/myca.crt -keyfile myCA/private/myca.key -out example_com.crt -in example_com.csr # IPアドレスでアクセスする場合は引数に -extensions v3_req も追加 #sudo openssl ca -config ./openssl.cnf -md sha256 -cert myCA/myca.crt -keyfile myCA/private/myca.key -out 192.168.1.10.crt -in 192.168.1.10.csr -extensions v3_req ・ ・ Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated }} #html(</div>) #html(</div>) ** クライアント証明書の作成 [#zd512cea] #html(<div style="padding-left:10px;">) 基本的にはサーバ証明書と同じだが、署名時に使用する openssl.cnf を一部変更する必要がある。(下記参照) *** 鍵の作成 [#g527d8a5] #html(<div style="padding-left:10px;">) #myterm2(){{ openssl genrsa -des3 -out example_com-client1.key 1024 Generating RSA private key, 1024 bit long modulus .++++++ ...............++++++ e is 65537 (0x10001) Enter pass phrase for example_com.key: Verifying - Enter pass phrase for example_com-client1.key: }} #html(</div>) *** 証明書への署名要求の作成 [#a7e5eeb0] #html(<div style="padding-left:10px;">) #myterm2(){{ openssl req -new -sha256 -key example_com-client1.key -out example_com-client1.csr ・ いろいろ聞かれるので入力 ・ }} #html(</div>) *** openssl.cnf を一部変更した openssl-client.cnf を作成 [#saaf2894] #myterm2(){{ [my_ca_default] . . x509_extensions = usr_cert # 追加 . . [ usr_cert ] # 追加 basicConstraints=CA:FALSE # 追加 nsCertType = client, email # 追加 }} *** プライベートCAで署名( openssl-client.cnf を使用する事 ) [#v1c9261e] #html(<div style="padding-left:10px;">) #myterm2(){{ sudo openssl ca -config ./openssl-client.cnf -md sha256 -cert myCA/myca.crt -keyfile myCA/private/myca.key -out example_com-client1.crt -in example_com-client1.csr ・ ・ Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated }} #html(</div>) #html(</div>) ** Apacheの設定変更 [#jdcf88be] #html(<div style="padding-left:10px;">) *** 設定ファイル変更 [#h8e6d055] #html(<div style="padding-left:10px;">) #myhtml2(){{ <VirtualHost *:443> . . SSLCertificateFile /var/certs/example_com.crt SSLCertificateKeyFile /var/certs/example_com_nopass.key # プライベート認証局証明書のパス(クライアント証明書に署名したCA) SSLCACertificateFile /var/certs/myCA/myca.crt # クライアント証明書を要求する SSLVerifyClient require . . </VirtualHost> }} #html(</div>) *** 再起動 [#d0ac0942] #html(<div style="padding-left:10px;">) #myterm2(){{ sudo /usr/sbin/apachectl restart }} #html(</div>) #html(</div>) ** 動作確認 [#wef7dbef] #html(<div style="padding-left:10px;">) #myterm2(){{ curl https://xxx.xxx.xxx/ --cacert /var/certs/myCA/myca.crt --key /var/certs/example_com-client1.key --cert /var/certs/example_com-client1.crt }} ただし curl が openSSL でビルドされてない場合は以下のように怒られる。 #myterm2(){{ curl: (58) SSL: Can't load the certificate "/var/certs/client1.crt" and its private key: OSStatus -25299」 }} この場合は brew install curl --with-openssl で入れ直すか、クライアント証明書を PKCS#12 形式に変換する。 #myterm2(){{ openssl pkcs12 -export -in /var/certs/example_com-client1.crt -inkey /var/certs/example_com-client1.key -out /var/certs/example_com-client1.p12 }} 変換したP12形式の証明書を使用してリクエストする場合 #myterm2(){{ curl https://xxx.xxx.xxx/ --cacert /var/certs/myCA/myca.crt -E /var/certs/example_com-client1.p12:password }} #html(</div>)