当前位置: 首页 > 知识库问答 >
问题:

Websocket Autobahn Python客户端:如何使用服务器和客户端证书连接到服务器?

狄飞鹏
2023-03-14

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

  • 服务器证书~/。minikube/ca.crt(据我所知为X509格式)
  • 客户端证书~/。minikube/客户。带按键的crt~/。minikube/客户。按键

我已经检查过,我可以成功地使用这些证书密钥使用curl发出库伯内特斯远程API调用。

从Autobahn的echo_tls/client.py示例中,我了解到我可能需要使用ssl。这里的ssl是指自动导入的pyopenssl包。

但是,我想不通如何把证书传给工厂?

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

共有1个答案

濮俭
2023-03-14
匿名用户

经过反复试验,我现在得到了下面的解决方案。为了帮助其他人,我不仅要展示代码,还要展示测试驱动示例代码的参考设置。

首先安装minikube,然后启动minikube实例;我已经用Minikube1.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身份验证,因此这是一个“硬”测试。请注意,还有其他方法,例如服务器证书和承载令牌(而不是客户端证书)。

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头之前,还需要通知虚拟服务器需要提供多个服务器证书中的哪一个!

不幸的是,这是一个丑陋的领域——我很高兴在这里得到反馈!只需使用urlparse(ccfg.host)。主机名适用于某些minikube实例,但不适用于其他实例。我还没有弄明白为什么看起来相似的实例表现不同。

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

唉,运行上面的python3代码python3wssex。py。如果脚本正确连接,那么您应该会看到一条类似于2019-05-03 12:34:56 9600[-]{“对等”:“tcp4:192.168.99.100:8443”,“headers”:{“sec websocket accept”:…

此外,您以前启动过的websocket服务器应该显示日志消息,例如来自某些(V4(172.17.0.1:35222))和其他一些服务器的[INFO webostat::net\u peer]传入TCP连接。

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

 类似资料:
  • 问题内容: 我完全被困在这里。我有一个Java客户端代码,需要使用自签名证书连接到SSL服务器。 仅 当我在服务器端禁用SSLv2支持时, 才会 出现此问题。 痕迹是 在服务器端,我可以看到以下跟踪: 如果启用SSL2,我会看到 而且一切正常。 我还知道那不是服务器端的东西,因为与其他软件连接可以正常工作。 知道我在做什么错吗? 还有人知道这个“读取客户端问候A / B”是什么意思吗? 谢谢 更新

  • 我有一个示例Spring启动应用程序来运行图形QL服务器,具有作为客户端,我的pom有以下依赖项: 当我尝试从客户端连接时,出现以下错误: 狩猎决议好心建议。 我还有几个问题: 我应该使用SimpleGraphQLHttpServlet将请求路由到endpoint吗 我正在React UI上使用apollo client,那么它是强制使用apollo server还是spring boot可以工作

  • 验证 SSH 服务器证书(客户端) 和 SSH 用户证书 类似,使用客户端机构认证来验证主机。需要一个 SSH 服务器数字证书认证机构签发服务器证书,客户端只需要保存 CA 的公钥。 使用一台处于气隙系统下的计算机来生成服务器数字证书认证机构的根证书: ❯ ssh-keygen -C "SSH Server Certificate Authority" -f sshserver.root.ca 使

  • 我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se

  • 所有的 我正在尝试连接到Oracle 19C数据库。我安装了两个Oracle客户端(11g和12c),因为我们需要支持遗留程序。我可以通过12c客户端与使用sqlplus的任何用户连接,没有问题。但是如果我与任何用户一起使用11g(11.2.0)客户端。我总是得到: 两个客户端都有完全相同的sqlnet。ora和tnsnames。ora文件,因此两个客户端都指向同一个数据库。 有什么想法吗?我是否

  • 客户端应用程序在以下代码处挂起: