目录
OpenSSL组件库
-
OpenSSL是用于应用程序的软件库,该应用程序可保护计算机网络上的通信免遭窃听或需要识别另一方的身份,是SSL和TLS协议的开源实现。
-
采用C语言作为开发语言,具备了跨平台的能力,支持Unix/Linux、Windows、Mac OS等多种平台。
-
OpenSSL整个软件包大概可以分成三个主要的功能部分:
- 密码算法库
- SSL协议库
- 应用程序
-
密码算法库是一个强大完整的密码算法库,它是OpenSSL的基础部分,也是很值得一般密码安全技术人员研究的部分,它实现了目前大部分主流的密码算法和标准。主要包括对称算法、非对称算法、散列算法、数字签名和认证、X509数字证书标准、PKCS12、PKCS7等标准。其他两个功能部分SSL协议和应用程序都是基于这个库开发的。
-
SSL协议部分完全实现和封装了SSL协议的三个版本和TLS协议。
-
应用程序覆盖了密码技术的应用,主要包括了各种算法的加密程序和各种类型密钥的产生程序(如RSA、Md5、Enc等等)、证书签发和验证程序(如Ca、X509、Crl等)、SSL连接测试程序(如S_client和S_server等)以及其它的标准应用程序(如Pkcs12和Smime等)。
安装和配置
OpenSSL 是一个开源项目,其组成主要包括一下三个组件:
-
openssl:多用途的命令行工具
-
libcrypto:加密算法库
-
libssl:加密模块应用库,实现了ssl及tls
openssl可以实现秘钥证书管理、对称加密和非对称加密 。安装OpenSSL通常很简单,大多数操作系统都提供了预编译的包。例如,在Ubuntu上,可以使用apt-get install openssl命令进行安装。

在windows上如果不想自己编译源码,那么可以直接去下载编译好的二进制文件进行安装,省事方便:

