tcp-proxy.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/usr/bin/env python3
  2. import sys
  3. import re
  4. from twisted.internet import defer
  5. from twisted.internet import protocol
  6. from twisted.internet import reactor
  7. from twisted.python import log
  8. from twisted.enterprise import adbapi
  9. # Connect to:
  10. HOST = "127.0.0.1"
  11. PORT = 2002
  12. # Listen on:
  13. LISTEN_PORT = 9999
  14. LISTEN_ON = "127.0.0.1"
  15. class ProxyClientProtocol(protocol.Protocol):
  16. def __init__(self):
  17. self.user = None
  18. self.dbinit = False
  19. self.db = None
  20. self.buffer = ""
  21. self.lines = list()
  22. def connectionMade(self):
  23. log.msg("Client: connected to peer")
  24. self.cli_queue = self.factory.cli_queue
  25. self.cli_queue.get().addCallback(self.serverDataReceived)
  26. def serverDataReceived(self, chunk):
  27. # rlogin looks like this: \x00 password \x00 username \x00 terminal/speed \x00
  28. # b'\x00up2lat3\x00bugz\x00ansi-bbs/115200\x00'
  29. # We're looking for 4 \x00!
  30. # TODO: Line processing, and line cleaning (remove ANSI color codes)
  31. if chunk is False:
  32. self.cli_queue = None
  33. log.msg("Client: disconnecting from peer")
  34. self.factory.continueTrying = False
  35. self.transport.loseConnection()
  36. else:
  37. self.buffer += chunk.decode("utf-8")
  38. if self.user is None:
  39. # Ok, process this
  40. # self.buffer += chunk.decode('utf-8')
  41. # We don't have the username yet
  42. parts = self.buffer.split("\x00")
  43. if len(parts) >= 5:
  44. # Got it!
  45. self.user = parts[1]
  46. log.msg("User: {0}".format(self.user))
  47. # Reset buffer -- remove everything before last \x00
  48. zpos = self.buffer.rindex("\x00")
  49. self.buffer = self.buffer[zpos + 1 :]
  50. # init sqlite db using the username
  51. else:
  52. # process the buffer
  53. # Handle backspaces by deleting previous character.
  54. pos = self.buffer.find("\x08")
  55. while pos != -1:
  56. # Ok, there's a backspace, so:
  57. self.buffer = self.buffer[0 : pos - 1] + self.buffer[pos + 1 :]
  58. pos = self.buffer.find("\x08")
  59. # There won't be ansi color codes from the user!
  60. # There will be \r\n (If I remember correctly)
  61. pos = self.buffer.find("\r")
  62. while pos != -1:
  63. line = self.buffer[0:pos]
  64. self.lines.append(line)
  65. log.msg("L> {0}".format(line))
  66. self.buffer = self.buffer[pos + 1 :]
  67. pos = self.buffer.find("\r")
  68. #
  69. #
  70. # Strip out ANSI color codes
  71. # self.buffer = re.sub(r'\x1b[\d;?\d+m', '', self.buffer)
  72. # Process lines ...
  73. self.transport.write(chunk)
  74. self.cli_queue.get().addCallback(self.serverDataReceived)
  75. # elif b"$" == chunk:
  76. # self.factory.svr_queue.put(b"HELLO.\r\n")
  77. # self.cli_queue.get().addCallback(self.serverDataReceived)
  78. # elif self.cli_queue:
  79. # log.msg("Client: writing %d bytes to peer" % len(chunk))
  80. # log.msg(">>", repr(chunk))
  81. # self.transport.write(chunk)
  82. # self.cli_queue.get().addCallback(self.serverDataReceived)
  83. # else:
  84. # self.factory.cli_queue.put(chunk)
  85. def dataReceived(self, chunk):
  86. # log.msg("Client: %d bytes received from peer" % len(chunk))
  87. # clean, strip ANSI, etc.
  88. log.msg("<<", repr(chunk))
  89. self.factory.svr_queue.put(chunk)
  90. def connectionLost(self, why):
  91. log.msg("connectionLost because: %s" % why)
  92. # if self.cli_queue:
  93. # self.cli_queue = None
  94. # log.msg("Client: peer disconnect unexpectedly")
  95. self.factory.svr_queue.put(False)
  96. self.cli_queue = None
  97. self.transport.loseConnection()
  98. class ProxyClientFactory(protocol.ClientFactory):
  99. maxDelay = 10
  100. protocol = ProxyClientProtocol
  101. def __init__(self, svr_queue, cli_queue):
  102. self.svr_queue = svr_queue
  103. self.cli_queue = cli_queue
  104. # ProxyServer is created for each connection
  105. class ProxyServer(protocol.Protocol):
  106. def connectionMade(self):
  107. self.svr_queue = defer.DeferredQueue()
  108. self.cli_queue = defer.DeferredQueue()
  109. self.svr_queue.get().addCallback(self.clientDataReceived)
  110. factory = ProxyClientFactory(self.svr_queue, self.cli_queue)
  111. reactor.connectTCP(HOST, PORT, factory)
  112. def clientDataReceived(self, chunk):
  113. if chunk is False:
  114. self.transport.loseConnection()
  115. else:
  116. log.msg("Server: writing %d bytes to original client" % len(chunk))
  117. self.transport.write(chunk)
  118. self.svr_queue.get().addCallback(self.clientDataReceived)
  119. def dataReceived(self, chunk):
  120. log.msg("Server: %d bytes received" % len(chunk))
  121. self.cli_queue.put(chunk)
  122. def connectionLost(self, why):
  123. log.msg("lost connection %s" % why)
  124. self.cli_queue.put(False)
  125. if __name__ == "__main__":
  126. log.startLogging(sys.stdout)
  127. factory = protocol.Factory()
  128. factory.protocol = ProxyServer
  129. reactor.listenTCP(LISTEN_PORT, factory, interface=LISTEN_ON)
  130. reactor.run()