- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在尝试让一个简单的 Python SSL 示例运行一天,但没有成功。我想创建一个 SSL 服务器和 SSL 客户端。服务器应该对客户端进行身份验证。 Python 文档对 SSL 模块的示例非常简单,通常我找不到很多工作示例。我正在使用的代码如下;
客户:
import socket
import ssl
class SSLClient:
def __init__(self, server_host, server_port, client_cert, client_key):
self.server_host = server_host
self.server_port = server_port
self._context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
self._context.load_cert_chain(client_cert, client_key)
self._sock = None
self._ssock = None
def __del__(self):
self.close()
def connect(self):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ssock = self._context.wrap_socket(
self._sock, server_hostname=self.server_host
)
self._ssock.connect((self.server_host, self.server_port))
def send(self, msg):
self._ssock.send(msg.encode())
def close(self):
self._ssock.close()
服务器:
import socket
import ssl
from threading import Thread
class SSLServer:
def __init__(self, host, port, cafile, chunk_size=1024):
self.host = host
self.port = port
self.chunk_size = chunk_size
self._context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
self._context.load_verify_locations(cafile)
self._ssock = None
def __del__(self):
self.close()
def connect(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind((self.host, self.port))
sock.listen(5)
with self._context.wrap_socket(sock, server_side=True) as self._ssock:
conn, _ = self._ssock.accept()
while True:
data = conn.recv(self.chunk_size).decode()
print(data)
if data is None:
break
def close(self):
self._ssock.close()
class SSLServerThread(Thread):
def __init__(self, server):
super().__init__()
self._server = server
self.daemon = True
def run(self):
self._server.connect()
def stop(self):
self._server.close()
测试脚本:
import client, server
from os import path
from time import sleep
server_host = "localhost"
server_port = 11234
client_cert = path.join(path.dirname(__file__), "client.crt")
client_key = path.join(path.dirname(__file__), "client.key")
s = server.SSLServer(server_host, server_port, client_cert)
s_thread = server.SSLServerThread(s)
s_thread.start()
sleep(2)
c = client.SSLClient(server_host, server_port, client_cert, client_key)
c.connect()
c.send("This is a test message!")
c.close()
s.close()
我使用以下命令生成了我的客户端证书和 key :
openssl req -newkey rsa:2048 \
-x509 \
-sha256 \
-days 3650 \
-nodes \
-out client.crt \
-keyout client.key \
-subj "/C=UK/ST=Scotland/L=Glasgow/O=Company A/OU=Testing/CN=MyName"
测试脚本似乎启动了服务器并允许客户端连接,但是当我尝试发送测试消息时收到 BrokenPipeError。
令人恼火的是,我一直收到各种不同的错误消息,所以这很可能是多种因素的结合。这是我创建的一个简单示例,旨在尝试让某些东西正常工作。在我更复杂的示例中,当客户端尝试连接到服务器时,我得到“NO_SHARED_CIPHERS”。令人恼火的是,我不明白为什么这个简单的示例似乎比更复杂的示例走得更远(即连接似乎已成功建立),即使它们的设置几乎相同。
如果有人想测试它,我已经在 git@github.com:stevengillies87/python-ssl-client-auth-example.git 上传了一个 repo。
我意识到第一个错误来自复制粘贴和示例,但没有意识到它在设置方面与我的代码有何不同。它使用 socket.socket() 创建套接字,而我的示例使用 socket.create_connection(),它也连接套接字。这就是我收到 BrokenPipeError 的原因。现在,我的简单示例和我正在编写的实际代码都出现了一致的 NO_SHARED_CIPHER 错误。我在源代码中添加了一行以在套接字被包装后连接客户端。
最佳答案
所以,正如预期的那样,这是多种因素的结合。
在我将 SSL 层添加到我的代码之前,它使用 TCP 套接字。我在客户端中使用 socket.create_connection() 在一次调用中创建和连接一个套接字。当我添加 SSL 时,我继续这样做,但是因为我试图通过 TCP 套接字连接到 SSL 服务器,所以我收到了 NO_SHARED_CIPHER 错误。
这个问题的解决方案是只用 sock = socket.socket()
创建 TCP 套接字,用 ssock = ssl_context.wrap_context(sock)
包装它,然后然后调用 SSL 层上的连接,ssock.connect((host, port))
。
但是,我在连接时仍然遇到握手错误。我找到了这个链接,https://www.electricmonk.nl/log/2018/06/02/ssl-tls-client-certificate-verification-with-python-v3-4-sslcontext/ ,其中提供了如何创建相互验证的 SSL 客户端/服务器的详细示例。至关重要的是,作者指出用于服务器身份验证的主机名必须与创建 server.crt 和 server.key 文件时输入的“通用名称”相匹配。以前我一直在使用与我连接的同一主机,在本例中为“localhost”。他们还指出,对于客户端身份验证,ssl_context 验证模式应设置为 verify_mode = ssl.CERT_REQUIRED
。
示例运行后,我开始着手删除服务器的客户端身份验证。这是通过将客户端 SSL 上下文从 ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
更改为 ssl.SSLContext()
来完成的。客户端现在不需要 server.crt 文件即可成功连接。
令人沮丧的是,我仍然需要创建服务器证书/ key 文件并使用 ssl_context.load_cert_chain()
将它们加载到服务器中,即使我不需要对服务器进行身份验证。如果我尝试从服务器中删除此步骤,我会再次收到 NO_SHARED_CIPHER 错误。如果有人知道如何避免这种情况,请告诉我,或解释为什么有必要这样做。
下面的工作代码,并在问题中的 github 链接上更新。
客户:
import socket
import ssl
class SSLClient:
def __init__(
self, server_host, server_port, sni_hostname, client_cert, client_key,
):
self.server_host = server_host
self.server_port = server_port
self.sni_hostname = sni_hostname
self._context = ssl.SSLContext()
self._context.load_cert_chain(client_cert, client_key)
self._sock = None
self._ssock = None
def __del__(self):
self.close()
def connect(self):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ssock = self._context.wrap_socket(self._sock,)
self._ssock.connect((self.server_host, self.server_port))
def send(self, msg):
self._ssock.send(msg.encode())
def close(self):
self._ssock.close()
服务器:
import socket
import ssl
from threading import Thread
class SSLServer:
def __init__(
self, host, port, server_cert, server_key, client_cert, chunk_size=1024
):
self.host = host
self.port = port
self.chunk_size = chunk_size
self._context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self._context.verify_mode = ssl.CERT_REQUIRED
self._context.load_cert_chain(server_cert, server_key)
self._context.load_verify_locations(client_cert)
def connect(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind((self.host, self.port))
sock.listen(5)
while True:
conn, _ = sock.accept()
with self._context.wrap_socket(conn, server_side=True) as sconn:
self._recv(sconn)
def _recv(self, sock):
while True:
data = sock.recv(self.chunk_size)
if data:
print(data.decode())
else:
break
class SSLServerThread(Thread):
def __init__(self, server):
super().__init__()
self._server = server
self.daemon = True
def run(self):
self._server.connect()
测试:
import client, server
from os import path
from time import sleep
server_host = "127.0.0.1"
server_port = 35689
server_sni_hostname = "www.company-b.com"
client_cert = path.join(path.dirname(__file__), "client.crt")
client_key = path.join(path.dirname(__file__), "client.key")
server_cert = path.join(path.dirname(__file__), "server.crt")
server_key = path.join(path.dirname(__file__), "server.key")
s = server.SSLServer(server_host, server_port, server_cert, server_key, client_cert)
s_thread = server.SSLServerThread(s)
s_thread.start()
sleep(2)
c = client.SSLClient(
server_host, server_port, server_sni_hostname, client_cert, client_key
)
c.connect()
c.send("This is a test message!")
c.close()
关于python - 如何创建只有服务器对客户端进行身份验证的 Python SSL 客户端/服务器对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63980192/
我在 Cloudflare 的域名服务器上有一个域名 example.com。该域指向我的专用服务器的 IP 地址,该服务器运行 CentOS/WHM/cPanel。该站点可访问 - 一切都很好。 我
我正在努力将 SSL 支持添加到我们现有的应用程序中,并已开始考虑向后兼容性。 与我读过的其他帖子不同的一个特殊情况是服务器可能不一定使用 SSL 代码更新。所以我将有一个 SSL 客户端连接到一个对
我有几个 https://*.rest-service.mydomain.com。随着服务数量的增加,我觉得管理 SSL 证书的成本很高。我为 *.mydomain.com 购买了通配符证书。 新添加
我的客户要求我在他的网站上做反向 ssl。但我是这个学期的新手。谁能帮我解决这个问题。 请描述或引用如何做。 最佳答案 查看 this wiki article . In the case of se
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 去年关闭。 Improve this
我连接到我的网络服务器上的存储库,但是当我尝试推送我的更改时,它显示:“错误 403:需要 ssl”,但在我的存储库设置中我已经激活了 ssl 选项。 有什么建议吗? 最佳答案 当您连接到存储库时,您
抱歉,如果这听起来像是转储问题,我已经阅读了很多关于 SSL 握手和 SSL 工作原理的文章和文档。我对一件事感到困惑,如果有人能澄清我就太好了。 我知道私钥要保密。但是我已经看到通过在请求中指定私钥
随着物联网越来越主流,越来越需要从硬件发送http请求。 一个主要问题是硬件微 Controller 无法发送 ssl 请求,但大多数服务器/网站/服务都在使用 ssl。 所以,问题是,有没有桥(一个
我有一个 ssl 页面,它还从非 ssl 站点下载头像。我能做些什么来隔离该内容,以便浏览器不会警告用户混合内容吗? 最佳答案 只是一个想法 - 或者: 尝试在头像网站上使用 ssl url,如有必要
我在 Digital Ocean droplet(使用 nginx)上设置了两个域。我已经在其中一个(domain1)中安装了一个 SSL 证书,并且那个证书一切正常。第二个域 (domain2) 不
我收到这个错误: Error frontend: 502 Bad gateway 99.110.244:443 2017/09/28 13:03:51 [error] 34080#34080: *10
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 6 年前。 Improve
我遇到了一个问题,我正在构建一个 nginx 反向代理以定向到不同 url 路径上的多个微服务。 该系统完全基于 docker,因此开发和生产使用相同的环境。这在安装 SSL 时给我带来了问题,因为
所以我知道要求 SSL 证书和接受之间的根本区别,一个意味着您必须拥有 SSL 证书,另一个意味着您不需要。 在某个网页的 IIS 管理器中,我有以下设置: 我遇到的问题是,当我设置需要 SSL 证书
我今天才发现 .app 域名需要 SSL 证书。我购买它是为了将 DNS 重定向到已经设置了 SSL 证书的站点,所以我的问题是是否可以设置它? 我正在使用 Google Domains,在将合成临时
堆栈 : react ,NGINX 1.14.0,GUnicorn,Django 2.2.8,Python 3.6.9 错误 : 在浏览器:当 React 调用 Django API(当然是在请求头中
假设我在计算机上编辑主机文件以使 google.com 指向我的 VPS 服务器 IP,并且服务器具有通过 Apache 或 Nginx 配置的 google.com 的虚拟主机/服务器 block
我有一个场景,我正在处理用于 URL 路由的 IIS 网站配置。我已添加网站并在服务器上导入所需的证书。 我的情况是(我有多个网站 URL 和两个 SSL 证书 - 如下所示): qatest1.ab
我知道服务器发送的证书无法伪造(仍然存在 MD5 冲突,但成本高昂),但是伪造客户端又如何呢?在中间人攻击中:我们不能告诉服务器我们是合法客户端并从该服务器获取数据并对其进行操作,然后使用合法客户端公
我已通读相关问题,但无法完全找到我要查找的内容。我设置了一个名为“domain.com”的域,并创建了两个子域“client.domain.com”和“client-intern.domain.com
我是一名优秀的程序员,十分优秀!