代码改变世界

Python升级后ssl模块不可用问题解决和浅析

2019-09-20 09:20  潇湘隐者  阅读(7671)  评论(2编辑  收藏  举报

在Cent0S 7.5下将Python 2.7.5升级到Python 3.6.6后,发现ssl模块不可用,具体详细信息如下所示:

 

[root@db-server ~]# pip list
Package    Version
---------- -------
pip        19.2.3 
setuptools 39.0.1 
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)) - skipping
 
[root@db-server ~]# python -V
Python 3.6.6
 
>>> import ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/ssl.py", line 101, in <module>
    import _ssl             # if we can't import it, let the error propagate
ModuleNotFoundError: No module named '_ssl'
>>> 
>>> import socket
>>> hasattr(socket,"SSL")
False
>>>

 

 

检查发现openssl包已经安装了,然后按照网上的文章,修改Modules/Setup.dist中,找到SSL配置部分,如下截图所示

 

[root@db-server ~]# yum list installed |grep openssl
openssl.x86_64                        1:1.0.2k-19.el7                  @base    
openssl-libs.x86_64                   1:1.0.2k-19.el7                  @base 

 

 

# Socket module helper for SSL support; you must comment out the other

# socket line above, and possibly edit the SSL variable:

#SSL=/usr/local/ssl

#_ssl _ssl.c \

#       -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \

#       -L$(SSL)/lib -lssl -lcrypto

 

# The crypt module is now disabled by default because it breaks builds

# on many systems (where -lcrypt is needed), e.g. Linux (I believe).

#

# First, look at Setup.config; configure may have set this for you.

 

#_crypt _cryptmodule.c # -lcrypt        # crypt(3); needs -lcrypt on some systems

 

clip_image001[4]

 

这里需要取消注释部分(上图红框附近部分的设置),设置SSL路径,但是这个SSL的安装路径在哪里呢? 我查找了一下,发现openssl的安装路径如下:

 

[root@db-server ~]# whereis openssl
openssl: /usr/bin/openssl /usr/lib64/openssl /usr/share/man/man1/openssl.1ssl.gz
[root@db-server ~]# rpm -ql openssl
/etc/pki/CA
/etc/pki/CA/certs
/etc/pki/CA/crl
/etc/pki/CA/newcerts
/etc/pki/CA/private
/etc/pki/tls/certs/Makefile
/etc/pki/tls/certs/make-dummy-cert
/etc/pki/tls/certs/renew-dummy-cert
/etc/pki/tls/misc/CA
/etc/pki/tls/misc/c_hash
/etc/pki/tls/misc/c_info
/etc/pki/tls/misc/c_issuer
/etc/pki/tls/misc/c_name
/usr/bin/openssl
/usr/share/doc/openssl-1.0.2k
/usr/share/doc/openssl-1.0.2k/FAQ
/usr/share/doc/openssl-1.0.2k/NEWS
/usr/share/doc/openssl-1.0.2k/README
/usr/share/doc/openssl-1.0.2k/README.FIPS
/usr/share/doc/openssl-1.0.2k/README.legacy-settings
/usr/share/licenses/openssl-1.0.2k
/usr/share/licenses/openssl-1.0.2k/LICENSE
/usr/share/man/man1/asn1parse.1ssl.gz
/usr/share/man/man1/ca.1ssl.gz
/usr/share/man/man1/ciphers.1ssl.gz
/usr/share/man/man1/cms.1ssl.gz
/usr/share/man/man1/crl.1ssl.gz
/usr/share/man/man1/crl2pkcs7.1ssl.gz
/usr/share/man/man1/dgst.1ssl.gz
/usr/share/man/man1/dhparam.1ssl.gz
/usr/share/man/man1/dsa.1ssl.gz
/usr/share/man/man1/dsaparam.1ssl.gz
/usr/share/man/man1/dss1.1ssl.gz
/usr/share/man/man1/ec.1ssl.gz
/usr/share/man/man1/ecparam.1ssl.gz
/usr/share/man/man1/enc.1ssl.gz
/usr/share/man/man1/errstr.1ssl.gz
/usr/share/man/man1/gendsa.1ssl.gz
/usr/share/man/man1/genpkey.1ssl.gz
/usr/share/man/man1/genrsa.1ssl.gz
/usr/share/man/man1/md2.1ssl.gz
/usr/share/man/man1/md4.1ssl.gz
/usr/share/man/man1/md5.1ssl.gz
/usr/share/man/man1/mdc2.1ssl.gz
/usr/share/man/man1/nseq.1ssl.gz
/usr/share/man/man1/ocsp.1ssl.gz
/usr/share/man/man1/openssl.1ssl.gz
/usr/share/man/man1/pkcs12.1ssl.gz
/usr/share/man/man1/pkcs7.1ssl.gz
/usr/share/man/man1/pkcs8.1ssl.gz
/usr/share/man/man1/pkey.1ssl.gz
/usr/share/man/man1/pkeyparam.1ssl.gz
/usr/share/man/man1/pkeyutl.1ssl.gz
/usr/share/man/man1/req.1ssl.gz
/usr/share/man/man1/ripemd160.1ssl.gz
/usr/share/man/man1/rsa.1ssl.gz
/usr/share/man/man1/rsautl.1ssl.gz
/usr/share/man/man1/s_client.1ssl.gz
/usr/share/man/man1/s_server.1ssl.gz
/usr/share/man/man1/s_time.1ssl.gz
/usr/share/man/man1/sess_id.1ssl.gz
/usr/share/man/man1/sha.1ssl.gz
/usr/share/man/man1/sha1.1ssl.gz
/usr/share/man/man1/sha224.1ssl.gz
/usr/share/man/man1/sha256.1ssl.gz
/usr/share/man/man1/sha384.1ssl.gz
/usr/share/man/man1/sha512.1ssl.gz
/usr/share/man/man1/smime.1ssl.gz
/usr/share/man/man1/speed.1ssl.gz
/usr/share/man/man1/spkac.1ssl.gz
/usr/share/man/man1/sslpasswd.1ssl.gz
/usr/share/man/man1/sslrand.1ssl.gz
/usr/share/man/man1/ts.1ssl.gz
/usr/share/man/man1/verify.1ssl.gz
/usr/share/man/man1/version.1ssl.gz
/usr/share/man/man1/x509.1ssl.gz
/usr/share/man/man5/config.5ssl.gz
/usr/share/man/man5/openssl.cnf.5ssl.gz
/usr/share/man/man5/x509v3_config.5ssl.gz
/usr/share/man/man7/des_modes.7ssl.gz

 

