域SSL证书和Websockets SSL证书的区别
问题描述
我有一个域名example.com
,我的注册商为该域名颁发了一个SSL证书*.example.com
。我添加了以下代码行:
SSLEngine on
SSLCertificateFile /etc/apache2/certs/ssl.cer
SSLCertificateKeyFile /etc/apache2/certs/ssl.key
SSLCertificateChainFile /etc/apache2/certs/ssl_intermediate.cer
对我的Apache配置进行以下更改,网页可以通过https访问:
https://example.com
。
现在,该网页还侦听位于以下位置的Websockets连接:
wss://example.com:8888/wss/
,该连接被转发到一个Python Websockets服务器。
ProxyPass "/wss/" "http://<internal_ip>:8888/" upgrade=websocket
这个也没有问题。我困惑的是我注册商颁发的SSL证书与使用SSL保护websockets连接的能力之间的关系。我同时使用websockets
的Python库作为客户端和服务器端,该库支持加密连接(摘自这里)。
...
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
localhost_pem = pathlib.Path(__file__).with_name("localhost.pem")
ssl_context.load_cert_chain(localhost_pem)
async def main():
async with websockets.serve(hello, "<internal_ip>", 8888, ssl=ssl_context):
await asyncio.Future()
...
我的主要问题如下:
- 这个pem文件是应该和由我注册商颁发的证书一样,还是它们完全独立?
- 客户端和服务器是否应使用相同的pem文件?
- 如果域名已经使用了SSL,是否有必要保护WebSockets连接?
如果我不提供SSL上下文,一切都按预期工作。但连接仍然是wss连接,所以我对为什么没有SSL的情况下这个能够工作感到困惑。当我提供测试证书localhost.pem时,来自这里的连接会失败。
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
所以我不确定是否可以使用任何自签名证书进行网络套接字连接,还是必须与域证书同步。
解决方案
这个pem文件是否应该与我的注册商颁发的证书相同,还是它们完全独立?
由于Web服务器和Websocket位于相同的域名上(即使端口不同),因此可以使用相同的证书。但也可以使用不同的证书 – 可以同时有多个覆盖相同域名的证书。
客户端和服务器是否应该使用相同的pem文件?
无论是Web服务器还是Websocket,通常只进行服务器的身份验证。在这里,客户端只验证服务器的证书,因此需要信任它。这通常是通过信任颁发服务器证书的证书颁发机构(CA)来完成的,而不是直接信任服务器的证书。
使用证书进行客户端身份验证称为相互身份验证,不太常见。但在这种情况下,客户端不应使用服务器证书,而应使用自己的证书 – 这是用于验证客户端而非服务器。
如果域名已经使用SSL,是否有必要保护网络套接字连接?
Websocket连接应该具有与域名本身相同的安全性。这并不意味着Websocket服务器本身需要具备TLS功能。常见的设置是将现有的Web服务器简单地用作Websocket服务器的反向代理 – 在这种情况下,Web服务器终止TLS并向客户端提供服务器证书。这样一来,可以使用默认的HTTPS端口,并仅为Websocket使用特殊路径。看起来这就是您打算在配置中执行的操作(特殊路径/ws
)。