从Apache迁移到Nginx后SSL证书修正
这里讨论的是网站从Apache迁移到Nginx之后,使用python访问网站出现下面的问题:
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
关于如何从Apache迁移到Nginx,请参看How to migrate Apache to Nginx by converting VirtualHosts to Server Blocks。
使用Python访问网站代码:
try:
url='https://www.360converter.com'
tmpfile = '/tmp/utest.html'
urlretrieve( url, tmpfile )
except Exception as e:
print( 'Failed: ' + str( e ))
迁移之后,在浏览器中访问正常,但是Python就有上面的问题。
下面是Apache和nginx配置文件中关于证书配置的部分,
Apache:
SSLCertificateFile /path/to/my.crt
SSLCertificateKeyFile /path/to/my.key
SSLCertificateChainFile /path/to/CA.crt
Nginx
ssl_certificate /path/to/my.crt;
ssl_certificate_key /path/to/my.key;
可以看出Apache中有SSLCertificateChainFile这个指示符号,而nginx则没有,我们简单的做法就是直接将它丢弃。结果就导致了上面的问题,为了解决这个问题,就是my.crt和ca.crt合并。直接ca.crt的内容,里面的所有内容,包括BEGIN和END行添加到my.crt文件的后面,像下面这样:
合并CRT
—–BEGIN CERTIFICATE—–
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
—–END CERTIFICATE—–
—–BEGIN CAbundle CERTIFICATE—–
YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
—–END CAbundle CERTIFICATE—–
这里简单说一下,为什么浏览器可以,为什么python?这是因为浏览器一般都默认安装了这些根证书,而python则没有。 为什么apache可以,nginx(使用没有合并的crt文件)不可以?这是因为在apache中我们配置了 SSLCertificateChainFile, 因此客户端访问的时候apache会把SSLCertificateChainFile指定的根证书同时发送给客户端,而nginx没有。而我们合并crt之后,nginx就会发送根证书了。
Reference
How To Compile Nginx from Source on a CentOS 6.4 x64 VPS
Building Nginx and OpenSSL from Source
How to enable SSL on NGINX
How to properly configure your nginx for TLS