尝试了几个路径,例如SSL=/usr/lib64/openssl ,然后重新编译安装Python,发现依然报错,

 

[root@db-server Python-3.6.6]# vi Modules/Setup.dist

 

 

SSL=/usr/lib64/openssl

_ssl _ssl.c \

       -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \

       -L$(SSL)/lib -lssl -lcrypto

 

 

#cd /tmp/Python-3.6.6

#./configure --prefix=/usr/local

#make

#make install

 

在Python的解压安装包里面,我查了一下setup.py , 搜索ssl关键字,发现有如下一些代码, 但是我在系统搜索了一下,居然找不到这些目录(ssl/include和/ssl/lib)和ssl.h这些文件。

[root@db-server ~]# vi /tmp/Python-3.6.6/setup.py
    # Detect SSL support for the socket module (via _ssl)
        search_for_ssl_incs_in = [
                              '/usr/local/ssl/include',
                              '/usr/contrib/ssl/include/'
                             ]
        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
                             search_for_ssl_incs_in
                             )
        if ssl_incs is not None:
            krb5_h = find_file('krb5.h', inc_dirs,
                               ['/usr/kerberos/include'])
            if krb5_h:
                ssl_incs += krb5_h
        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
                                     ['/usr/local/ssl/lib',
                                      '/usr/contrib/ssl/lib/'
                                     ] )
 
        if (ssl_incs is not None and
            ssl_libs is not None):
            exts.append( Extension('_ssl', ['_ssl.c'],
                                   include_dirs = ssl_incs,
                                   library_dirs = ssl_libs,
                                   libraries = ['ssl', 'crypto'],
                                   depends = ['socketmodule.h']), )
        else:
            missing.append('_ssl')

  

clip_image002[4]

 

 

[root@db-server ~]# ls -lrt /usr/lib64/openssl
total 0
drwxr-xr-x. 2 root root 218 Sep 20 07:00 engines
 
[root@db-server ~]# ls /usr/local/ssl
ls: cannot access /usr/local/ssl: No such file or directory
 
[root@db-server ~]# find / -name ssl.h

 

后面才搞清楚,openssl包只包含了可执行部分,openssl-devel才包含了头文件、头文件参考、某些库文件等以及跟开发相关的东西。所以只安装了openssl包是找不到相应的头文件的,安装完openssl-devel之后,验证确认这些目录和文件已经存在了。

 

[root@db-server ~]# rpm -qa | grep openssl-devel
[root@db-server ~]# rpm -qa | grep openssl
openssl-1.0.2k-19.el7.x86_64
openssl-libs-1.0.2k-19.el7.x86_64
 
[root@db-server ~]# yum list installed |grep openssl-devel
[root@db-server ~]# yum list installed |grep openssl
openssl.x86_64                        1:1.0.2k-19.el7                  @base    
openssl-libs.x86_64                   1:1.0.2k-19.el7                  @base    
[root@db-server ~]# 
 
[root@db-server ~]# yum install openssl-devel

 

使用# rpm -ql  openssl-devel 定位安装安装路径为/usr/include/openssl,修改安装路径的Modules/Setup.dist文件,修改后的部分如下所示(对比上面截图),然后重新编译安装Python后问题彻底解决。

 

 

# Socket module helper for SSL support; you must comment out the other

# socket line above, and possibly edit the SSL variable:

SSL=/usr/include/openssl

_ssl _ssl.c \

        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \

        -L$(SSL)/lib -lssl –lcrypto

 

 

clip_image003[4]

 

 

参考资料:

 

https://www.cnblogs.com/minglee/p/9232673.html