txsocksx¶
txsocksx is SOCKS4/4a and SOCKS5 client endpoints for Twisted 10.1 or
greater. The code is available on github: https://github.com/habnabit/txsocksx
Examples¶
These examples assume familiarity with how to use Twisted endpoints. For simplicity, most of the examples will use SOCKS5.
Authenticating¶
One specifies authentication methods to a SOCKS5ClientEndpoint via the
methods parameter. For example, to connect using the username spam and
password eggs:
exampleEndpoint = SOCKS5ClientEndpoint(
'example.com', 6667, proxyEndpoint, methods={'login': ('spam', 'eggs')})
However, this will disable anonymous authentication. To use either login or anonymous authentication, specify both methods:
exampleEndpoint = SOCKS5ClientEndpoint(
'example.com', 6667, proxyEndpoint, methods={'login': ('spam', 'eggs'),
'anonymous': ()})
The methods dict must always map from a string to a tuple.
SOCKS4¶
SOCKS4 has no authentication, but does have a configurable “user ID” which defaults to an empty string:
exampleEndpoint = SOCKS4ClientEndpoint(
'example.com', 6667, proxyEndpoint, user='spam')
Connecting to a thing over tor¶
To connect to example.com on port 6667 over tor, one creates a
SOCKS5ClientEndpoint wrapping the endpoint of the tor server:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
exampleEndpoint = SOCKS5ClientEndpoint('example.com', 6667, torServerEndpoint)
Establishing the connection from there proceeds like usual:
deferred = exampleEndpoint.connect(someFactory)
txsocksx will not do any DNS resolution, so the hostname example.com
will not leak; tor will receive the hostname directly and do the DNS lookup
itself.
Tor allows connections by SOCKS4 or SOCKS5, and does not expect a user ID to be sent when using the SOCKS4 client.
Cancelling a connection¶
Sometimes one tires of waiting and wants to abort the connection attempt. For example, to abort the whole connection attempt after ten seconds:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
exampleEndpoint = SOCKS5ClientEndpoint('example.com', 6667, torServerEndpoint)
deferred = exampleEndpoint.connect(someFactory)
reactor.callLater(10, deferred.cancel)
This is a trivial example; real code should cancel the IDelayedCall returned
by reactor.callLater when the deferred fires. The code would then look like
this:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
exampleEndpoint = SOCKS5ClientEndpoint('example.com', 6667, torServerEndpoint)
deferred = exampleEndpoint.connect(someFactory)
canceler = reactor.callLater(10, deferred.cancel)
def cancelCanceler(result):
if canceler.active():
canceler.cancel()
return result
deferred.addBoth(cancelCanceler)
Making HTTP requests¶
Twisted’s builtin Agent HTTP client did not support being handed an
arbitrary endpoint before 15.0, so txsocksx provides an Agent for maximum
compatibility.
While txsocksx requires only Twisted 10.1, txsocksx.http requires Twisted
12.1 or greater. Its usage is almost identical to normal Agent usage:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
agent = SOCKS5Agent(reactor, proxyEndpoint=torServerEndpoint)
deferred = agent.request('GET', 'http://example.com/')
Note that the proxyEndpoint parameter must be passed as a keyword
argument. There is a second, optional, keyword-only argument for passing
additional arguments to the SOCKS5ClientEndpoint as SOCKS5Agent
constructs it:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
agent = SOCKS5Agent(reactor, proxyEndpoint=torServerEndpoint,
endpointArgs=dict(methods={'login': ('spam', 'eggs')}))
deferred = agent.request('GET', 'http://example.com/')
SOCKS5Agent transparently supports HTTPS via TLSWrapClientEndpoint.
For users with Twisted 15.0 or greater, SOCKS5Agent also implements
IAgentEndpointFactory.
Upgrading to TLS¶
Sometimes one wants to switch to speaking TLS as soon as the proxy negotiation
is finished. For that, there is txsocksx.tls. After wrapping an endpoint with
TLSWrapClientEndpoint, the connection will be upgraded to using TLS
immediately after proxy negotiation finishes:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
exampleEndpoint = SOCKS5ClientEndpoint('example.com', 6667, torServerEndpoint)
tlsEndpoint = TLSWrapClientEndpoint(exampleEndpoint)
deferred = tlsEndpoint.connect(someFactory)
Proxying over a proxy¶
Because of txsocksx‘s composable design, it’s trivial to connect from one SOCKS
proxy to another:
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
firstProxyEndpoint = SOCKS5ClientEndpoint(
'first-proxy.example.com', 1080, torServerEndpoint)
secondProxyEndpoint = SOCKS4ClientEndpoint(
'second-proxy.example.com', 1080, firstProxyEndpoint)
finalHop = SOCKS5ClientEndpoint(
'example.com', 113, secondProxyEndpoint)
deferred = finalHop.connect(someFactory)
API¶
txsocksx.client¶
SOCKS4/4a and SOCKS5 client endpoints.
-
class
txsocksx.client.SOCKS4ClientEndpoint(host, port, proxyEndpoint, user='')[source]¶ An endpoint which does SOCKS4 or SOCKS4a negotiation.
Parameters: - host – The hostname or IP to connect to through the SOCKS4 server. If
this is a valid IPv4 address, it will be sent to the server as a SOCKS4
request. Otherwise, host will be sent as a hostname in a SOCKS4a
request. In the SOCKS4a case, the hostname will not be resolved by
txsocksxbut will be sent without modification to the SOCKS4 server to be resolved remotely. - port – The port to connect to through the SOCKS4 server.
- proxyEndpoint – The endpoint of the SOCKS4 server. This must provide IStreamClientEndpoint.
- user – The user ID to send to the SOCKS4 server.
-
connect(fac)[source]¶ Connect over SOCKS4.
The provided factory will have its
buildProtocolmethod once a SOCKS4 connection has been successfully negotiated. Returns aDeferredwhich will fire with the resultingProtocolwhen negotiation finishes, or errback for a variety of reasons. For example:- If the
Deferredreturned byproxyEndpoint.connecterrbacks (e.g. the connection to the SOCKS4 server was refused). - If the SOCKS4 server gave a non-success response.
- If the SOCKS4 server did not reply with valid SOCKS4.
- If the
Deferredreturned fromconnectwas cancelled.
The returned
Deferredis cancelable during negotiation: the connection will immediately close and theDeferredwill errback with aCancelledError. TheDeferredcan be canceled before negotiation starts only if theDeferredreturned byproxyEndpoint.connectis cancelable.If the factory’s
buildProtocolreturnsNone, the connection will immediately close.- If the
- host – The hostname or IP to connect to through the SOCKS4 server. If
this is a valid IPv4 address, it will be sent to the server as a SOCKS4
request. Otherwise, host will be sent as a hostname in a SOCKS4a
request. In the SOCKS4a case, the hostname will not be resolved by
-
class
txsocksx.client.SOCKS5ClientEndpoint(host, port, proxyEndpoint, methods={'anonymous': ()})[source]¶ An endpoint which does SOCKS5 negotiation.
Parameters: - host – The hostname to connect to through the SOCKS5 server. This
will not be resolved by
txsocksxbut will be sent without modification to the SOCKS5 server to be resolved remotely. - port – The port to connect to through the SOCKS5 server.
- proxyEndpoint – The endpoint of the SOCKS5 server. This must provide IStreamClientEndpoint.
- methods – The authentication methods to try.
Authentication methods are specified as a dict mapping from method names to tuples. By default, the only method tried is anonymous authentication, so the default methods is
{'anonymous': ()}.The
anonymousauth method must map to an empty tuple if provided.The other method available by default is
login.loginmust map to a tuple of(username, password).-
connect(fac)[source]¶ Connect over SOCKS5.
The provided factory will have its
buildProtocolmethod once a SOCKS5 connection has been successfully negotiated. Returns aDeferredwhich will fire with the resultingProtocolwhen negotiation finishes, or errback for a variety of reasons. For example:- If the
Deferredreturned byproxyEndpoint.connecterrbacks (e.g. the connection to the SOCKS5 server was refused). - If the SOCKS5 server gave a non-success response.
- If the SOCKS5 server did not reply with valid SOCKS5.
- If the
Deferredreturned fromconnectwas cancelled.
The returned
Deferredis cancelable during negotiation: the connection will immediately close and theDeferredwill errback with aCancelledError. TheDeferredcan be canceled before negotiation starts only if theDeferredreturned byproxyEndpoint.connectis cancelable.If the factory’s
buildProtocolreturnsNone, the connection will immediately close.- If the
- host – The hostname to connect to through the SOCKS5 server. This
will not be resolved by
txsocksx.http¶
-
class
txsocksx.http.SOCKS4Agent(*a, proxyEndpoint, endpointArgs={}, **kw)[source]¶ An Agent which connects over SOCKS4.
See
SOCKS5Agentfor details.-
endpointFactory¶ alias of
SOCKS4ClientEndpoint
-
-
class
txsocksx.http.SOCKS5Agent(*a, proxyEndpoint, endpointArgs={}, **kw)[source]¶ An
Agentwhich connects over SOCKS5.Parameters: - proxyEndpoint – The same as proxyEndpoint for
SOCKS5ClientEndpoint: the endpoint of the SOCKS5 proxy server. This argument must be passed as a keyword argument. - endpointArgs – A dict of keyword arguments which will be passed when
constructing the
SOCKS5ClientEndpoint. For example, this could be{'methods': {'anonymous': ()}}.
The rest of the parameters, methods, and overall behavior is identical to Agent. The
connectTimeoutandbindAddressarguments will be ignored and should be specified when constructing the proxyEndpoint.If used with Twisted 15.0 or greater, this class will also implement IAgentEndpointFactory.
-
endpointFactory¶ alias of
SOCKS5ClientEndpoint
- proxyEndpoint – The same as proxyEndpoint for
txsocksx.tls¶
TLS convenience wrappers for endpoints.
-
class
txsocksx.tls.TLSWrapClientEndpoint(contextFactory, wrappedEndpoint)[source]¶ An endpoint which automatically starts TLS.
Parameters: - contextFactory – A ContextFactory instance.
- wrappedEndpoint – The endpoint to wrap.
-
connect(fac)[source]¶ Connect to the wrapped endpoint, then start TLS.
The TLS negotiation is done by way of wrapping the provided factory with TLSMemoryBIOFactory during connection.
Returns: A Deferredwhich fires with the sameProtocolaswrappedEndpoint.connect(fac)fires with. If thatDeferrederrbacks, so will the returned deferred.