我有一個用python 3實作的安全網路套接字服務器,在RaspberryPI設備上運行,地址為RASPI_ADDRESS,暴露在8000埠。 在RaspberryPI設備上,ssl的版本顯示為:
import ssl
print(ssl.OPENSSL_VERSION)。
OpenSSL 1.1.1d 10 Sep 2019
出于測驗目的,我使用了一個用openssl生成的自簽名證書:證書檔案cert.pem,其配套的私鑰在key.pem。
在客戶端,我在一臺 Windows 機器上,我按以下方式實作了客戶端(上面的 cert.pem 檔案在這里可以作為本地拷貝):
import ssl
import websocket
ws = websocket.WebSocket(sslopt={"ssl_version": ssl.PROTOCOL_TLSv1, "certfile": "cert.pem"})
try:
ws.connect("wss:/RASPI_ADDRESS:8000")
ws.send("Hello, Server")
print(ws.recv())
ws.close()
except Exception as e:
print("Exception: "/span>, e)
我在ws.connect(...)上得到了這個例外:
Exception: [SSL] PEM lib (_ssl.c:4065)
(如果我使用 "ws://... "的非安全方式進行連接,它就會作業)
不幸的是,我在搜索這個錯誤時沒有得到很多相關的結果。我試著在sslopt中也提供私鑰("keyfile": "key.pem"),但是腳本似乎陷入了一些同步阻塞中--沒有例外,螢屏上沒有列出任何東西,但服務器端也沒有收到任何東西。
有誰能指出我做錯了什么嗎?
uj5u.com熱心網友回復:
最后,我通過使用websockets庫重寫服務器和客戶端解決了這個問題。https://pypi.org/project/websockets/
也許它也可以使用websocket-client庫https://pypi.org/project/websocket-client/來運行,但檔案中的內容部分不一致,令人困惑。在此寫下一個簡化的作業方案,供今后參考,其形式是一個假的回聲服務器。
在RasPI上運行的服務器(在局域網的IP地址RASPI_IP上可見)
import asyncio
import pathlib
import ssl
import websockets
async def hello(websocket, path)。
name = await websocket.recv()
print(f"<<< {name}"/span>)
greeting = f "Hello {name}!
await websocket.send(greeting)
print(f">>> {greeting}"/span>)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
localhost_pem = pathlib.Path(__file__).with_name("key_cert.pem")
ssl_context.load_cert_chain(localhost_pem)
async def main()。
async with websockets.serve(hello, "0.0.0.0", 8765, ssl=ssl_context) 。
await asyncio.Future() # run forever
asyncio.run(main())
注意websockets.serve()中的 "0.0.0.0 "主機IP! 如果我們將其設定為 "localhost",客戶端將看到一個以這個錯誤結束的堆疊跟蹤:
ConnectionRefusedError。[WinError 1225] 遠程計算機拒絕網路連接。
在Windows機器上運行的客戶端:
import asyncio
import pathlib
import ssl
import websockets
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
localhost_pem = pathlib.Path(__file__).with_name("key_cert.pem")
ssl_context.load_verify_locations(localhost_pem)
uri_linux = "wss:/RASPI_IP:8765"/span>
async def hello()。
uri = uri_linux
async with websockets.connect(uri, ssl=ssl_context) as websocket。
name = input("你的名字是什么?")
await websocket.send(name)
print(f">>> {name}"/span>)
greeting = await websocket.recv()
print(f"<<< {greeting}"/span>)
asyncio.run(hello())
與原來的實作相比,這至少讓我有了反應,因為后來我遇到了這樣的錯誤:
ssl.SSLCertVerificationError。[SSL: CERTIFICATE_VERIFY_FAILED] 證書驗證失敗。IP地址不匹配,證書是 不有效for *RASPI_IP*。(_ssl.c:1129)
通過生成帶有SAN而不是只有CN的證書,這個問題就解決了:https://serverfault.com/a/880809
此外,我把證書和密鑰合并成一個檔案。cat key.pem cert.pem > key_cert.pem
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/329847.html
標籤:
上一篇:我怎樣才能解決這個問題呢?
下一篇:如何在JPA規范中使用串列
