卷曲命令是一种发出网络请求的工具,它在通过 HTTPS 与安全服务器通信时使用 SSL/TLS。
默认情况下,curl
尝试在可用时使用安全连接,但了解如何控制和诊断这些连接至关重要。
使用客户端证书
您可以使用--cert
当您需要使用 SSL 客户端证书向远程服务器进行身份验证时,请选择此选项。
客户端证书是向服务器确认客户端身份的一种方式。它在仅需要用户名和密码来提高安全性的设置中特别有用。
curl --cert /path/to/certificate.pem:password https://secure.example.com
Output:
* Trying 192.168.1.10...
* TCP_NODELAY set
* Connected to secure.example.com (192.168.1.10) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
接下来的几行是 SSL/TLS 握手过程的详细细分,其中包括正在使用的协议版本(在本例中为 TLSv1.3)和其他相关元数据。
当服务器响应“HTTP/1.1 200 OK”时,表示连接和数据传输成功。
如果证书受密码保护,则在冒号后提供密码。
指定证书类型
curl
在自动检测正确类型方面做得非常出色,但有时您需要显式指定证书类型。
curl --cert /path/to/certificate.der --cert-type DER https://secure.example.com
这个命令告诉curl
连接时使用 DER 格式的客户端证书secure.example.com
.
Output:
* Trying 192.168.1.11...
* TCP_NODELAY set
* Connected to secure.example.com (192.168.1.11) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
在这里,--cert
选项指向客户端证书的位置。在本例中,它是 DER 编码的证书。
选项--cert-type DER
tells curl
所提供的客户端证书属于 DER 类型。
虽然 PEM 是默认(也是最常见)格式,但 DER 是 PEM 的二进制形式,用于特定环境。
使用私钥
私钥与证书一起使用,向服务器证明客户端的身份,而无需泄露密钥本身。
curl --cert /path/to/certificate.pem --key /path/to/privatekey.pem https://secure.example.com
该命令指示curl
连接时使用客户端证书及其关联的私钥secure.example.com
.
随着--key
选项,你正在指挥curl
到与客户端证书对应的私钥的位置。
请记住,虽然客户端证书是公开的并且可以共享,但私钥必须保密。
如果恶意行为者获得了私钥的访问权限,他们就可以在 SSL/TLS 通信中冒充证书所有者。
指定私钥类型
您可以显式指定私钥的类型以避免任何歧义。
curl --cert /path/to/certificate.pem --key /path/to/privatekey.der --key-type DER https://secure.example.com
该命令发出信号curl
在建立连接时使用 DER 格式的客户端证书及其关联的私钥secure.example.com
.
指定 CA 捆绑包
信任远程服务器需要信任的基础。该基础通常基于证书颁发机构 (CA) 的证书。
在许多系统中,默认情况下都有一组预定义的受信任 CA 证书。
但是,有时您需要使用自定义或私有 CA,或者只想指定不同的 CA 捆绑包。curl
提供--cacert
此类情况的选项。
curl --cacert /path/to/ca-bundle.crt https://custom-ca.example.com
在这里,你讲述的是curl
连接到时使用特定的 CA 捆绑包来验证服务器的证书custom-ca.example.com
.
Output:
* Trying 192.168.1.14...
* TCP_NODELAY set
* Connected to custom-ca.example.com (192.168.1.14) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /path/to/ca-bundle.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
在此输出中,curl
正在建立安全连接custom-ca.example.com
,并且它利用提供的 CA 捆绑包在 SSL/TLS 握手期间验证服务器的证书。
分解命令的主要元素:
The --cacert /path/to/ca-bundle.crt
选项指定 CA 捆绑包的路径curl
应该使用。 CA 捆绑包包含一个或多个 CA 证书,curl
会信任。
多个 CA 证书的目录
如果您有多个 CA 证书,将它们全部合并到一个 CA 捆绑文件中是不切实际的。
相反,您应该将每个 CA 证书保存在其自己的文件中并指向curl
到所有这些证书所在的目录。这就是--capath
选项进来了。
curl --capath /path/to/ca-directory/ https://multi-ca.example.com
通过这个命令,curl
连接时将使用指定的目录来验证服务器的证书multi-ca.example.com
.
Output:
* Trying 192.168.1.15...
* TCP_NODELAY set
* Connected to multi-ca.example.com (192.168.1.15) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: /path/to/ca-directory/
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
从输出中可以看到curl
建立安全连接multi-ca.example.com
。值得注意的是,在 SSL/TLS 握手期间,它利用指定目录中的 CA 证书来验证服务器的证书。
使用证书吊销列表
证书吊销列表 (CRL) 是通常由证书颁发机构 (CA) 维护的证书列表,这些证书在到期日期之前已被吊销,不应再受信任。
如果私钥被泄露或证书被错误颁发,则会被放置在 CRL 中。curl
提供使用 CRL 的选项来确保它不信任已吊销的证书。
curl --crlfile /path/to/crlfile.pem https://revoked-cert.example.com
在此命令中,curl
在与服务器建立连接之前,使用给定的 CRL 来验证服务器的证书未被吊销revoked-cert.example.com
.
Output:
* Trying 192.168.1.16...
* TCP_NODELAY set
* Connected to revoked-cert.example.com (192.168.1.16) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* Certificate did not match CRL
* Closing connection 0
* SSL certificate problem: certificate has been revoked
curl: (60) SSL certificate problem: certificate has been revoked
从这个输出来看,curl
尝试安全连接revoked-cert.example.com
.
在 SSL/TLS 握手期间,它检测到服务器的证书与提供的 CRL 上的条目匹配,因此连接被终止。
公钥固定
通过“固定”公钥,您可以明确定义客户端在建立安全连接时应期望使用哪个公钥或一组密钥。
这可以降低利用流氓证书进行中间人 (MitM) 攻击的风险,即使这些证书是由受信任的 CA 颁发的。
curl --pinnedpubkey /path/to/pubkey.pem https://pinned-server.example.com
通过这个命令,curl
只会信任到的连接pinned-server.example.com
如果服务器的公钥与提供的固定密钥匹配。
Output:
* Trying 192.168.1.17...
* TCP_NODELAY set
* Connected to pinned-server.example.com (192.168.1.17) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* SSL certificate problem: public key does not match pinned public key
* Closing connection 0
curl: (60) SSL certificate problem: public key does not match pinned public key
在此示例输出中,curl
正在尝试创建安全连接pinned-server.example.com
.
然而,在 SSL/TLS 握手期间,它发现服务器的公钥与中提供的公钥不匹配pubkey.pem
,导致连接终止。
选择特定的密码套件
有时,出于安全或兼容性原因,您想要指定哪些密码套件curl
建立连接时应该使用(或避免)。
The --ciphers
选项允许您制定此规范。
curl --ciphers 'ECDHE-RSA-AES128-GCM-SHA256' https://cipher-specific.example.com
通过执行这个命令,curl
将尝试使用ECDHE-RSA-AES128-GCM-SHA256
建立安全连接时的密码套件cipher-specific.example.com
.
Output:
* Trying 192.168.1.18...
* TCP_NODELAY set
* Connected to cipher-specific.example.com (192.168.1.18) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.3 / ECDHE-RSA-AES128-GCM-SHA256
...
< HTTP/1.1 200 OK
...
输出表明curl
已建立安全连接cipher-specific.example.com
使用指定的密码套件。
可以列出多个用冒号分隔的密码套件,从而允许curl
根据服务器支持使用其中任何一个。
强制 TLS 版本
在某些情况下,由于服务器要求、测试需要或安全策略,希望强制使用特定版本的 TLS。
你可以强制curl
使用特定版本的 TLS。这可以帮助确定是否有特定版本导致问题:
- 对于 TLS 1.0:
curl --tlsv1.0 https://example.com
- 对于 TLS 1.1:
curl --tlsv1.1 https://example.com
- 对于 TLS 1.2:
curl --tlsv1.2 https://example.com
- 对于 TLS 1.3:
curl --tlsv1.3 https://example.com
TLS 1.3 是最新版本,与之前的版本相比,引入了各种改进和安全增强功能。
设置允许的最大 TLS 版本
虽然使用最新版本来增强安全性通常是一个好主意,但在某些情况下,您需要限制最大 TLS 版本,无论是出于兼容性、测试还是过渡原因。curl
提供--tls-max
定义此上限的选项。
curl --tls-max 1.2 https://tls-specific.example.com
该命令指示curl
连接到tls-specific.example.com
最多使用 TLS 1.2 版本,即使客户端和服务器都支持更高版本。
Output:
* Trying 192.168.1.19...
* TCP_NODELAY set
* Connected to tls-specific.example.com (192.168.1.19) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.2 / [Cipher Suite]
...
< HTTP/1.1 200 OK
...
从这个输出可以明显看出curl
已成功建立安全连接tls-specific.example.com
但将使用 TLS 版本 1.2,即使版本 1.3 或任何更新版本可用且受支持。
恢复先前的 TLS 会话
通过重用先前连接中的会话参数,您可以跳过部分握手过程,从而缩短连接时间。
curl
提供--tls-session
为此目的,可以选择利用先前会话的会话 ID。
curl --tls-session /path/to/session-id-file https://session-resume.example.com
Here, curl
将尝试恢复之前的 TLS 会话session-resume.example.com
使用存储在的会话详细信息session-id-file
.
Output:
* Trying 192.168.1.20...
* TCP_NODELAY set
* Connected to session-resume.example.com (192.168.1.20) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.3 / [Cipher Suite]
* Session resumption (using session ID)
...
< HTTP/1.1 200 OK
...
输出显示curl
成功连接到session-resume.example.com
并根据提供的会话 ID 恢复 TLS 会话,从而可能加快连接设置速度。
但是,要使会话恢复正常工作,客户端和服务器都必须支持它并且具有兼容的会话详细信息。
执行 TLS 身份验证
除了服务器提供其证书(如传统 SSL 中一样)之外,客户端还提供服务器验证的证书。
curl
支持这种扩展的安全形式--tlsauthtype
选项允许您指定要执行的 TLS 身份验证的类型。
curl --cert /path/to/client-cert.pem --key /path/to/client-key.pem --tlsauthtype SRP --tlsuser 'tlsusername' --tlspassword 'tlspassword' https://mutual-auth.example.com
在这个例子中,curl
将尝试连接到mutual-auth.example.com
使用安全远程密码 (SRP) 类型的 TLS 身份验证,同时还提供客户端证书和密钥。
Output:
* Trying 192.168.1.21...
* TCP_NODELAY set
* Connected to mutual-auth.example.com (192.168.1.21) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.3 / [Cipher Suite]
* Server certificate:
* ...
* Client certificate:
* ...
* TLS SRP authentication successful
...
< HTTP/1.1 200 OK
...
输出展示了使用 SRP 成功进行的相互身份验证。服务器和客户端的证书都经过验证,确保已建立的连接具有更高级别的信任。
The --tlsuser
and --tlspassword
选项允许您提供用于 TLS 身份验证的用户名和密码。
需要 SSL/TLS
The --ssl-reqd
选项中curl
确保仅在使用 SSL/TLS 时才建立连接。
curl --ssl-reqd https://secure-only.example.com
Output:
* Trying 192.168.1.24...
* TCP_NODELAY set
* Connected to secure-only.example.com (192.168.1.24) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.3 / [Cipher Suite]
...
< HTTP/1.1 200 OK
...
输出确认连接成功secure-only.example.com
通过 SSL/TLS 加密通道。
尝试升级到 SSL/TLS
在连接启动时未加密但能够升级到安全 SSL/TLS 连接的情况下,--ssl
选项中curl
发挥作用。
使用时,curl
将尝试升级连接以使用 SSL/TLS 加密,即使初始握手未加密,您也能享受安全通道的好处。
curl --ssl http://try-ssl.example.com
Output:
* Trying 192.168.1.25...
* TCP_NODELAY set
* Connected to try-ssl.example.com (192.168.1.25) port 80 (#0)
* Issuing SSL/TLS upgrade request...
* Successfully upgraded to SSL/TLS
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
从该输出中,您可以看到连接最初在端口 80(标准 HTTP 端口)上启动,然后发出 SSL/TLS 升级请求。
然后,连接已成功升级为 SSL/TLS 加密通道。
The --ssl
选项是一个强大的工具,特别是在与支持“升级”标头的服务器交互时,允许从不安全连接过渡到安全连接。
禁用证书吊销检查
证书吊销是一项安全功能,其中被认为不可靠(由于泄露、过期或其他原因)的证书在其实际过期日期之前失效。
但是,在某些情况下,尤其是在测试或受控环境中,您希望禁用这些检查。
In curl
, the --ssl-no-revoke
选项允许这样做,但您应该谨慎使用它。
curl --ssl-no-revoke https://revocation-test.example.com
该命令指示curl
连接时忽略证书吊销检查revocation-test.example.com
.
Output:
* Trying 192.168.1.27...
* TCP_NODELAY set
* Connected to revocation-test.example.com (192.168.1.27) port 443 (#0)
* WARNING: Certificate revocation checks disabled!
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
< HTTP/1.1 200 OK
...
输出显示一条警告,表明证书吊销检查已被禁用。
常见 SSL/TLS 错误故障排除
本节将指导您解决使用时可能遇到的一些常见 SSL/TLS 错误curl
并提供解决方案来解决这些问题。
Curl 错误 SSL 验证失败
这意味着无法根据已知的证书颁发机构 (CA) 验证服务器提供的证书,或者可能存在与 SSL 证书相关的其他问题。
以下是一些潜在原因以及解决方法:
-
过期证书:服务器提供的 SSL 证书已过期。
-
自签名证书:该证书是自签名的,不是由已知的证书颁发机构颁发的。
-
主机名不匹配:证书的公用名 (CN) 或使用者备用名称 (SAN) 与服务器的主机名不匹配。
-
过时的 CA 商店:您系统上的 CA 存储可能已过时,并且可能没有验证服务器证书所需的证书。
故障排除步骤:
检查证书:您可以使用以下命令查看服务器的证书详细信息:
echo | openssl s_client -connect servername:443 | openssl x509 -text
这将为您提供有关证书的详细信息,例如其到期日期和颁发者。
指定 CA 捆绑包:如果您有要用于验证的特定 CA 捆绑包,您可以使用--cacert
option:
curl --cacert /path/to/ca-bundle.crt https://example.com
更新 CA 商店:在某些系统上,您可能需要更新 CA 存储。该方法因系统而异。例如,在基于 Debian 的系统上,您可以使用:
sudo apt-get update && sudo apt-get install --reinstall ca-certificates
检查代理:确保没有任何可能干扰您的连接的代理配置。如果代理已到位,则应正确配置它以处理 SSL/TLS 流量。
SSL 403 禁止
“403 Forbidden”是一个 HTTP 状态代码,表示服务器理解该请求,但拒绝授权。这可能是由于以下几个原因造成的:
-
缺乏权限:服务器可能被设置为拒绝访问您尝试访问的特定资源。
-
地理限制:某些 Web 服务器根据客户端的地理位置限制访问。
-
IP黑名单:您的 IP 地址可能因可疑活动而被列入黑名单。
-
盗链保护:如果引荐来源网址不是来自同一域,某些 Web 服务器会阻止直接访问资源(例如图像)。
-
服务器配置错误:.htaccess 文件或其他服务器配置文件配置不正确。
-
访问规则限制:服务器可能对用户代理有特定的规则,并可能阻止来自
curl
默认情况下。
-
SSL 证书问题:尽管 403 通常与授权有关,但服务器或客户端上配置错误的 SSL/TLS 设置可能会干扰正确的访问。
故障排除步骤:
使用详细模式: Using -v
with curl
可以给出更多关于请求和响应过程的细节:
curl -v https://example.com
更改用户代理:某些服务器可能会阻止默认设置curl
用户代理。你可以改变它-A
:
curl -A "Mozilla/5.0" https://example.com
用浏览器检查:在 Web 浏览器中打开该 URL,查看问题是否仍然存在。这可以帮助确定问题是否出在curl
或服务器范围内。
仅检查标头:使用-I
选项与curl
仅获取标头。这可以提供线索,特别是如果有一个“位置”标头可能会重定向您:
curl -I https://example.com
检查服务器日志:如果您有权访问服务器,请检查服务器日志(例如 Apache 的日志)error.log
或者 Nginx 的error.log
)了解有关请求被禁止的原因的更多详细信息。
SSL/TLS 配置:如果您怀疑错误与 SSL/TLS 相关,请检查服务器的配置。类似的工具Qualys SSL 实验室可以提供对服务器 SSL 设置的深入了解。
处理过期证书
当服务器的证书过期时,curl
由于证书无效而拒绝建立连接。
curl https://expired-cert.example.com
Output:
* Trying 192.168.1.28...
* TCP_NODELAY set
* Connected to expired-cert.example.com (192.168.1.28) port 443 (#0)
* SSL certificate problem: certificate has expired
* Closing connection 0
curl: (60) SSL certificate problem: certificate has expired
解决方案:
- 解决此问题最安全的方法是更新服务器端的证书。
- 出于测试目的,您可以使用绕过此检查
--insecure
标志,但不建议在生产环境中使用。
解决主机名不匹配的问题
当 URL 中提供的主机名与服务器提供的证书中的公用名 (CN) 或使用者备用名称 (SAN) 不匹配时,会出现此错误。
curl https://mismatched-host.example.com
Output:
* Trying 192.168.1.29...
* TCP_NODELAY set
* Connected to mismatched-host.example.com (192.168.1.29) port 443 (#0)
* SSL: no alternative certificate subject name matches target host name 'mismatched-host.example.com'
* Closing connection 0
curl: (51) SSL: no alternative certificate subject name matches target host name 'mismatched-host.example.com'
解决方案:
- 验证 URL 并确保您连接到正确的服务器。
- 更新服务器的 SSL 证书以包含正确的 CN 或将所需的主机名添加到 SAN 字段。
- 对于临时故障排除,
--insecure
flag 可用于忽略此错误,但从长远来看,这不是一个安全的解决方案。
处理不支持的协议或密码
如果客户端(在本例中,curl
)并且服务器没有相互的 SSL/TLS 协议版本或密码套件,连接将失败。
curl https://unsupported-protocol.example.com
Output:
* Trying 192.168.1.30...
* TCP_NODELAY set
* Connected to unsupported-protocol.example.com (192.168.1.30) port 443 (#0)
* SSL handshake failed due to unsupported protocol or cipher
* Closing connection 0
curl: (35) SSL handshake failed due to unsupported protocol or cipher
解决方案:
- 检查服务器支持的协议和密码,然后确保您的
curl
客户支持他们。
- 升级你的
curl
版本或服务器的 SSL/TLS 软件,以支持现代且安全的协议版本和密码。
- 作为临时措施,您可以使用类似标志来指定特定的协议版本
--tlsv1.2
or --tlsv1.3
。但是,请始终确保您强制使用的版本受到两者的支持并且是安全的。
实际例子
抛开所有理论,理解的真正价值curl
当应用于现实场景时,SSL/TLS 功能就会发挥作用。
让我们通过几个实际示例来展示如何使用curl
在与 SSL/TLS 相关的日常任务中。
安全连接到网站
安全连接到网站是主要用例curl
处理 SSL/TLS 时。
以下是您在执行此操作时如何确保最佳安全性的方法:
curl -I --tlsv1.3 --cacert /path/to/trusted/ca/certificate.pem https://secure-website.example.com
Output:
HTTP/2 200
date: Fri, 25 Aug 2023 12:00:00 GMT
server: Apache/2.4.29
strict-transport-security: max-age=63072000; includeSubDomains
通过查看标头,您可以看到该网站使用 HTTP/2 并设置了“Strict-Transport-Security”标头,这表明它的安全配置良好。
-
-I
仅获取标头,使其成为检查网站连接及其安全标头的轻量级方法。
-
--tlsv1.3
确保您使用的是最新且安全的 TLS 版本。
-
--cacert
允许您指定自定义证书颁发机构,确保服务器的证书根据您信任的证书进行验证。
调试 SSL/TLS 问题
如果您在连接站点时遇到问题,打开详细日志记录可以帮助您识别问题:
curl -v --tlsv1.3 https://problematic-website.example.com
Output:
* Trying 192.168.1.31...
* TCP_NODELAY set
* Connected to problematic-website.example.com (192.168.1.31) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, handshake failure (512):
* error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
* Closing connection 0
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
详细输出(-v
flag)提供有关连接过程的详细信息。
在这里,您可以看到“警报握手失败”,这表明之间可能没有共享密码套件curl
和服务器。
--tlsv1.3
指定TLS版本,需要根据服务器的能力进行调整。