Python2 ベースの https クライアントを使用できるように、証明書で Nginx 1.8 を動作させるのに問題があります。(requests.py、URLLib)
nginx を設定するときに、Comodo および GlobalTrust ワイルドカード証明書を使用してサーバー上でチェーン化しようとしましたが、Python からこのエラーが発生します。
requests.exceptions.SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Nginx では、SSL を設定するために次のディレクティブを使用しています。
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:HIGH:!MD5:!aNULL:!EDH:!CAMELLIA;
ssl_protocols TLSv1.2 TLSv1.1 SSLv3;
#ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/nginx/alphassl/cert_bundle.crt;
ssl_certificate_key /etc/nginx/newkey/key.key;
そして、サーバー上で証明書を連鎖させ、
cat server.crt intermediate.crt root.crt > cert_bundle.crt
Comodoの場合:
cat server.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > ssl_bundled.crt
curl、chrome、python3では問題なく動作しますが、python 2.7.6からは次のようなリクエストでアクセスできるようにする必要があります。
import requests
requests.get('https://server.com/', verify=True)
また、リクエストすることもできます詳しくはこちら私の証明書のベンダーである python2 からのものなので、これは python クライアントではなくサーバーの問題であると考えています。
さらに、opensslでデバッグすると次のようになります。
openssl s_client -connect g.peakdata.net:443 -CAfile /etc/ssl/certs/ca-certificates.crt
CONNECTED(00000003)
depth=0 OU = Domain Control Validated, OU = PositiveSSL Wildcard, CN = *.peakdata.net
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, OU = PositiveSSL Wildcard, CN = *.peakdata.net
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, OU = PositiveSSL Wildcard, CN = *.peakdata.net
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.peakdata.net
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFUTCCBDmgAwIBAgIQYc2m4QZ+tkek2fUe/Y7+1jANBgkqhkiG9w0BAQsFADCB
kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
QTAeFw0xNTA1MDUwMDAwMDBaFw0xNjA1MTIyMzU5NTlaMFsxITAfBgNVBAsTGERv
bWFpbiBDb250cm9sIFZhbGlkYXRlZDEdMBsGA1UECxMUUG9zaXRpdmVTU0wgV2ls
ZGNhcmQxFzAVBgNVBAMUDioucGVha2RhdGEubmV0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA5Jor5AzXAxaUdc5e1Oim3Fmo5fpAv8Ug42r6mTM81JGV
lxi4ICQ/3FszeJARUs0KhaS4k6nnf0VsCudw2DDw0u3jfAstjhS5JCNLDFAY1D01
GzKp1EZ0iU9xsE8qa/6iPFQ9v9zVzQ72wimk00X32pPAGKrVr8L9w11JtfTrjP1Q
N6QygQBu7KcCtMRCA5eWinz3PnYdZL7analYasY2sY+/tp5iQJasiOfuXKO82of+
wBV5wsh1igR1BzwKOAhU8IYN1pKilvbhMb6qeMP3CAZMe205ACQavqfq4a2aK1pR
oqK9r9jiqzUj4sULbTVS+Kd6OqydtSJF8xaUU/Di7QIDAQABo4IB2TCCAdUwHwYD
VR0jBBgwFoAUkK9qOpRaC9iQ6hJWc99DtDoo2ucwHQYDVR0OBBYEFEifaFvh1SCN
ceI/gwjjeCiiW7ArMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1Ud
JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEB
AgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BT
MAgGBmeBDAECATBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vY3JsLmNvbW9kb2Nh
LmNvbS9DT01PRE9SU0FEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3Js
MIGFBggrBgEFBQcBAQR5MHcwTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jcnQuY29tb2Rv
Y2EuY29tL0NPTU9ET1JTQURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5j
cnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAnBgNVHREE
IDAegg4qLnBlYWtkYXRhLm5ldIIMcGVha2RhdGEubmV0MA0GCSqGSIb3DQEBCwUA
A4IBAQB2m/qah9mHPUQn3yRd3LHRHIigxdDySh5Rb75255I2AuSPQ3HQoi7vt0TB
0oOgRbdZ2RuLtlZVd6nOfQ24dh0rJ5JOzXDAb4hpfsDimpvzEMoqPudJpJgbjLJc
Bhx30ny0MecheoS/In1t59bw8RKZUukyGRqWHsQDbRq5F2MUWc7WFokydmTY1o9o
EQBKdOykiYRS07M7oqFc5weyCnii/dE4WtT7g4gA5zQsvPzsEmeKqvxY5RI8eg1R
8cF/Mr5iov9xGyPelgHwgHroE34G9YclxXVeyDcUlSWUK2j30M28h/feGkVMj+U4
+SZk/Ek5WhfUJmgy+b6JTtB8/l67
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.peakdata.net
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 2036 bytes and written 427 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-RC4-SHA
Session-ID: 8ACFB450411BE9FF0B26CAA57047D80D9A146F41CDD093C8247698216BCF6FE1
Session-ID-ctx:
Master-Key: 515A3952C76176757C51EA8B8FA35FC71C2CD496ABDE0D6E1870E04D1B020F786267D761C7A38051EFA14DE552D10F53
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 600 (seconds)
TLS session ticket:
0000 - d7 35 92 7d 59 5c ba 5c-9a 4d 79 c7 b5 b6 3e 1a .5.}Y\.\.My...>.
0010 - df 9a 5f de f4 af 9d 29-0e a8 d1 23 01 08 aa 64 .._....)...#...d
0020 - 81 0f 4d 6f e2 a6 19 3e-ca 7e a9 9f d3 c8 a0 96 ..Mo...>.~......
0030 - ce a1 37 a3 99 96 da 26-6f 83 ff 41 96 41 dc 17 ..7....&o..A.A..
0040 - d7 11 6c be 50 1f 0c 7d-ad e5 0f 34 d8 fd db be ..l.P..}...4....
0050 - 87 3e fe 05 92 06 c8 0e-fc fc cc 8f f6 ae 08 a6 .>..............
0060 - a3 3e c1 3e 61 4a fd 41-1f 5b 24 8d 97 6a aa e3 .>.>aJ.A.[$..j..
0070 - 36 6b 68 1d f2 31 e7 da-05 29 59 1b 8f 21 38 25 6kh..1...)Y..!8%
0080 - dc 67 8e bf 8e 02 63 26-43 f1 c3 9e 7c 78 e5 e3 .g....c&C...|x..
0090 - cd ea 63 77 02 03 6a 01-10 45 84 c1 d9 73 c4 b0 ..cw..j..E...s..
00a0 - e7 2d 86 a8 72 d8 ed b9-05 5c 2c a1 4b 66 8f 8a .-..r....\,.Kf..
Start Time: 1431626677
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
ありがとう
答え1
これは、サーバーの設定が悪く、サポートが不足していることが原因です。 SNI (サーバー名表示)Python 2.7.6 では、同じ IP アドレスで複数の証明書をサポートするには SNI が必要です。SNI サポートは Python3 にあり、バージョン 2.7.9 でも追加されましたが、バージョン 2.7.6 には含まれていません。
SNI なしでサーバーに接続すると、証明書のみが取得され、信頼チェーンは取得されません。
$ openssl s_client -connect g.peakdata.net:443
...
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.peakdata.net
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
代わりに SNI を使用してサーバーに接続すると、ルート CA を含む完全なチェーンが取得されます (ルート CA を含める必要はありません。クライアントはこれを無視します)。
$ openssl s_client -connect g.peakdata.net:443 -CAfile /etc/ssl/certs/ca-certificates.crt -servername g.peakdata.net
...
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.peakdata.net
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
3 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
python3 とブラウザは SNI を使用するため、成功します。Python 2.7.6 は SNI を使用せず、正しい証明書を取得しますが、チェーンが欠落しています。そのため、ローカル ルート CA に対して証明書を検証できません。