Closed
Description
@Carglglz
During the handshake the Sec-WebSocket-Key is send undecoded which results in it being sent with an additional b''
(like b'tb4IfqY2SEcIEy0pv0opLQ=='
).
If the line:
is changed to the following it doesn't cause an error anymore:
headers["Sec-WebSocket-Key"] = key.decode()
I used a python-websocket Server for testing which seems to make more sense than the other options as a servers, since it claim to be more strickly following the RFC6455 specification and offers informative error logging.
Here is the server error log of the handshake:
= connection is CONNECTING
< GET / HTTP/1.1
< Origin: https://192.168.178.123:4443
< Connection: Upgrade
< Sec-WebSocket-Key: b'tb4IfqY2SEcIEy0pv0opLQ=='
< Host: 192.168.178.123:4443
< Upgrade: websocket
< Sec-WebSocket-Version: 13
s_w_key="b'tb4IfqY2SEcIEy0pv0opLQ=='"
! invalid handshake
Traceback (most recent call last):
File "/home/username/tls-test/venv/lib/python3.11/site-packages/websockets/legacy/handshake.py", line 86, in check_request
raw_key = base64.b64decode(s_w_key.encode(), validate=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/base64.py", line 88, in b64decode
return binascii.a2b_base64(s, strict_mode=validate)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
binascii.Error: Only base64 data is allowed
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/username/tls-test/venv/lib/python3.11/site-packages/websockets/legacy/server.py", line 167, in handler
await self.handshake(
File "/home/username/tls-test/venv/lib/python3.11/site-packages/websockets/legacy/server.py", line 609, in handshake
key = check_request(request_headers)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/username/tls-test/venv/lib/python3.11/site-packages/websockets/legacy/handshake.py", line 88, in check_request
raise InvalidHeaderValue("Sec-WebSocket-Key", s_w_key) from exc
websockets.exceptions.InvalidHeaderValue: invalid Sec-WebSocket-Key header: b'tb4IfqY2SEcIEy0pv0opLQ=='
> HTTP/1.1 400 Bad Request
> Date: Tue, 07 May 2024 00:14:16 GMT
> Server: Python/3.11 websockets/12.0
> Content-Length: 102
> Content-Type: text/plain
> Connection: close
> [body] (102 bytes)
connection rejected (400 Bad Request)
x closing TCP connection
! timed out waiting for TCP close
x aborting TCP connection
= connection is CLOSED
connection closed
After the change the connection works as expected. Strangely two other servers i've tested connected despite of this bug. After the code change they also still connect as to be expected.
Here is the server code:
#!/usr/bin/env python
import asyncio
import pathlib
import ssl
import websockets
import logging
logging.basicConfig(
format="%(message)s",
level=logging.DEBUG,
)
async def hello(websocket):
while True:
msg = await websocket.recv()
print(f"{msg}")
# await websocket.send(msg)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_cert = "cert.pem"
ssl_key = "key.pem"
ssl_context.load_cert_chain(ssl_cert, ssl_key)
async def main():
async with websockets.serve(hello, "0.0.0.0", 4443, ssl=ssl_context):
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
Metadata
Metadata
Assignees
Labels
No labels