Fedora34 Python3.9请求旧RHEL服务器报SSL UNSUPPORTED_PROTOCOL错误如何解决
解决方案
1. 优先调整系统加密策略(Fedora专属)
Fedora 34默认启用了严格的系统加密策略,默认禁用了TLS 1.0、TLS 1.1等旧版本协议,这是你修改openssl.cnf不生效的核心原因。
- 临时全局降级策略(用完可还原):
执行命令:sudo update-crypto-policies --set LEGACY
执行后重新登录终端即可生效,该策略会自动开启旧TLS版本支持,适配旧版加密套件。需要还原默认策略时执行sudo update-crypto-policies --set DEFAULT即可。 - 不想修改全局配置可以用自定义配置文件:
新建一个自定义openssl配置文件,比如~/openssl_legacy.conf,内容如下:
openssl_conf = default_conf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.0 CipherString = DEFAULT:@SECLEVEL=1
运行Python脚本前先执行export OPENSSL_CONF=~/openssl_legacy.conf,仅对当前终端会话生效,不会影响系统其他程序。
2. Python代码层面正确配置SSL上下文
你之前的配置没有生效,是因为没有将自定义的SSL上下文绑定到请求对象中,正确的可运行代码如下:
urllib版本
import ssl import json import urllib.request # 构造兼容旧TLS版本的SSL上下文 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.min_version = ssl.TLSVersion.TLSv1_0 # 关闭证书校验,适配旧服务器的自签/过期证书 context.check_hostname = False context.verify_mode = ssl.CERT_NONE # 配置加密套件兼容旧版OpenSSL context.set_ciphers('DEFAULT:@SECLEVEL=1') # 将自定义上下文绑定到urllib请求 opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=context)) urllib.request.install_opener(opener) # 执行业务请求 data = json.dumps(pickle_post_data()).encode('utf-8') response = urllib.request.urlopen(U_REGISTRATION_POST, data, 20)
requests版本
import ssl import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class TLS10Adapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=False, **pool_kwargs): context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.min_version = ssl.TLSVersion.TLSv1_0 context.check_hostname = False context.verify_mode = ssl.CERT_NONE context.set_ciphers('DEFAULT:@SECLEVEL=1') self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, ssl_context=context, **pool_kwargs ) session = requests.Session() session.mount('https://', TLS10Adapter()) # 执行业务请求 data = json.dumps(pickle_post_data()).encode('utf-8') response = session.post(U_REGISTRATION_POST, data=data, verify=False)
3. 兜底方案:调用curl命令行发请求
如果上述Python配置依然不生效,可以直接调用系统curl工具发起请求,curl直接调用系统OpenSSL库,只要系统加密策略调整完成就能正常访问,在Python中通过subprocess调用即可:
import subprocess import json post_data = json.dumps(pickle_post_data()) cmd = [ 'curl', '-k', '--tls1.0', '-X', 'POST', '-H', 'Content-Type: application/json', '-d', post_data, U_REGISTRATION_POST ] result = subprocess.run(cmd, capture_output=True, text=True, timeout=20) response_content = result.stdout
注意事项
以上所有方案均为临时过渡方案,旧服务器使用的OpenSSL 0.9.8、TLS 1.0均已停止维护多年,存在大量严重安全漏洞,等准入限制解除后请尽快完成服务器升级替换。
内容的提问来源于stack exchange,提问作者hilton8r
相关产品推荐
相关产品推荐

