gpt4 book ai didi

python-3.x - Websocket 高速公路 Python 客户端 : how to connect to server using server and client certificates?

转载 作者:太空宇宙 更新时间:2023-11-03 14:27:28 25 4
gpt4 key购买 nike

websocket 客户端(使用 Autobahn/Python 和 Twisted)需要连接到 websocket 服务器:客户端需要向服务器出示其客户端证书,客户端需要检查服务器的证书。例如,这些证书是在 Kubernetes minikube 安装过程中创建的。特别是:

  • 服务器证书 ~/.minikube/ca.crt(据我所知采用 X509 格式)。
  • 带有 key ~/.minikube/client.key 的客户端证书 ~/.minikube/client.crt

我已经检查过我可以成功地使用这些证书+ key 来使用 curl 发出 Kubernetes 远程 API 调用。

来自高速公路的 echo_tls/client.py示例 我知道我可能需要使用 ssl.ClientContextFactory()。这里的ssl是指twisted自动导入的pyopenssl包。

但是,我不知道如何将证书传递给工厂?

  • 我如何告诉 websocket 因素向服务器提供客户端证书?
  • 如何让 websocket 检查服务器的证书以检测 MITM 攻击?

最佳答案

经过反复试验,我现在得出了下面的解决方案。为了帮助其他人,我不仅会展示代码,还会展示用于测试示例代码的引用设置。

首先,安装minikube,然后启动一个minikube实例;我已经使用 minikube 1.0.0 进行了测试,然后运行 ​​Kubernetes 1.14,这是撰写本文时的最新版本。然后启动一个简单的 websocket 服务器,它只显示发送给它的内容,并将您对连接的 websocket 客户端所做的任何输入发回。

minikube start
kubectl run wsserver --generator=run-pod/v1 --rm -i --tty \
--image ubuntu:disco -- bash -c "\
apt-get update && apt-get install -y wget && \
wget https://github.com/vi/websocat/releases/download/v1.4.0/websocat_1.4.0_ssl1.1_amd64.deb && \
dpkg -i webso*.deb && \
websocat -vv -s 0.0.0.0:8000"

接下来是 Python 代码。它尝试从 minikube 通过 Kubernetes 的远程 API 连接到我们刚刚启动的 wsserver,使用远程 API 作为其反向代理。 minikube 设置通常使用客户端和服务器的相互 SSL/TLS 身份验证,因此这是一个“硬”测试。请注意,还有其他方法,例如服务器证书和不记名 token (而不是客户端证书)。

import kubernetes.client.configuration
from urllib.parse import urlparse
from twisted.internet import reactor
from twisted.internet import ssl
from twisted.python import log
from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS
import sys

if __name__ == '__main__':
log.startLogging(sys.stdout)

class EchoClientProto(WebSocketClientProtocol):
def onOpen(self):
print('onOpen')
self.sendMessage('testing...\n'.encode('utf8'))
def onMessage(self, payload, isBinary):
print('onMessage')
if not isBinary:
print('message %s' % payload.decode('utf8'))
def onClose(self, wasClean, code, reason):
print('onClose', wasClean, code, reason)
print('stopping reactor...')
reactor.stop()

# Select the Kubernetes cluster context of the minikube instance,
# and see what client and server certificates need to be used in
# order to talk to the minikube's remote API instance...
kubernetes.config.load_kube_config(context='minikube')
ccfg = kubernetes.client.configuration.Configuration._default
print('Kubernetes API server CA certificate at %s' % ccfg.ssl_ca_cert)
with open(ccfg.ssl_ca_cert) as ca_cert:
trust_root = ssl.Certificate.loadPEM(ca_cert.read())
print('Kubernetes client key at %s' % ccfg.key_file)
print('Kubernetes client certificate at %s' % ccfg.cert_file)
with open(ccfg.key_file) as cl_key:
with open(ccfg.cert_file) as cl_cert:
client_cert = ssl.PrivateCertificate.loadPEM(cl_key.read() + cl_cert.read())

# Now for the real meat: construct the secure websocket URL that connects
# us with the example wsserver inside the minikube cluster, via the
# remote API proxy verb.
ws_url = 'wss://%s/api/v1/namespaces/default/pods/wsserver:8000/proxy/test' % urlparse(ccfg.host).netloc
print('will contact: %s' % ws_url)
factory = WebSocketClientFactory(ws_url)
factory.protocol = EchoClientProto

# We need to attach the client and server certificates to our websocket
# factory so it can successfully connect to the remote API.
context = ssl.optionsForClientTLS(
trust_root.getSubject().commonName.decode('utf8'),
trustRoot=trust_root,
clientCertificate=client_cert
)

connectWS(factory, context)
print('starting reactor...')
reactor.run()
print('reactor stopped.')

使用 optionsForClientTLS 附加客户端和服务器证书时,这里的棘手部分是 Twisted/SSL 期望被告知我们将要与之交谈的服务器名称。这也需要通知虚拟服务器他们需要出示他们的多个服务器证书中的哪一个 - 在有任何 HTTP header 之前!

不幸的是,这现在是一个丑陋的领域——我很乐意在这里得到反馈!简单地使用 urlparse(ccfg.host).hostname 可以在一些 minikube 实例上工作,但不能在其他实例上工作。我还没有弄清楚为什么看似相似的实例表现不同。

我目前的解决方法是简单地使用服务器证书中主题的 CN(通用名称)。也许更稳健的方法可能是仅在远程 API 服务器的 URL 使用 IP 地址文字而不是 DNS 名称(或至少是标签)时才采用这种策略。

唉,运行 python3 wssex.py 上面的 Python 3 代码。如果脚本正确连接,那么您应该会看到类似于 2019-05-03 12:34:56+9600 [-] {"peer": "tcp4:192.168.99.100:8443", "headers ": {"sec-websocket-accept": ...

此外,您之前启动的 websocket 服务器应该显示日志消息,例如 [INFO websocat::net_peer] Incoming TCP connection from Some(V4(172.17.0.1:35222)),还有一些。

这证明客户端脚本已通过安全的 websocket 成功连接到 minikube 的远程 API,通过身份验证和访问控制,现在连接到 minikube 内的(不安全的)websocket 演示服务器。

关于python-3.x - Websocket 高速公路 Python 客户端 : how to connect to server using server and client certificates?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55799804/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com