websockets
websockets copied to clipboard
Add support for SOCKS proxies to connect()
EDIT - until this is implemented, the workaround consists in creating a socket connected to a socks proxy e.g. with https://pypi.org/project/python-socks/, then connect(sock=...).
See https://github.com/python-websockets/websockets/issues/475#issuecomment-1268504779 for details.
would be a great feature!
The status of this is:
- I'm not sure it's reasonable to write a custom SOCKS implementation (not sure what's involved exactly but I assume it isn't trivial).
- I'm not finding a SOCKS implementation that I could easily graft into websockets and that I'm willing to add as a dependency.
I looked at what a minimal client implementation of SOCKS v5 would involve.
- SOCKS v5 - RFC 1928 looks doable.
- Username / password authentication RFC 1928 is trivial.
- GSS-API authententication RFC 1961 looks complicated.
RFC 1928 says that "compliant implementations MUST support GSSAPI" but perhaps a non-compliant implementation would still be useful :-)
I don't think SOCKS v4 is worth investigating at this point.
I think that proxy/different transports should not have to be implemented as part of this library. The key point IMO is to support for it with an API that accepts a specific interface, for example by having a well-tailored way to strap the protocol on top of a different asyncio.StreamReader/asyncio.StreamWriter pair.
Edit: I would even go as far as to say that any different transport implementations (read: reader/writer pair) are out of scope for this library. Keep it simple. (However, that doesn't prevent you from writing a small SOCKS transport library and recommending it.)
An asyncio protocol protocol can be layered on top of another protocol. WebSocketClientProtocol could connect to a SocksProtocol which connects to a transport. Then we need a developer-friendly way to (auto-)configure this.
What is the current status regarding the support of socks5? Has there been any progress? I've checked the 3 points needed to have fully implement this. Are these points something that can be done easily (by myself even) or whether someone has checked whether a library can be used (like PySocks)?
No progress.
Hi, just wanted to write a bit about my experience trying to use a socks proxy with this library (it worked!)
Basically my code goes something like this (I'm connecting to an .onion service):
from urllib.parse import urlparse
import socks
import websockets
URL = "https://xxxxxxxxxxx.onion"
async def main():
netloc = urlparse(URL).netloc
ws_url = f"wss://{netloc}/ws"
# Disable SSL verification (self-signed certificate)
ssl_context = ssl.SSLContext()
ssl_context.verify_mode = ssl.CERT_NONE
ssl_context.check_hostname = False
# Initialize the connection to the server through the proxy
tor_proxy = socks.socksocket()
tor_proxy.set_proxy(socks.SOCKS5, "localhost", 9050)
tor_proxy.connect((netloc, 443))
# No ping and high timeout since tor is slow
websocket = await websockets.connect(
ws_url, ssl=ssl_context,
sock=tor_proxy,
server_hostname=netloc,
ping_interval=None,
ping_timeout=None,
open_timeout=60
)
That was it!
Not really straightforward, but it works :)
[EDIT]: Forgot to mention it, the socks import is from the PySocks package.
That's the most reasonable way to do it for your use case that I can think of.
hi, How are we looking on this? is there any way to support HTTP TLS pass-through proxy? similarly to how AIOHTTP client does https://docs.aiohttp.org/en/stable/client_reference.html#aiohttp.ClientSession.ws_connect
@aaugustin hey, I created a package which exposes a subclass of connect with the additional proxy keyword argument. https://github.com/racinette/websockets_proxy
Thank you for sharing! I'm glad that you provided a third party solution, as this is one of the few long-lasting feature gaps in websockets.