Win64 OpenSSL x Light,安装Win64 OpenSSL xi版本最常用的软件包
Win64 OpenSSL xi,安装Win64 OpenSSL xi版本完整软件包
Win32 OpenSSL xi Light,安装Win32 OpenSSL xi版本最常用的软件包
Win32 OpenSSL xi,安装Win32 OpenSSL xi版本完整软件包
基本概念和术语
SSL/TLS (SSL/TLS)
SSL (Secure Sockets Layer): 一种安全协议,用于在互联网上提供加密通信。
TLS (Transport Layer Security): SSL的继承者,提供更强的安全性。
SSL(Secure Sockets Layer 安全套接层)和TLS(Transport Layer Security 传输层安全)是保护网络通信安全的协议。它们的主要区别在于:
-
SSL 是早期的加密协议,由网景公司开发。随着时间的推移,它的安全性逐渐降低。
-
TLS 是SSL的继任者,提供了更强的安全性和更高效的性能。
SSL/TLS握手是建立加密通信的关键步骤。这个过程涉及多个阶段,包括:
-
客户端和服务器的协议版本协商:确定使用哪个版本的SSL/TLS。
-
密钥交换:客户端和服务器交换密钥信息,确保双方都能加密和解密信息。
-
证书验证:客户端验证服务器的身份,确保通信安全。
在SSL/TLS中,加密算法和密钥交换是保证数据安全的核心。这包括:
-
对称加密:双方共享一个密钥,用于加密和解密信息。
-
非对称加密:使用一对公钥和私钥,其中一个用于加密,另一个用于解密。
非对称加密
公钥 (Public Key): 用于加密数据,可以公开。
私钥 (Private Key): 用于解密数据,必须保密。
- 先使用 genrsa 标准命令生成私钥;
- 再使用 rsa 标准命令从私钥中提取公钥;
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [-f4] [-3] [-rand file(s)] [-engine id] [numbits]
# 生成私钥,指定私钥的长度为2048bit 1024基本安全, 2048非常安全
openssl genrsa -out rsa_private_key.pem 2048
# 根据私钥生成对应的公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key_2048.pub
# 私钥转化成pkcs8格式, 非必须,pkcs8格式解析起来更方便
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt > rsa_private_key_pkcs8.pem
TCP/IP与SSL/TLS的结合
-
SSL (Secure Sockets Layer)安全套接层。是由Netscape公司于1990年开发,用于保障Word Wide Web(WWW)通讯的安全。主要任务是提供私密性,信息完整性和身份认证。1994年改版为SSLv2,1995年改版为SSLv3.
-
TLS(Transport Layer Security)安全传输层协议,)用于在两个通信应用程序之间提供保密性和数据完整性。该标准协议是由IETF于1999年颁布,整体来说TLS非常类似SSLv3,只是对SSLv3做了些增加和修改。
这两者的结合实际上是一种将安全层嵌入到传输层的尝试。TCP/IP协议(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是互联网的基础,而SSL/TLS(Secure Sockets Layer/Transport Layer Security,安全套接字层/传输层安全)则为这个基础增添了一层安全保护。

协议结构如下图:

-
SSL的体系结构中包含两个协议子层,其中底层是SSL记录协议层(SSL Record Protocol Layer);高层是SSL握手协议层(SSL HandShake Protocol Layer)。
-
SSL协议主要分为两层:
-
SSL记录协议层的作用是为高层协议提供基本的安全服务。SSL纪录协议针对HTTP协议进行了特别的设计,使得超文本的传输协议HTTP能够在SSL运行。纪录封装各种高层协议,具体实施压缩解压缩、加密解密、计算和校验MAC等与安全有关的操作。
-
SSL握手协议层包括SSL握手协议(SSL HandShake Protocol)、SSL密码参数修改协议(SSL Change Cipher Spec Protocol)和SSL告警协议(SSL Alert Protocol)。握手层的这些协议用于SSL管理信息的交换,允许应用协议传送数据之间相互验证,协商加密算法和生成密钥等。
-
-
SSL握手协议的作用是协调客户和服务器的状态,使双方能够达到状态的同步。
-
其中最重要的是记录协议和握手协议:
- SSL记录协议:它建立在可靠的传输(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能。
- SSL握手协议:它建立在SSL记录协议之上,用于在实际的数据传输开始之前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
在TCP/IP模型中,数据在从应用层向下传输到网络层时,会经历多次封装。每一层都会添加自己的头部信息。而在SSL/TLS中,加密发生在应用层数据被传递到传输层之前。这意味着,加密数据被TCP看作是普通数据进行传输。在接收端,数据被TCP层解封装后,再由SSL/TLS层进行解密,然后传递给应用层。
SSL/TLS使用对称加密和非对称加密的结合。非对称加密用于握手阶段的密钥交换,而对称加密则用于实际的数据传输。这种结合利用了两种加密方法的优点:非对称加密的安全性和对称加密的效率。
握手过程
SSL/TLS 连接通常包括握手阶段和数据传输阶段,其中握手阶段使用非对称加密,数据传输阶段使用对称加密。
1. 握手阶段(建立安全连接,主要使用非对称加密)
握手阶段的主要目的是让客户端和服务器协商出一个共享的对称密钥,并建立信任关系。这一过程涉及多个步骤:
(1) 客户端 Hello
- 客户端向服务器发送一个 Client Hello,内容包括:
- 支持的 TLS 版本(如 TLS 1.2、TLS 1.3)
- 支持的加密算法(如 AES、ChaCha20)
- 一个 随机数(Client Random),用于后续密钥计算
(2) 服务器 Hello
- 服务器收到 Client Hello 后,回复 Server Hello,内容包括:
- 确定使用的 TLS 版本和加密算法
- 另一个 随机数(Server Random)
- 服务器的 数字证书(包含公钥),用于身份验证
(3) 服务器证书验证
- 客户端检查服务器的 SSL 证书,验证其是否由受信任的 CA(证书颁发机构)签名。
- 如果证书有效,客户端继续进行握手,否则终止连接。
(4) 生成对称密钥
这一部分的方式取决于具体的 TLS 版本:
-
TLS 1.2 及以前:
- 客户端生成一个 Pre-Master Secret(预主密钥)。
- 使用服务器的 公钥 加密 Pre-Master Secret 并发送给服务器。
- 服务器使用 私钥 解密,得到 Pre-Master Secret。
- 双方基于 Pre-Master Secret + Client Random + Server Random 计算最终的 会话密钥(Session Key),用于后续对称加密。
-
TLS 1.3(改进版)
- 采用 ECDHE(椭圆曲线 Diffie-Hellman 密钥交换),客户端和服务器各自生成临时密钥对,并交换公钥。
- 双方使用自己的私钥和对方的公钥计算出相同的 会话密钥(Session Key)。
- 优点:前向安全性(Perfect Forward Secrecy, PFS),即使服务器私钥泄露,历史通信数据仍然安全。
(5) 握手完成
- 客户端和服务器都计算出相同的 Session Key。
- 发送一个 Finished 消息,表明握手完成。
2. 数据传输阶段(使用对称加密)
- 之后的所有通信数据都会使用对称加密(如 AES、ChaCha20)进行加密和解密,提升效率。
- 由于对称加密速度快,能够高效地加密和解密大量数据,比非对称加密更适合持续的数据传输。
为什么结合二者?
| 加密方式 | 特点 | SSL/TLS 作用 |
|---|---|---|
| 非对称加密(RSA、ECDSA) | 安全但速度慢 | 主要用于 身份认证、密钥交换 |
| 对称加密(AES、ChaCha20) | 速度快但需要密钥 | 主要用于 数据传输 |
- 非对称加密 解决了密钥分发的问题(即如何安全地交换对称密钥)。
- 对称加密 解决了性能问题(即如何高效地传输大量数据)。
TLS1.3
TLS 1.3 的握手过程整体上更简洁、更安全,主要步骤如下:
-
ClientHello 阶段
- 客户端发起:客户端发送一条 ClientHello 消息,其中包括:
- 一个 32 字节的随机数
- 支持的 TLS 版本列表(通过 supported_versions 扩展表明支持 TLS 1.3)
- 客户端支持的密码套件(TLS 1.3 中只支持 AEAD 算法,如 AES_GCM、ChaCha20-Poly1305)
- 关键扩展 key_share:客户端生成一个或多个临时(短暂)椭圆曲线公钥,用于后续的 ECDHE 密钥交换
- 如果进行会话恢复,还会包含 pre_shared_key 和 psk_key_exchange_modes 扩展,表示客户端希望利用之前协商的 PSK 来实现 0-RTT(零往返)或 1-RTT 会话恢复
- 客户端发起:客户端发送一条 ClientHello 消息,其中包括:
-
ServerHello 阶段
- 服务器响应:服务器从 ClientHello 中选择双方都支持的 TLS 版本(确认为 TLS 1.3)和密码套件
- 服务器在 ServerHello 消息中发送自己的 32 字节随机数
- 服务器在 key_share 扩展中提供其临时公钥,与客户端提供的公钥一起通过 ECDHE 算法计算出一个共享密钥
- 如果会话恢复生效,服务器也会在 ServerHello 中包含相应的 pre_shared_key 扩展
-
后续加密握手消息
- 从 ServerHello 之后开始,服务器会使用基于刚刚 ECDHE 共享密钥派生出的握手流量密钥,对后续消息进行加密。这部分消息通常包括:
- EncryptedExtensions:传送一些协商好的扩展(例如 ALPN 等)
- (可选)CertificateRequest:如果服务器需要客户端认证,则请求客户端证书
- Certificate:服务器的数字证书,用于验证服务器身份
- CertificateVerify:服务器使用其私钥对整个握手过程中至此已传输的消息进行数字签名,证明其对证书中公钥的掌控
- Finished:一条基于整个握手消息摘要生成的消息,确保双方握手数据一致
- 从 ServerHello 之后开始,服务器会使用基于刚刚 ECDHE 共享密钥派生出的握手流量密钥,对后续消息进行加密。这部分消息通常包括:
-
客户端验证与反馈
- 客户端使用事先通过 ECDHE 得到的共享密钥派生出相应的解密密钥,解密服务器发送的加密消息
- 客户端验证服务器的证书和 CertificateVerify 消息,确保服务器身份真实可信
- 验证无误后,客户端生成自己的 Finished 消息(也是基于整个握手消息的摘要)并发送给服务器
-
密钥导出与应用数据传输
- 双方基于握手过程中交换的随机数和共享的 ECDHE 秘密,通过 HKDF 分层导出最终的主密钥,然后进一步派生出用于加密应用数据的密钥和初始化向量
- 此后,所有应用数据均使用这些派生出的密钥进行对称加密传输
- TLS 1.3 完整握手:只需要 1 个往返(1-RTT)。客户端发送 ClientHello 后,服务器回复 ServerHello 及后续的加密握手消息,客户端收到并确认后即可开始加密通信。
- TLS 1.2 完整握手:通常需要 2 个往返(2-RTT)。客户端发送 ClientHello 后,服务器依次发送 ServerHello、Certificate、ServerKeyExchange 等消息,再由客户端发送 ClientKeyExchange、ChangeCipherSpec 和 Finished 消息,最后服务器再发送 Finished 消息。
另外,TLS 1.3 支持 0-RTT 模式(在会话恢复时):
- 在 0-RTT 模式下,如果客户端和服务器之前已经建立过会话,客户端可以在发送 ClientHello 后立即发送部分加密的应用数据(称为 early data),从而进一步减少延迟(但这种模式存在重放攻击风险,适用于只读请求等幂等操作)。
OpenSSL命令手册
详细参考:https://www.openssl.net.cn/docs/1.html 和 https://www.cnblogs.com/logchen/p/10840654.html

比如,签发证书:
CA根证书
openssl x509 -req -days 3650 -in rootca.req -signkey rootca.key -out rootca.pem -passin pass:xxxx(私钥带密码的情况) -CAcreateserial
用户证书
openssl x509 -req -in user.req -CA rootca.pem -CAkey rootca.key -out user.pem -passin pass:12345678 v3_req -CAcreateserial -days 3650
生成v3证书,需要加配置文件指定扩展项
-extfile xxx.conf -extensions v3_req
CA根证书是数字证书体系中的核心组成部分,
- 定义:根证书是由顶级**证书颁发机构(Certificate Authority, CA)**自行签发的自签名证书,位于信任链的顶端。它是整个公钥基础设施(PKI)的信任起点。
- 特点:根证书的公钥被预置在操作系统、浏览器或设备的信任存储中(如Windows的受信任根证书颁发机构列表),用于验证其他证书的合法性。
CA根证书的作用:
- 建立信任链:根证书通过签发中间CA证书,形成多层级的信任链。例如:
根证书 → 中间CA证书 → 网站SSL证书
浏览器会逐级验证证书链,最终确认终端证书(如网站证书)是否可信。 - 身份验证与加密:确保通信双方(如用户与服务器)的身份真实性,并为HTTPS、电子邮件加密等场景提供安全保障。
- 防篡改:通过数字签名技术,防止证书内容被伪造或篡改。
- 公开信任的CA:
大多数公司申请的证书(如SSL/TLS证书)是由中间CA证书签发的终端实体证书,而非根证书。公共CA(如DigiCert、Let’s Encrypt)不会直接暴露根证书私钥,而是通过中间层签发证书,以降低根证书泄露的风险。 - 私有PKI场景:
部分大型企业可能自建私有PKI体系,生成私有根证书,用于签发内部系统(如内网、VPN)的证书。但这些私有根证书不会被公共设备(如浏览器)默认信任,需手动导入。 - 自签名证书:
若公司自行生成证书(如用于测试环境),这类证书是自签名的,但不等同于根证书。它们缺乏信任链支持,浏览器会提示“不受信任”。
生成TLS1.3证书
下面给出一个基于 OpenSSL 的示例,生成基于椭圆曲线(prime256v1)的密钥对和自签名证书,该证书默认采用 SHA-256 算法,非常适合 TLS1.3 使用。假设要生成用于域名 xxx.com 的证书,可按下面步骤操作:
# 1. 生成 EC 私钥(prime256v1 曲线推荐用于 TLS1.3)
openssl ecparam -name prime256v1 -genkey -noout -out nginx_tls.key
# 2. 生成自签名证书(有效期 10 年),其中 -subj 参数指定证书的主题信息,这里用的是 xxx.com 作为 Common Name (CN)
openssl req -new -x509 -sha256 -key nginx_tls.key -out nginx_tls.crt -days 3650 -subj "/CN=xxx.com"
生成后,你会得到一个私钥文件(nginx_tls.key)和一个证书文件(nginx_tls.crt),然后你可以在 Nginx 配置中引用它们来启用 HTTPS。
关于域名和子域名的说明:
-
证书绑定域名
在上述例子中,证书的 Common Name 是 xxx.com,这意味着它默认只对该域名有效。如果直接使用这个证书,浏览器在访问 zzz.xxx.com 时会出现域名不匹配的警告。 -
支持子域名的方案
为了让同一证书同时覆盖主域名和其子域名,有以下两种常见做法:-
申请通配符证书:
例如,将证书的 Common Name 设置为 *.xxx.com。这种证书可以覆盖所有子域名(如 zzz.xxx.com、abc.xxx.com 等),但注意通配符证书通常不涵盖根域名(即 xxx.com本身),所以需要确认申请时是否同时支持根域名(通常会在 Subject Alternative Name 中同时列出 xxx.com)。示例生成通配符证书(利用配置文件指定 SAN):
-
创建一个 OpenSSL 配置文件(例如 openssl.cnf):
[ req ] default_md = sha256 prompt = no default_bits = 256 req_extensions = v3_req distinguished_name = dn [ dn ] CN = *.xxx.com [ v3_req ] subjectAltName = @alt_names [ alt_names ] DNS.1 = *.xxx.com DNS.2 = xxx.com -
使用配置文件生成证书:
openssl ecparam -name prime256v1 -genkey -noout -out nginx_wildcard.key openssl req -new -x509 -sha256 -key nginx_wildcard.key -out nginx_wildcard.crt -days 3650 -config openssl.cnf
-
-
在证书中添加 SAN(Subject Alternative Names):
如果你只需为 xxx.com 和一个或几个特定子域名(例如 zzz.xxx.com)申请证书,可以在生成 CSR(证书签名请求)时,在 SAN 中列出所有需要的域名。对自签名证书来说,同样可以利用配置文件来指定:[ req ] default_md = sha256 prompt = no default_bits = 256 req_extensions = v3_req distinguished_name = dn [ dn ] CN = xxx.com [ v3_req ] subjectAltName = @alt_names [ alt_names ] DNS.1 = xxx.com DNS.2 = zzz.xxx.com然后执行:
openssl ecparam -name prime256v1 -genkey -noout -out nginx_multi.key openssl req -new -x509 -sha256 -key nginx_multi.key -out nginx_multi.crt -days 3650 -config openssl.cnf
-
通过以上两种方式,你可以根据实际需求决定是否需要覆盖子域名。总结来说,原先申请的仅针对 xxx.com 的证书是有域名限制的;如果需要支持 zzz.xxx.com,建议使用通配符证书或者在 SAN 中添加子域名,从而让证书在多个域名下都能正常使用。
在上述命令中,我们生成的是一个自签名证书,它同时充当了服务器证书和根证书的角色,因此并没有单独指定或引入一个外部的根证书。在正式的生产环境中,通常的做法是让一个公认的 CA 用其受信任的根证书对你的服务器证书进行签发,从而形成完整的证书链。
关键区别:
-
使用受信任的根证书:
公认的 CA 签发的证书链最终会追溯到一个被广泛预装在浏览器和操作系统信任库中的根证书。这样一来,当用户访问你的网站时,浏览器能自动验证整个证书链,从而建立安全的 HTTPS 连接,不会出现不安全警告。 -
自签名根证书:
如果你自签发一个根证书(或者像上面那样生成自签名证书),虽然技术上可以完成加密通信,但由于该根证书不在浏览器或操作系统的默认信任列表中,客户端就会认为这个证书是不可信的,从而显示“连接不安全”或类似的警告。只有在你手动将这个自签发的根证书导入到每个客户端的信任库中,才能避免这种警告,但这通常只适用于内部或测试环境。
Python ssl问题
urllib3.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:992)问题
sslv3 alert handshake failure 错误通常表示在 SSL/TLS 握手过程中出现了问题,具体来说是由于 SSLv3 协议的使用导致的。这个错误的源头可以从多个方面进行分析,尤其是从 requests 包的角度来看。以下是可能导致该错误的原因及其详细分析:
- SSL/TLS 协议版本不匹配
-
原因:
- 客户端(如
requests)和服务器之间的 SSL/TLS 协议版本不匹配。服务器可能不支持 SSLv3,而客户端尝试使用 SSLv3 进行连接。
- 客户端(如
-
解决方案:
- 确保
requests使用的是 TLS 1.2 或更高版本。可以通过更新requests和urllib3库来确保使用最新的协议。
- 确保
- 服务器配置问题
-
原因:
- 服务器可能配置为不支持 SSLv3,或者仅支持较旧的协议版本(如 SSLv3),而客户端使用的是较新的协议版本。
-
解决方案:
- 检查服务器的 SSL/TLS 配置,确保它支持 TLS 1.2 或 TLS 1.3,并且没有禁用这些协议。
- 客户端配置问题
-
原因:
requests库可能被配置为使用 SSLv3,或者在某些情况下,底层的urllib3库可能会尝试使用 SSLv3。
-
解决方案:
- 确保在代码中没有强制使用 SSLv3。可以通过设置
verify参数为True来确保使用默认的安全设置。
- 确保在代码中没有强制使用 SSLv3。可以通过设置
- 证书问题
-
原因:
- SSL/TLS 握手过程中,证书验证失败可能导致握手失败。虽然这通常会导致不同的错误,但在某些情况下,可能会导致握手失败。
-
解决方案:
- 确保服务器的 SSL 证书有效且未过期,并且客户端能够正确验证该证书。
- 加密套件不匹配
-
原因:
- 客户端和服务器之间的加密套件不匹配。服务器可能不支持客户端请求的加密套件。
-
解决方案:
- 检查并确保客户端和服务器都支持相同的加密套件。可以通过设置
requests的ciphers参数来指定使用的加密套件。
- 检查并确保客户端和服务器都支持相同的加密套件。可以通过设置
我们可以通过:https://www.ssllabs.com/ssltest来查询一个网站支持的加密套件版本:

经过对比,发现用urllib3 == 1.26.5可以请求成功,urllib3 == 2.0.7 报错 sslv3 握手失败。所以最少降级 urllib3 的版本是可以解决的,但是终究不是长久之计。
在网上找了良久得到的解决方案:
class TLSAdapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
context = ssl.create_default_context()
context.check_hostname = False
# 降低安全级别以兼容旧服务器
# Python 3.10 增加了 TLS 堆栈的默认安全设置,其中包括禁止任何仍然使用 RSA 密钥交换的密码。
# 一些服务器仍然需要这种过时的密钥交换
context.set_ciphers("DEFAULT")
kwargs['ssl_context'] = context
return super().init_poolmanager(*args, **kwargs)
def __request(method, url, **kwargs) -> Response:
with Session() as session:
session.mount("https://", TLSAdapter())
return session.request(method=method, url=url, **kwargs)
InsecureRequestWarning警告
# 第一种方法,
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# 第二种方法
import requests
requests.packages.urllib3.disable_warnings()
response = requests.get(url, verify=False)
在 requests 包中,verify=False 用于控制是否验证 SSL 证书的有效性。它的适用场景和开启/禁用的影响如下:
-
适用场景:
-
verify=True(默认开启 SSL 证书验证):- 适用于生产环境、大多数安全要求严格的场景。
- 确保请求的服务器使用的是可信的 SSL 证书,防止中间人攻击(MITM)。
- 适用于访问 HTTPS 站点时需要安全性保证的情况。
-
verify=False(禁用 SSL 证书验证):- 适用于测试环境或调试场景,比如:
- 访问自签名证书的服务器。
- 访问内部测试服务器(没有有效的 CA 证书)。
- 需要快速测试 API 调用,不关心安全性。
- 用于抓包分析 HTTPS 流量(比如使用 Charles、Burp Suite 等代理软件)。
- 适用于测试环境或调试场景,比如:
-
-
verify选项的影响:-
verify=True(默认,启用 SSL 证书验证)requests会使用本机 CA 证书来验证服务器的 SSL 证书。- 如果服务器的证书无效、过期、或是自签名证书,则请求会抛出
SSLError,比如:requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed - 适用于访问可信的 HTTPS 网站,确保通信安全。
-
verify=False(禁用 SSL 证书验证)requests不会检查服务器的 SSL 证书,无论证书是否合法,都会进行请求。- 可能会导致安全风险,比如:
- 可能遭受中间人攻击(MITM),导致数据泄露或篡改。
- 可能连接到伪造的网站,而不自知。
- Python 会发出 InsecureRequestWarning,提示你这样做不安全:
InsecureRequestWarning: Unverified HTTPS request is being made.
-
-
如何正确使用
verify- 推荐的做法:
- 在生产环境中,始终保持
verify=True,确保通信安全。 - 如果遇到证书问题:
- 使用可信的 CA 签发证书,避免自签名证书。
- 提供 CA 证书文件,用
verify="path/to/cert.pem"方式指定正确的证书:requests.get("https://example.com", verify="/path/to/cert.pem") - 如果必须禁用 SSL 证书验证(如调试环境),可忽略警告:
import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) requests.get("https://example.com", verify=False)
- 在生产环境中,始终保持
- 推荐的做法:
本地 CA 证书的作用是 验证服务器证书是否由受信任的 CA 机构签发。当你访问 HTTPS 网站时,本地的 CA 证书用于检查服务器证书是否可信:
- 服务器提供自己的证书(包括公钥)。
- 本地计算机检查该证书是否由受信任的 CA 签署。
- 如果该 CA 在本地的 受信任 CA 证书存储 中,则连接被认为是安全的。
- 如果 CA 不被信任(例如自签名证书),则连接可能会失败,抛出
SSL: CERTIFICATE_VERIFY_FAILED错误。
本地 CA 证书的来源:大多数操作系统和浏览器都内置了一组 受信任的 CA 证书,这些 CA 由官方机构(如 Mozilla、Microsoft、Apple)维护。
- Windows:存储在 证书管理器(
certmgr.msc)。 - Linux:通常存储在
/etc/ssl/certs/或/etc/pki/tls/certs/。 - macOS:使用 钥匙串访问(Keychain Access) 管理证书。
Python 的 requests 模块默认使用 certifi 提供的 CA 证书,它是一个受 Mozilla 维护的证书列表,文件路径通常是:
import certifi
print(certifi.where()) # 查看 requests 使用的 CA 证书路径
服务器证书 vs. 本地 CA 证书
| 类别 | 存储位置 | 作用 |
|---|---|---|
| 服务器证书 | 部署在 Web 服务器(如 Nginx、Apache)上 | 证明服务器身份 |
| 本地 CA 证书 | 存储在操作系统或 Python (certifi) | 验证服务器证书是否合法 |
如何让服务器证书被本地信任?
如果你的服务器使用 自签名证书,你需要手动让本地信任它:
- 将自签名证书添加到本地 CA 存储(适用于 Linux/macOS/Windows)。
- 在
requests中指定证书路径:requests.get("https://yourserver.com", verify="/path/to/server_cert.pem")
CA机构
目前全球有很多 受信任的 CA(Certificate Authority)机构,它们负责签发 SSL/TLS 证书,确保网站和用户之间的通信安全。
以下 CA 机构被广泛信任,并且它们的根证书已被主流操作系统和浏览器(Chrome、Firefox、Edge、Safari)默认信任:
(1) 全球主要商业 CA
| CA 机构 | 特点 | 官网 |
|---|---|---|
| DigiCert | 全球最大 CA 之一,支持 OV/EV 证书 | digicert.com |
| Sectigo(原 Comodo CA) | 提供 DV/OV/EV 证书,市场份额大 | sectigo.com |
| GlobalSign | 企业级 CA,提供代码签名证书 | globalsign.com |
| Entrust | 提供 SSL/TLS 和身份验证服务 | entrust.com |
| GoDaddy | 域名注册商,也提供 SSL 证书 | godaddy.com |
(2) 免费 SSL 证书提供商
以下 CA 机构提供 免费的 SSL 证书,它们是真实可信的,并且已经被主流浏览器信任:
| CA 机构 | 特点 | 官网 |
|---|---|---|
| Let’s Encrypt | 最著名的免费 SSL 证书提供商,由 ISRG 运营 | letsencrypt.org |
| ZeroSSL | 提供免费 DV 证书(90 天),支持 ACME | zerossl.com |
| Buypass | 提供免费 SSL 证书(180 天有效期) | buypass.com |
💡 免费 CA 机构是否可信?
是的,像 Let’s Encrypt 和 ZeroSSL 已经被 Chrome、Firefox、Safari 等浏览器默认信任,和付费 CA 的 DV 证书一样安全,但功能有限:
- 仅支持 DV(域验证)证书,不提供 OV/EV 证书。
- 有效期较短(通常 90 天),需要定期续期(可用 ACME 自动化)。
- 不提供企业级担保(商业 CA 可能提供保险赔偿)。
推荐:如果你是个人站长或小型网站,完全可以使用 Let’s Encrypt 或 ZeroSSL 来免费获取 SSL 证书。
如何判断一个 CA 是否真实可信?
要确认某个 CA 是否可信,可以使用以下方法:
方法 1:检查浏览器信任
在 Chrome 或 Firefox 中查看某个网站的证书:
- 访问网站(如
https://example.com)。 - 点击地址栏的 🔒 锁🔒 图标 → 查看证书。
- 查看证书签发者(Issuer),比如:
Issued by: Let's Encrypt
如果证书由 Let’s Encrypt、DigiCert、GlobalSign 等知名 CA 签发,说明可信。
方法 2:查询 CA/B 论坛信任列表
CA/B Forum(CA/Browser Forum)是全球管理证书信任的组织,所有受信任的 CA 机构都必须在其列表中注册。
✅ 查询方法:
- Mozilla 信任的 CA 列表:Mozilla CA Certificates
- Microsoft 信任的 CA 列表:Microsoft Trusted Root Program
如果某个 CA 不在这些列表中,那么它可能是不可信的。
方法 3:查询官方证书透明度(CT)日志
证书透明度(Certificate Transparency, CT)日志可以用来验证某个 CA 是否真的签发了证书。
✅ 查询方法:
- Google Chrome CT 日志:Google Transparency Report
- Let’s Encrypt 证书查询:crt.sh
只需输入域名,即可查看该网站的证书信息。如果证书签发机构是可信 CA,说明该证书是合法的。
付费 CA vs. 免费 CA,应该选哪种?
| 对比项 | 免费 CA(如 Let’s Encrypt) | 付费 CA(如 DigiCert) |
|---|---|---|
| 证书类型 | 仅支持 DV 证书 | 支持 DV/OV/EV 证书 |
| 有效期 | 最长 90 天(需续期) | 1 年或以上 |
| 自动续期 | ✅ 支持 ACME 自动化 | ❌ 需手动续期(部分支持 API) |
| 担保/保险 | ❌ 无 | ✅ 提供赔偿($100,000+) |
| 价格 | 免费 | $10 - $1000+ |
| 适用场景 | 个人博客、小型网站 | 企业、银行、电商、政府网站 |
✅ 适合使用 Let’s Encrypt 的情况:
- 个人网站、博客、API、测试服务器。
- 你不需要 OV/EV 认证,只需要 HTTPS 加密。
✅ 适合使用付费 CA 的情况:
- 企业网站、电商、金融服务(需要 OV/EV 证书)。
- 大型公司(需要强担保和扩展功能,如 S/MIME、代码签名)。
免费 SSL 证书(如 Let’s Encrypt)和付费 SSL 证书(如 DigiCert、GlobalSign)在 加密强度 上是相同的,但功能和适用场景不同。主要区别体现在身份认证级别、有效期、担保金额、技术支持等方面。
免费 SSL vs. 付费 SSL 功能对比
| 功能 | 免费 SSL 证书(如 Let’s Encrypt) | 付费 SSL 证书(如 DigiCert) |
|---|---|---|
| 加密强度 | ✅ 相同(支持 256 位加密 + TLS 1.2/1.3) | ✅ 相同 |
| 证书类型 | ❌ 仅支持 DV(域名验证) | ✅ 支持 DV/OV/EV |
| 身份验证 | ✅ 仅验证域名所有权 | ✅ 可验证公司/企业身份(OV/EV) |
| 有效期 | ⏳ 最多 90 天(需频繁续期) | ✅ 最长 1-2 年 |
| 自动续期 | ✅ 支持 ACME 自动续期 | ❌ 需要手动更新(部分提供 API) |
| 担保赔偿 | ❌ 无 | ✅ 高达 $1,000,000+ |
| 技术支持 | ❌ 无(社区支持) | ✅ 24/7 客服支持 |
| 子域名支持 | ✅ 部分支持 Wildcard 证书 | ✅ 支持 |
| 适用场景 | 个人网站、小型博客 | 企业、银行、电商、政府机构 |
主要区别解析
(1) 证书类型
SSL 证书分为三种类型:
- DV(域名验证,Domain Validation) ✅ 免费 SSL 仅支持
- OV(组织验证,Organization Validation) ❌ 免费 SSL 不支持
- EV(扩展验证,Extended Validation) ❌ 免费 SSL 不支持
| 类型 | 验证要求 | 适用场景 | 免费 SSL(Let’s Encrypt)支持吗? |
|---|---|---|---|
| DV 证书 | 仅验证域名所有权(无需提供企业信息) | 个人网站、博客、小型业务 | ✅ 支持 |
| OV 证书 | 需要企业身份验证(公司信息、营业执照) | 企业网站、B2B 平台 | ❌ 不支持 |
| EV 证书 | 需要严格的公司审核(法律实体、财务信息) | 银行、电商、大型企业 | ❌ 不支持 |
✅ 免费 SSL 证书仅支持 DV 类型,适用于个人网站、小型企业。
❌ 付费 SSL 证书支持 OV/EV,可用于政府、金融、电商等需要验证企业身份的场景。
(2) 证书有效期
- 免费 SSL 证书有效期仅 90 天,需要频繁续期(可用 ACME 自动化)。
- 付费 SSL 证书有效期可达 1-2 年,减少续期管理成本。
💡 免费证书需要自动化续期(如 Certbot),否则可能导致 HTTPS 失效!
(3) 担保赔偿
- 免费 SSL 证书没有担保(如果证书被滥用,你无法索赔)。
- 付费 SSL 证书提供保险:
- DV 证书:$10,000-$100,000 赔偿
- OV 证书:$100,000-$500,000 赔偿
- EV 证书:$1,000,000+ 赔偿
✅ 如果你的网站涉及敏感数据(金融、交易),建议使用付费 SSL,避免法律风险。
(4) 技术支持
- 免费 SSL 证书没有官方支持,遇到问题只能查文档或去论坛提问(如 Let’s Encrypt 社区)。
- 付费 SSL 证书提供 24/7 技术支持,有问题可以直接联系 CA 机构客服。
✅ 企业级网站通常需要有 SLA(服务级别协议),这时付费 SSL 更可靠!
(5) Wildcard 证书(通配符证书)
| 功能 | 免费 SSL(Let’s Encrypt) | 付费 SSL(DigiCert 等) |
|---|---|---|
| 支持通配符(Wildcard) | ✅ 支持(仅 DV) | ✅ 支持(DV/OV) |
| 泛域名格式 | *.example.com | *.example.com |
| 适用场景 | 个人网站、小型企业 | 企业、托管服务商 |
💡 Let’s Encrypt 支持 Wildcard 证书,但需要 DNS-01 方式验证(不能用 HTTP 方式验证)。
付费 Wildcard 证书支持 OV/EV,可用于企业级业务。
申请免费SSL证书
Python 也可以安装和使用 Certbot!Certbot 是一个 Python 编写的 ACME 客户端,可以通过 pip 安装并运行,但官方推荐使用 snap 或 OS 包管理器(如 apt、yum)来安装。(ACME(Automatic Certificate Management Environment) 是一个自动化 SSL 证书申请、验证、颁发和续期的协议。ACME 服务器(ACME Server) 就是支持 ACME 协议的 证书颁发机构(CA),它负责处理 SSL/TLS 证书的自动化管理。)
Let’s Encrypt 官方推荐 Certbot 作为自动化工具,支持一键申请和自动续期。
sudo yum install snapd
sudo systemctl enable --now snapd.socket
sudo ln -s /var/lib/snapd/snap /snap
使用snapd安装certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
生成证书(需要指定nginx)
certbot certonly --nginx --nginx-ctl /usr/local/nginx/sbin/nginx --nginx-server-root /usr/local/nginx/conf
这里的certonly就是只下载对应文件,不进行配置nginx,适用于自己配置或者更新使用。去掉则会帮你进行配置nginx(我没有试用)。
执行上面的命令后,程序会让你确认你的邮箱和你的域名,确认完成后会将证书文件生成在指定目录中。
certbot certonly --nginx --nginx-ctl /usr/local/nginx/sbin/nginx --nginx-server-root /usr/local/nginx/conf
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): [这里输入你的邮箱]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y [选Y 继续]
Account registered.
Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: whrss.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): [这里不需要输入,回车选所有]
Requesting a certificate for whrss.com
Successfully received certificate.
Certificate is saved at:
# [这里告诉我们生成的文件路径和有效期]
/etc/letsencrypt/live/whrss.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/whrss.com/privkey.pem
This certificate expires on 2023-03-02.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
http2 nginx配置:
server {
listen 443 ssl http2; # 启用 HTTP/2(基于 TCP)
listen [::]:443 ssl http2; # 兼容 IPv6
server_name whrss.com www.whrss.com;
ssl_certificate /etc/letsencrypt/live/whrss.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/whrss.com/privkey.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/html;
index index.html;
# 提供静态文件
location / {
try_files $uri $uri/ /index.html;
}
# API 反向代理
location /api/v1/ {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Via "nginx";
}
# 静态资源缓存优化
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|mp4|webp|avif)$ {
expires 6M;
access_log off;
add_header Cache-Control "public, max-age=15552000";
}
}
server {
listen 80;
listen [::]:80;
server_name whrss.com www.whrss.com;
return 301 https://$host$request_uri;
}
HTTP/3 nginx配置:
server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport; # 启用 HTTP/3(基于 QUIC + UDP)
listen [::]:443 quic reuseport;
http3 on;
quic_retry on;
server_name whrss.com www.whrss.com;
ssl_certificate /etc/letsencrypt/live/whrss.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/whrss.com/privkey.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.3; # HTTP/3 仅支持 TLS 1.3
ssl_prefer_server_ciphers on;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256';
# HTTP/3 相关头
add_header Alt-Svc 'h3=":443"; ma=86400'; # 浏览器优先使用 HTTP/3
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/html;
index index.html;
# 提供静态文件
location / {
try_files $uri $uri/ /index.html;
}
# API 反向代理
location /api/v1/ {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Via "nginx";
}
# 静态资源缓存优化
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|mp4|webp|avif)$ {
expires 6M;
access_log off;
add_header Cache-Control "public, max-age=15552000";
}
}
server {
listen 80;
listen [::]:80;
server_name whrss.com www.whrss.com;
return 301 https://$host$request_uri;
}
申请免费域名
大多数域名注册商都需要付费(如 .com、.net、.org 需要购买)。但以下提供免费域名:
📌 1️⃣ Freenom(提供免费 .tk、.ml、.ga、.cf、.gq 域名)
✅ 官网:https://www.freenom.com/
✅ 支持 .tk、.ml、.ga、.cf、.gq 免费注册
✅ 可以用于 Let’s Encrypt 申请 SSL
❌ 可能会回收域名(如果流量大,Freenom 可能收回你的域名)
📌 2️⃣ EU.org(免费二级域名)
✅ 官网:https://www.eu.org/
✅ 提供 yourname.eu.org 域名
✅ 永久免费,不会回收
❌ 需要手动申请,审核较慢(1-2 周)
📌 3️⃣ InfinityFree(免费二级域名)
✅ 官网:https://www.infinityfree.net/
✅ 提供 yourname.rf.gd、yourname.epizy.com 二级域名
✅ 支持 Let’s Encrypt
❌ 仅适用于测试或小型项目(部分 IP 可能被封)
🎯结合免费域名 + 免费 SSL 搭建 HTTPS 网站,如果你想 完全免费 搭建一个 HTTPS 网站,可以这样做:
- 注册免费域名(推荐 Freenom 或 EU.org)。
- 使用 Cloudflare 免费 CDN(提供 HTTPS 代理)。
- 在服务器上安装 Let’s Encrypt(自动配置 SSL)。
- 用 Certbot 自动续期,保持证书不过期。
| 免费服务 | 提供内容 | 推荐指数 |
|---|---|---|
| Let’s Encrypt | 免费 SSL 证书(90 天,自动续期) | ⭐⭐⭐⭐⭐ |
| Freenom | .tk、.ml、.ga、.cf、.gq 免费域名 | ⭐⭐⭐ |
| EU.org | .eu.org 免费域名(永久有效) | ⭐⭐⭐⭐⭐ |
| ZeroSSL | 可视化免费 SSL(90 天) | ⭐⭐⭐⭐ |
👉 如果你想要一个免费 HTTPS 站点,推荐:
- 域名:Freenom / EU.org
- SSL:Let’s Encrypt(Certbot 自动化)
🚀 这样,你可以 0 成本 搭建 HTTPS 站点! 💯
OpenSSH
- OpenSSH 是使用 SSH 协议进行远程登录的连接工具。 它加密所有通信讯息以消除窃听、连接劫持。 此外,OpenSSH 提供了大量的安全隧道功能、多种身份验证方法和复杂的配置选项。
- OpenSSH 包含的组件如下:
(1)ssh:OpenSSH 远程登录客户端,作为 rlogin 和 Telnet 的替代方案。
(2)scp:OpenSSH 安全文件复制,作为 rcp 的替代方案,将文件复制到其他电脑上。
(3)sftp:OpenSSH 安全文件传输,类似于 scp。
(4)sshd:OpenSSH 守护进程。
(5)ssh-keygen:OpenSSH 身份验证密钥实用程序,产生RSA或ECDSA密钥,用来认证用。
(6)ssh-agent:OpenSSH 身份验证代理,用于帮助用户不需要每次都要输入密钥的工具。
(7)ssh-add:向 OpenSSH 身份验证代理添加私钥身份,用于帮助用户不需要每次都要输入密钥的工具。
(8)ssh-keyscan:从服务器收集 SSH 公钥,并记录公钥。
在 Linux 系统上 SSH 是非常常用的工具,通过 SSH Client 我们可以连接到运行了 SSH Server 的远程机器上。SSH Client 的基本使用方法是:
ssh user@remote -p port
执行 ssh-keygen 即可生成 SSH 钥匙,一路回车即可。
local$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:47VkvSjlFhKRgz/6RYdXM2EULtk9TQ65PDWJjYC5Jys user@local
The key's randomart image is:
+---[RSA 2048]----+
| ...o...X+o|
| . o+ B=Oo|
| .....ooo*=|
| o+ooo.+ .|
| .SoXo. . |
| .E X.+ . |
| .+.= . |
| .o |
| |
+----[SHA256]-----+
这段话告诉了我们,生成的公钥放在了 ~/.ssh/id_rsa.pub,私钥放在了 ~/.ssh/id_rsa。
- OpenSSH常常被误认以为与OpenSSL有关联,但实际上这两个计划有不同的目的,不同的发展团队,名称相近只是因为两者有同样的软件发展目标──提供开放源代码的加密通讯软件。
- OpenSSH是SSH协议的具体实现、OpenSSL是SSL与TSL的具体实现。OpenSSH 与OpenSSL只是名字相似但是关联不大,同样软件发展目标是为提供开放源代码的加密通讯软件。而生成非对称公私钥的方式有很多,如OpenSSH 、OpenSSL与GnuPG。
本文介绍了OpenSSL和OpenSSH两个开源项目的核心功能与应用场景,包括非对称加密的实现方式、SSH协议的工作原理以及SSL/TLS协议的区别与重要性。
804

被折叠的 条评论
为什么被折叠?



