Python 中实施的 Websockets (WSS) 服务器问题
Issue with Websockets (WSS) server implemented in Python
我知道 browser-based implementation at websockets.readthedocs.io as well as the secure implementation(wss) 但我很难将两者结合使用 (Browser-based WSS)。
目前,我正在两个不同的环境中测试套接字服务器,windows 10 NT(最新)超过 ws 和 CentOS 7.9 wss 和 在 Cloudflare 代理后 。 windows 测试工作正常,但是当在浏览器中尝试 CentOS 7 实现时,套接字失败并抛出 因未知原因立即关闭 (Client-side Websockets错误,我的 websocket.onerror
回调中的事件阶段 #2)。
我怀疑我的 sslContext
有问题,我应该承认我在开发级别的证书方面经验不多。 CORS 不允许使用与加载 websocket 的初始页面不匹配的证书完成握手,因此我安装了 Cloudflare 原始证书并启用了 authenticated origin pulls CF 仪表板。自访问初始化 websocket 的页面以来,我已经确认我的原始证书已正确提供给浏览器,但我不确定我的 websocket 是否按应有的方式将证书提供给 CF 边缘服务器,这会导致 CF 出错.
在阅读了 CF 论坛上的许多主题后,我认为只要原始服务器上的内容正确,CF 就可以很好地代理 WSS。
我正在尝试 CF 支持建议的端口 8443 上的 websocket。
我怀疑我在 sslContext
中错误地使用了提供的 Cloudflare 原始证书。
参考下面的 sslContext
,cert.crt
是 CA,cert.key 是相应的密钥,这两个都是我在生成 CF 原始证书时收到的。这是正确的吗?如果不正确,如何使用 CF 原始证书来保护 websocket?
这里是相关的sslContext
:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("/var/www/mysite.org/cert/cert.crt", "/var/www/mysite.org/cert/cert.key")
怀疑这只是一个 browser-based 问题,我使用 browser-based example on ReadTheDocs(客户端)的修改版本来增强 loosely-secured 浏览器,果然,在正确使用 Certifi
创建一个 sslContext
[下面的第二个粘贴],我遇到了异常:
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
cli.main()
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
run()
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 268, in run_path
return _run_module_code(code, init_globals, run_name,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\User\Desktop\mysite\socket\client.py", line 23, in <module>
asyncio.get_event_loop().run_until_complete(test())
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
return future.result()
File "c:\Users\User\Desktop\mysite\socket\client.py", line 13, in test
async with websockets.connect(
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 604, in __aenter__
return await self
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 629, in __await_impl__
await protocol.handshake(
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 388, in handshake
raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 525
这是返回 525
响应代码的测试客户端:
import asyncio
import ssl
import websockets
import certifi
import logging
logging.basicConfig(filename="client.log", level=logging.DEBUG)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.load_verify_locations(certifi.where())
async def test():
uri = "wss://mysite.org:8443/"
async with websockets.connect(
uri, ssl=ssl_context
) as websocket:
await websocket.send("test")
print("> test")
response = await websocket.recv()
print(f"< {response}")
asyncio.get_event_loop().run_until_complete(test())
这是服务器端的所有相关脚本:
if 'nt' in name:
ENUMS.PLATFORM = 0
platform = DEBUG_WINDOWS_NT
start_server = websockets.serve(
server,
platform.adapter,
platform.port,
max_size=9000000
)
else:
ENUMS.PLATFORM = 1
platform = PRODUCTION_CENTOS_7_xx
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("/var/www/mysite.org/cert/cert.crt", "/var/www/mysite.org/cert/cert.key")
start_server = websockets.serve(
server,
platform.adapter,#0.0.0.0
platform.port,#8443
max_size=9000000,
ssl=ssl_context
)
try:
asyncio.get_event_loop().run_until_complete(start_server)
print("Mysite Socket -> LISTENING ON %s:%s" % (platform.adapter, platform.port,))
asyncio.get_event_loop().run_forever()
except Exception as e:
print(e)
这里是相应的客户端JS(如果有用的话):
let sAddress;
if (location.hostname.includes('mysite.org')){
sAddress = `wss://${location.hostname}:8443/`
}else{
sAddress = `ws://${location.hostname}:5567/`
}
console.log(`URI: ${sAddress}`);
methods = [
{
action: "detection",
captcha: "",
blob: undefined
},
];
this.websocket = new WebSocket(sAddress);
this.websocket.onerror = function (event){
console.log(event);
switch (event.eventPhase) {
case 2:
alert("The connection is going through the closing handshake, or the close() method has been invoked.");
break;
default:
alert("Unknown error.");
break;
}
location.reload();
}
这是尝试连接后我的服务器脚本的日志输出(客户端和浏览器的结果相同):
DEBUG:asyncio:Using selector: EpollSelector
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
请注意“state = CONNECTING” 事件,它们会继续,不断......
所以本质上是建立了一个连接,客户端关闭但 CF 继续向源服务器发送请求。
看到这个后,我决定捕获端口 8443 上的流量,这里是 从客户端到套接字服务器的一次 尝试的转储,这在同一时间不断重复发生一次尝试后的顺序。
在十六进制编辑器中检查转储后,我可以看到 CF 原始证书位于长度为 1662 的数据包中。
据我所知,握手实际上是通过代理发生的,但是 fails/is 被浏览器丢弃,这使得 CF 边缘服务器重试握手,可能期待关闭 header 或它没有从中得到的东西客户端。
无论哪种方式,browser/client 似乎都以兼职方式放弃了握手。
browser/client 尝试
期间端口 8443 上流量的 Tcpdump
01:04:21.585671 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1, win 64, length 0
01:04:21.586293 IP CLOUDFLARE > MY_SERVER: Flags [P.], seq 1:227, ack 1, win 64, length 226
01:04:21.586321 IP MY_SERVER > CLOUDFLARE: Flags [.], ack 227, win 237, length 0
01:04:21.590265 IP MY_SERVER > CLOUDFLARE: Flags [P.], seq 1:1663, ack 227, win 237, length 1662
01:04:21.749807 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1461, win 67, length 0
01:04:21.749871 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1663, win 70, length 0
01:04:21.751082 IP CLOUDFLARE > MY_SERVER: Flags [P.], seq 227:1583, ack 1663, win 70, length 1356
01:04:21.751978 IP MY_SERVER > CLOUDFLARE: Flags [F.], seq 1663, ack 1583, win 258, length 0
01:04:21.911537 IP CLOUDFLARE > MY_SERVER: Flags [F.], seq 1583, ack 1664, win 70, length 0
01:04:21.911639 IP MY_SERVER > CLOUDFLARE: Flags [.], ack 1584, win 258, length 0
这就是奇怪的地方...
最后,我尝试绕过 CF 并使用 python 客户端直接访问我的服务器:
I get the following exception, with the same DEBUG:websockets.protocol:server - state = CONNECTING
message in the log:
Exception has occurred: SSLCertVerificationError
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
File "C:\Users\User\Desktop\mysite.org\socket\client.py", line 13, in test
async with websockets.connect(
File "C:\Users\User\Desktop\mysite.org\socket\client.py", line 23, in <module>
asyncio.get_event_loop().run_until_complete(test())
这是尝试从 Python 客户端直接访问服务器的 Tcpdump:
07:10:18.135487 IP MYIP > MYSERVER: Flags [S], seq 4035557944, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
07:10:18.135641 IP MYSERVER > MYIP: Flags [S.], seq 4244322261, ack 4035557945, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
07:10:18.306419 IP MYIP > MYSERVER: Flags [.], ack 1, win 1026, length 0
07:10:18.312218 IP MYIP > MYSERVER: Flags [P.], seq 1:518, ack 1, win 1026, length 517
07:10:18.312315 IP MYSERVER > MYIP: Flags [.], ack 518, win 237, length 0
07:10:18.316156 IP MYSERVER > MYIP: Flags [P.], seq 1:1663, ack 518, win 237, length 1662
07:10:18.485326 IP MYIP > MYSERVER: Flags [.], ack 1663, win 1026, length 0
07:10:18.485386 IP MYIP > MYSERVER: Flags [F.], seq 518, ack 1663, win 1026, length 0
07:10:18.485978 IP MYSERVER > MYIP: Flags [F.], seq 1663, ack 519, win 237, length 0
07:10:18.657095 IP MYIP > MYSERVER: Flags [.], ack 1664, win 1026, length 0
TLDR:
- 我的 sslContext 正确吗?
- 我使用的 CF 原始证书是否正确?
- 这甚至可能吗?如果可以,我做错了什么?
在这一点上,我被难住了,有点不知所措,在其他 too-good-to-be-true 框架(websockets <3)中,这是一个真正出乎意料的减速带。
如果需要更多信息,请告诉我,如果问题有点long/messy,我深表歉意long/messy。
任何反馈或解决方案都将不胜感激,因为我希望我们的访客拥有安全的体验,谢谢!
我已经解决了这个问题!
我错误地使用了证书,不需要使用原点 cert/authed 原点拉动首先让 Cloudflare 代理客户端。
我的解决方案是使用主机名 *.mysite.org
创建一个自签名证书,CF 代理它没问题:)
创建自签名证书
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
将自签名证书正确提交给 CF 边缘服务器
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("cert.pem", "cert.pem")
start_server = websockets.serve(
server,
platform.adapter,
platform.port,
max_size=9000000,
ssl=ssl_context
)
我知道 browser-based implementation at websockets.readthedocs.io as well as the secure implementation(wss) 但我很难将两者结合使用 (Browser-based WSS)。
目前,我正在两个不同的环境中测试套接字服务器,windows 10 NT(最新)超过 ws 和 CentOS 7.9 wss 和 在 Cloudflare 代理后 。 windows 测试工作正常,但是当在浏览器中尝试 CentOS 7 实现时,套接字失败并抛出 因未知原因立即关闭 (Client-side Websockets错误,我的 websocket.onerror
回调中的事件阶段 #2)。
我怀疑我的 sslContext
有问题,我应该承认我在开发级别的证书方面经验不多。 CORS 不允许使用与加载 websocket 的初始页面不匹配的证书完成握手,因此我安装了 Cloudflare 原始证书并启用了 authenticated origin pulls CF 仪表板。自访问初始化 websocket 的页面以来,我已经确认我的原始证书已正确提供给浏览器,但我不确定我的 websocket 是否按应有的方式将证书提供给 CF 边缘服务器,这会导致 CF 出错.
在阅读了 CF 论坛上的许多主题后,我认为只要原始服务器上的内容正确,CF 就可以很好地代理 WSS。 我正在尝试 CF 支持建议的端口 8443 上的 websocket。
我怀疑我在 sslContext
中错误地使用了提供的 Cloudflare 原始证书。
参考下面的 sslContext
,cert.crt
是 CA,cert.key 是相应的密钥,这两个都是我在生成 CF 原始证书时收到的。这是正确的吗?如果不正确,如何使用 CF 原始证书来保护 websocket?
这里是相关的sslContext
:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("/var/www/mysite.org/cert/cert.crt", "/var/www/mysite.org/cert/cert.key")
怀疑这只是一个 browser-based 问题,我使用 browser-based example on ReadTheDocs(客户端)的修改版本来增强 loosely-secured 浏览器,果然,在正确使用 Certifi
创建一个 sslContext
[下面的第二个粘贴],我遇到了异常:
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
cli.main()
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
run()
File "c:\Users\User\.vscode\extensions\ms-python.python-2021.5.829140558\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 268, in run_path
return _run_module_code(code, init_globals, run_name,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\User\Desktop\mysite\socket\client.py", line 23, in <module>
asyncio.get_event_loop().run_until_complete(test())
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
return future.result()
File "c:\Users\User\Desktop\mysite\socket\client.py", line 13, in test
async with websockets.connect(
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 604, in __aenter__
return await self
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 629, in __await_impl__
await protocol.handshake(
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\websockets\legacy\client.py", line 388, in handshake
raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 525
这是返回 525
响应代码的测试客户端:
import asyncio
import ssl
import websockets
import certifi
import logging
logging.basicConfig(filename="client.log", level=logging.DEBUG)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.load_verify_locations(certifi.where())
async def test():
uri = "wss://mysite.org:8443/"
async with websockets.connect(
uri, ssl=ssl_context
) as websocket:
await websocket.send("test")
print("> test")
response = await websocket.recv()
print(f"< {response}")
asyncio.get_event_loop().run_until_complete(test())
这是服务器端的所有相关脚本:
if 'nt' in name:
ENUMS.PLATFORM = 0
platform = DEBUG_WINDOWS_NT
start_server = websockets.serve(
server,
platform.adapter,
platform.port,
max_size=9000000
)
else:
ENUMS.PLATFORM = 1
platform = PRODUCTION_CENTOS_7_xx
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("/var/www/mysite.org/cert/cert.crt", "/var/www/mysite.org/cert/cert.key")
start_server = websockets.serve(
server,
platform.adapter,#0.0.0.0
platform.port,#8443
max_size=9000000,
ssl=ssl_context
)
try:
asyncio.get_event_loop().run_until_complete(start_server)
print("Mysite Socket -> LISTENING ON %s:%s" % (platform.adapter, platform.port,))
asyncio.get_event_loop().run_forever()
except Exception as e:
print(e)
这里是相应的客户端JS(如果有用的话):
let sAddress;
if (location.hostname.includes('mysite.org')){
sAddress = `wss://${location.hostname}:8443/`
}else{
sAddress = `ws://${location.hostname}:5567/`
}
console.log(`URI: ${sAddress}`);
methods = [
{
action: "detection",
captcha: "",
blob: undefined
},
];
this.websocket = new WebSocket(sAddress);
this.websocket.onerror = function (event){
console.log(event);
switch (event.eventPhase) {
case 2:
alert("The connection is going through the closing handshake, or the close() method has been invoked.");
break;
default:
alert("Unknown error.");
break;
}
location.reload();
}
这是尝试连接后我的服务器脚本的日志输出(客户端和浏览器的结果相同):
DEBUG:asyncio:Using selector: EpollSelector
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
DEBUG:websockets.protocol:server - state = CONNECTING
请注意“state = CONNECTING” 事件,它们会继续,不断...... 所以本质上是建立了一个连接,客户端关闭但 CF 继续向源服务器发送请求。
看到这个后,我决定捕获端口 8443 上的流量,这里是 从客户端到套接字服务器的一次 尝试的转储,这在同一时间不断重复发生一次尝试后的顺序。 在十六进制编辑器中检查转储后,我可以看到 CF 原始证书位于长度为 1662 的数据包中。 据我所知,握手实际上是通过代理发生的,但是 fails/is 被浏览器丢弃,这使得 CF 边缘服务器重试握手,可能期待关闭 header 或它没有从中得到的东西客户端。 无论哪种方式,browser/client 似乎都以兼职方式放弃了握手。
browser/client 尝试
期间端口 8443 上流量的 Tcpdump01:04:21.585671 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1, win 64, length 0
01:04:21.586293 IP CLOUDFLARE > MY_SERVER: Flags [P.], seq 1:227, ack 1, win 64, length 226
01:04:21.586321 IP MY_SERVER > CLOUDFLARE: Flags [.], ack 227, win 237, length 0
01:04:21.590265 IP MY_SERVER > CLOUDFLARE: Flags [P.], seq 1:1663, ack 227, win 237, length 1662
01:04:21.749807 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1461, win 67, length 0
01:04:21.749871 IP CLOUDFLARE > MY_SERVER: Flags [.], ack 1663, win 70, length 0
01:04:21.751082 IP CLOUDFLARE > MY_SERVER: Flags [P.], seq 227:1583, ack 1663, win 70, length 1356
01:04:21.751978 IP MY_SERVER > CLOUDFLARE: Flags [F.], seq 1663, ack 1583, win 258, length 0
01:04:21.911537 IP CLOUDFLARE > MY_SERVER: Flags [F.], seq 1583, ack 1664, win 70, length 0
01:04:21.911639 IP MY_SERVER > CLOUDFLARE: Flags [.], ack 1584, win 258, length 0
这就是奇怪的地方...
最后,我尝试绕过 CF 并使用 python 客户端直接访问我的服务器:
I get the following exception,
with the same DEBUG:websockets.protocol:server - state = CONNECTING
message in the log:
Exception has occurred: SSLCertVerificationError
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
File "C:\Users\User\Desktop\mysite.org\socket\client.py", line 13, in test
async with websockets.connect(
File "C:\Users\User\Desktop\mysite.org\socket\client.py", line 23, in <module>
asyncio.get_event_loop().run_until_complete(test())
这是尝试从 Python 客户端直接访问服务器的 Tcpdump:
07:10:18.135487 IP MYIP > MYSERVER: Flags [S], seq 4035557944, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
07:10:18.135641 IP MYSERVER > MYIP: Flags [S.], seq 4244322261, ack 4035557945, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
07:10:18.306419 IP MYIP > MYSERVER: Flags [.], ack 1, win 1026, length 0
07:10:18.312218 IP MYIP > MYSERVER: Flags [P.], seq 1:518, ack 1, win 1026, length 517
07:10:18.312315 IP MYSERVER > MYIP: Flags [.], ack 518, win 237, length 0
07:10:18.316156 IP MYSERVER > MYIP: Flags [P.], seq 1:1663, ack 518, win 237, length 1662
07:10:18.485326 IP MYIP > MYSERVER: Flags [.], ack 1663, win 1026, length 0
07:10:18.485386 IP MYIP > MYSERVER: Flags [F.], seq 518, ack 1663, win 1026, length 0
07:10:18.485978 IP MYSERVER > MYIP: Flags [F.], seq 1663, ack 519, win 237, length 0
07:10:18.657095 IP MYIP > MYSERVER: Flags [.], ack 1664, win 1026, length 0
TLDR:
- 我的 sslContext 正确吗?
- 我使用的 CF 原始证书是否正确?
- 这甚至可能吗?如果可以,我做错了什么?
在这一点上,我被难住了,有点不知所措,在其他 too-good-to-be-true 框架(websockets <3)中,这是一个真正出乎意料的减速带。
如果需要更多信息,请告诉我,如果问题有点long/messy,我深表歉意long/messy。
任何反馈或解决方案都将不胜感激,因为我希望我们的访客拥有安全的体验,谢谢!
我已经解决了这个问题!
我错误地使用了证书,不需要使用原点 cert/authed 原点拉动首先让 Cloudflare 代理客户端。
我的解决方案是使用主机名 *.mysite.org
创建一个自签名证书,CF 代理它没问题:)
创建自签名证书
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
将自签名证书正确提交给 CF 边缘服务器
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("cert.pem", "cert.pem")
start_server = websockets.serve(
server,
platform.adapter,
platform.port,
max_size=9000000,
ssl=ssl_context
)