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
그리고 코모도의 경우:
cat server.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > ssl_bundled.crt
컬, 크롬, Python3에서는 잘 작동하지만 다음과 같은 요청을 사용하여 Python 2.7.6에서 액세스할 수 있어야 합니다.
import requests
requests.get('https://server.com/', verify=True)
나는 또한 요청을 할 수 있습니다https://store.ssl2buy.com/내 인증서 공급업체인 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(서버 이름 표시)파이썬 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를 포함한 전체 체인을 얻게 됩니다(포함할 필요가 없으며 클라이언트는 이를 무시합니다).
$ 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에 대해 인증서를 확인할 수 없습니다.