Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SOCKS proxies to connect() #475

Open
aaugustin opened this issue Sep 23, 2018 · 12 comments
Open

Add support for SOCKS proxies to connect() #475

aaugustin opened this issue Sep 23, 2018 · 12 comments

Comments

@aaugustin
Copy link
Member

aaugustin commented Sep 23, 2018

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 #475 (comment) for details.

@oliver-zehentleitner
Copy link
Contributor

would be a great feature!

@aaugustin
Copy link
Member Author

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.

@aaugustin
Copy link
Member Author

aaugustin commented Jun 30, 2019

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.

@lgrahl
Copy link
Collaborator

lgrahl commented Jul 1, 2019

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.)

@aaugustin
Copy link
Member Author

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.

@Narzhan
Copy link

Narzhan commented May 18, 2020

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)?

@aaugustin
Copy link
Member Author

No progress.

@blackint-kge
Copy link

blackint-kge commented Oct 5, 2022

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.

@aaugustin
Copy link
Member Author

That's the most reasonable way to do it for your use case that I can think of.

@mattkoltun
Copy link

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

@racinette
Copy link

@aaugustin hey, I created a package which exposes a subclass of connect with the additional proxy keyword argument. https://github.com/racinette/websockets_proxy

@aaugustin
Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants