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
txsocksx
but 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
buildProtocol
method once a SOCKS4 connection has been successfully negotiated. Returns aDeferred
which will fire with the resultingProtocol
when negotiation finishes, or errback for a variety of reasons. For example:- If the
Deferred
returned byproxyEndpoint.connect
errbacks (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
Deferred
returned fromconnect
was cancelled.
The returned
Deferred
is cancelable during negotiation: the connection will immediately close and theDeferred
will errback with aCancelledError
. TheDeferred
can be canceled before negotiation starts only if theDeferred
returned byproxyEndpoint.connect
is cancelable.If the factory’s
buildProtocol
returnsNone
, 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
txsocksx
but 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
anonymous
auth method must map to an empty tuple if provided.The other method available by default is
login
.login
must map to a tuple of(username, password)
.-
connect
(fac)[source]¶ Connect over SOCKS5.
The provided factory will have its
buildProtocol
method once a SOCKS5 connection has been successfully negotiated. Returns aDeferred
which will fire with the resultingProtocol
when negotiation finishes, or errback for a variety of reasons. For example:- If the
Deferred
returned byproxyEndpoint.connect
errbacks (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
Deferred
returned fromconnect
was cancelled.
The returned
Deferred
is cancelable during negotiation: the connection will immediately close and theDeferred
will errback with aCancelledError
. TheDeferred
can be canceled before negotiation starts only if theDeferred
returned byproxyEndpoint.connect
is cancelable.If the factory’s
buildProtocol
returnsNone
, 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
SOCKS5Agent
for details.-
endpointFactory
¶ alias of
SOCKS4ClientEndpoint
-
-
class
txsocksx.http.
SOCKS5Agent
(*a, proxyEndpoint, endpointArgs={}, **kw)[source]¶ An
Agent
which 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
connectTimeout
andbindAddress
arguments 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 Deferred
which fires with the sameProtocol
aswrappedEndpoint.connect(fac)
fires with. If thatDeferred
errbacks, so will the returned deferred.