python-websockets / websockets

Library for building WebSocket servers and clients in Python
https://websockets.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
5.23k stars 519 forks source link

fix 403 forbidden when dial with CDN edge IP with Custom SNI #1553

Open mebest100 opened 3 days ago

mebest100 commented 3 days ago

When dial with CDN edge IP with Custom SNI, such as url: wss://${cdn_edgeIP}:443/path, CDN will report 403 forbidden error

image

That is because CDN will verify both TLS SNI name and Host in request header , but your below code will take IP as Host in request header when dial with CDN edge IP

build_host(wsuri.host, wsuri.port, wsuri.secure)

Hence we need to correct this bug. The test code as below:

import ssl
from websockets.client import connect
import asyncio
async def WssHandshake():

    server_host = '104.16.177.217' 
    server_port = 443  
    sni_hostname = 'testwebsocket.icanfly668.top'  

    ssl_context = ssl.create_default_context()

    headers = {
        'Host': sni_hostname,
        "User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
    }

    uri = f"wss://{server_host}:{server_port}/ws"
    async with connect(uri=uri, ssl=ssl_context,server_hostname=sni_hostname, 
        extra_headers=headers, subprotocols=["chat"]) as websocket:
        await websocket.send("Hello, WebSocket with SNI!")
        response = await websocket.recv()
        print(response)

asyncio.run(WssHandshake())

If take your old websockets version, it will report 403 forbbiden error. But take this PR code ,the error will be elimated