txtorcon
txtorcon copied to clipboard
Adding support for tunneling an existing TLS tunnel through tor
I'd like to tunnel my TLS tunnel through tor, so that overall i'd have a tunnel like this: tor(TLS(my_protocol)). Not sure if this is possible, maybe a convenience method (server and client side) to start TLS later is the way to add support for it.
With txsocksx (which implements TLSWrapClientEndpoint with the help of TLSMemoryBIOFactory -> http://twistedmatrix.com/documents/current/api/twisted.protocols.tls.html ) it works like this: client.py
from __future__ import print_function
from twisted.internet.task import react
from twisted.internet.defer import inlineCallbacks
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.python.filepath import FilePath
from twisted.internet import ssl, task, protocol, endpoints, defer
from twisted.python.modules import getModule
from txsocksx.tls import TLSWrapClientEndpoint
from txsocksx.client import SOCKS5ClientEndpoint
import other_proto
@defer.inlineCallbacks
def main(reactor):
factory = protocol.Factory.forProtocol(other_proto.something)
ca_data = FilePath(b'ca_cert.pem').getContent()
client_data = FilePath(b'a.client.pem').getContent()
ca_cert = ssl.Certificate.loadPEM(ca_data)
client_key = ssl.PrivateCertificate.loadPEM(client_data)
options = ssl.optionsForClientTLS(u'the-authority', ca_cert, client_key)
torServerEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 9050)
exampleEndpoint = SOCKS5ClientEndpoint("remote_ip_here", 1234, torServerEndpoint)
tlsEndpoint = TLSWrapClientEndpoint(options, exampleEndpoint)
deferred = yield tlsEndpoint.connect(factory)
done = defer.Deferred()
deferred.connectionLost = lambda reason: done.callback(None)
yield done
task.react(main)
server.py
import sys
from twisted.python.filepath import FilePath
from twisted.internet import ssl, protocol, task, defer, endpoints
from twisted.python import log
from twisted.python.modules import getModule
from twisted.protocols.basic import LineReceiver
from twisted.protocols.tls import TLSMemoryBIOFactory
import other_proto
def main(reactor):
log.startLogging(sys.stdout)
ca_data = FilePath('ca_cert.pem').getContent()
ca_cert = ssl.Certificate.loadPEM(ca_data)
ca_key = ssl.PrivateCertificate.loadPEM(ca_data)
factory = protocol.Factory.forProtocol(other_proto.example)
options = ca_key.options(ca_cert)
tlsFactory = TLSMemoryBIOFactory(options, False, factory)
reactor.listenTCP(1234, tlsFactory)
return defer.Deferred()
task.react(main)
I also tried startTLS with which I inconveniently started TLS within my protocol implementation at a later time, so i guess txsocksx implementation is the way to go.
Did you try something like:
endpoint = txtorcon.TorClientEndpoint(server_ip, server_port)
tlsEndpoint = TLSWrapClientEndpoint(options, endpoint)
p.s. this would make a good addition to the examples/
if you get it working :)
Yes, that worked fine with txtorcon.TorClientEndpoint. Thanks for the hint. I had to specifically provide socks_hostname='127.0.0.1', else (i think) it'd pick automatically the ipv6 localhost ::1.
client.py
from twisted.internet.task import react
from twisted.internet.defer import inlineCallbacks
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.python.filepath import FilePath
from twisted.internet import ssl, task, protocol, endpoints, defer
from twisted.python.modules import getModule
from txsocksx.tls import TLSWrapClientEndpoint
import txtorcon
import other_proto
@defer.inlineCallbacks
def main(reactor):
factory = protocol.Factory.forProtocol(other_proto.DecisionProtocol)
ca_data = FilePath(b'ca_cert.pem').getContent()
client_data = FilePath(b'a.client.pem').getContent()
ca_cert = ssl.Certificate.loadPEM(ca_data)
client_key = ssl.PrivateCertificate.loadPEM(client_data)
options = ssl.optionsForClientTLS(u'the-authority', ca_cert, client_key)
exampleEndpoint = txtorcon.TorClientEndpoint(ip, 8966, socks_hostname="127.0.0.1")
tlsEndpoint = TLSWrapClientEndpoint(options, exampleEndpoint)
deferred = yield tlsEndpoint.connect(factory)
done = defer.Deferred()
deferred.connectionLost = lambda reason: done.callback(None)
yield done
task.react(main)
@meejah is it possible to achieve this behaviour using this on client?
tor = yield txtorcon.launch() #launch fresh tor ep=tor.stream_via(host,port,tls=True,socks_endpoint=SSL4ClientEndpointTwistedInstance) #connect to server (host, port) using tls and already created twisted TLS instance ep.connect(someFactory)
From what I understand, using txsocksx is not necessary from 2017, but I couldn't find any other sources for this tls usage.