I'm trying to write an SSH proxy in Twisted, that intercepts SSH traffic and forwards it to a back-end ssh server.
On the front-end I'm using a modified Conch, with the following code subclassed as SSHSession:
def request_exec(self, data):
cmd,data = common.getNS(data)
log.msg('executing command "%s"' % cmd)
prot = session.SSHSessionClient()
prot.transport = self
pf = _ProtocolFactory(prot)
ep = endpoints.SSHCommandClientEndpoint.newConnection(reactor, cmd,
USER, HOST, port=PORT, password=PASSWORD)
ep.connect(pf)
self.client = prot
return 1
The _ProtocolFactory class looks like this:
class _ProtocolFactory():
"""
Factory to return the (existing) ssh session to pass to ssh command endpoint
It does not actually function as a factory
"""
def __init__(self, protocol):
self.protocol = protocol
def buildProtocol(self, addr):
return self.protocol
The entire thing accepts connections from users, and I can see it successfully logs in into the back-end.
The issue I'm having is with connecting the stdout/stdin channels to each other. The SSHSession on the back-end connection needs to be connected to the SSHSession on the front-end. I've tried to do that with the Protocol as an in-between, but I don't think this is correct.
Update: one-way data transfer is working by using a custom Protocol that translates client/server functions around (so dataReceived is mapped to write, and vice versa:
class InBetween(protocol.Protocol):
"""
This is the glue between the SSH server one one side and the
SSH client on the other side
"""
transport = None # Transport is the back-end the ssh-server
client = None # Client is the front-end, the ssh-client
buf = "" # buffer to send to back-end
def write(self, bytes):
# This is data going from the end-user to the back-end
if not self.transport:
self.buf += bytes
return
elif len(self.buf) and self.transport != None:
self.transport.dataReceived(self.buf)
self.buf = None
self.transport.dataReceived(bytes)
def dataReceived(self, data):
# This is data going from the back-end to the end-user
self.client.write(data)