fix: WebSocket federation proxy accepts self-signed TLS certificates
websockets.connect() used default SSL verification, rejecting self-signed
certs on remote instances. Same issue as the httpx fix (2c21dfe) but for
the websockets library. Fix: pass ssl.SSLContext with CERT_NONE when the
remote URL is wss://.
This commit is contained in:
+16
-1
@@ -17,6 +17,7 @@ import os
|
||||
import pathlib
|
||||
import pwd
|
||||
import socket
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
@@ -754,13 +755,27 @@ async def federation_terminal_ws_proxy(websocket: WebSocket, remote_id: int) ->
|
||||
else:
|
||||
ws_url = remote_url + "/terminal/ws" # assume already ws:// or wss://
|
||||
|
||||
# Build an SSL context that skips verification for self-signed certs on
|
||||
# remote instances. Same rationale as httpx verify=False: federation
|
||||
# peers may use self-signed or Tailscale-issued certs that don't pass the
|
||||
# system CA store. None tells websockets to use default behaviour (no
|
||||
# TLS) for plain ws:// URLs.
|
||||
ssl_context: ssl.SSLContext | None = None
|
||||
if ws_url.startswith("wss://"):
|
||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ssl_context.check_hostname = False
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
|
||||
await websocket.accept(subprotocol="tty")
|
||||
|
||||
try:
|
||||
async with websockets.connect(
|
||||
ws_url,
|
||||
subprotocols=[Subprotocol("tty")],
|
||||
additional_headers={"Authorization": f"Bearer {remote_key}"} if remote_key else {},
|
||||
additional_headers={"Authorization": f"Bearer {remote_key}"}
|
||||
if remote_key
|
||||
else {},
|
||||
ssl=ssl_context,
|
||||
) as remote_ws:
|
||||
|
||||
async def client_to_remote() -> None:
|
||||
|
||||
@@ -442,3 +442,20 @@ def test_federation_ws_proxy_route_exists():
|
||||
assert "/federation/{remote_id}/terminal/ws" in paths, (
|
||||
"App must have a WebSocket route at /federation/{remote_id}/terminal/ws"
|
||||
)
|
||||
|
||||
|
||||
def test_federation_ws_proxy_uses_ssl_context_for_wss():
|
||||
"""Federation WS proxy must pass an SSL context when connecting via wss://.
|
||||
|
||||
Self-signed certs on remote instances (cortex, spark-2, etc.) fail the
|
||||
default SSL verification in websockets.connect(). The proxy must build an
|
||||
SSLContext with CERT_NONE for wss:// URLs — the same fix already applied
|
||||
to the httpx client (verify=False) but for the websockets library.
|
||||
"""
|
||||
from muxplex.main import federation_terminal_ws_proxy
|
||||
|
||||
source = inspect.getsource(federation_terminal_ws_proxy)
|
||||
assert "ssl" in source and ("CERT_NONE" in source or "ssl_context" in source), (
|
||||
"Federation WS proxy must configure an SSL context (CERT_NONE / ssl_context) "
|
||||
"for self-signed cert support on wss:// connections"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user