Advertisement
Guest User

Untitled

a guest
Jan 15th, 2016
2,968
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.76 KB | None | 0 0
  1. #!/usr/bin/python
  2. #
  3. # This is the relay script mentioned in http://blog.zorinaq.com/?e=81
  4. #
  5. # Listens on the address and port specified by --local-ip and --local-port, and
  6. # relay all connections to the endpoint specified by --remote-hosts and
  7. # --remote-port. Multiple remote hosts can be specified: one will be selected
  8. # randomly for each connection.
  9. #
  10. # Optionally, if --mode 1:<secret> is specified, insert the secret key as the
  11. # first bytes of data transmitted through each relayed connection, and if
  12. # --mode 2:<secret> is specified, verify and remove the secret key (ignore
  13. # the connection by discarding all data if the key does not match).
  14. #
  15. # I recommend a long hex string for the secret, for example:
  16. # $ secret=`ps aux | md5sum | cut -c 1-32`
  17. # $ ./tcprelay-secret-exp.py [...] -m 1:"$secret"
  18.  
  19. #import asyncake
  20. import asyncore
  21. import socket, random, struct
  22. import re
  23.  
  24. class forwarder(asyncore.dispatcher):
  25.     def __init__(self, ip, port, remoteip, remoteport, mode, secret, backlog=600):
  26.         asyncore.dispatcher.__init__(self)
  27.         self.remoteip=remoteip
  28.         self.remoteport=remoteport
  29.         self.mode=mode
  30.         self.secret=secret
  31.         self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
  32.         self.set_reuse_addr()
  33.         self.bind((ip,port))
  34.         self.listen(backlog)
  35.  
  36.     def handle_accept(self):
  37.         conn, addr = self.accept()
  38.         # print '--- Connect --- '
  39.         sender(receiver(conn, addr[0], self.mode, self.secret),self.remoteip,self.remoteport, addr[0])
  40.  
  41. class receiver(asyncore.dispatcher):
  42.     def __init__(self, conn, client_ip, mode, secret):
  43.         asyncore.dispatcher.__init__(self,conn)
  44.         self.mode=mode
  45.         self.secret=secret
  46.         self.from_remote_buffer=''
  47.         self.to_remote_buffer=''
  48.         self.sender=None
  49.         self.client_ip = client_ip
  50.         self.zero_bytes_forwarded = True
  51.         # for framing
  52.         self.look_for_type = True
  53.         self.field_type = None
  54.         self.look_for_len_byte_nr = None
  55.         self.field_len = None
  56.         self.bytes_left_to_extract = None
  57.  
  58.     def handle_connect(self):
  59.         pass
  60.  
  61.     def detect_and_remove_framing(self, read):
  62.         processed_read = ''
  63.         for b in read:
  64.             if self.look_for_type:
  65.                 self.field_type = b
  66.                 self.look_for_type = False
  67.                 self.look_for_len_byte_nr = 0
  68.                 self.field_len = 0
  69.             elif self.look_for_len_byte_nr != None:
  70.                 self.field_len <<= 8
  71.                 self.field_len += ord(b)
  72.                 self.look_for_len_byte_nr += 1
  73.                 if self.look_for_len_byte_nr >= 2:
  74.                     self.look_for_len_byte_nr = None
  75.                     self.bytes_left_to_extract = self.field_len
  76.             elif self.bytes_left_to_extract != None:
  77.                 if self.field_type == 'd':
  78.                     processed_read += b
  79.                 else:
  80.                     pass
  81.                 self.bytes_left_to_extract -= 1
  82.                 if self.bytes_left_to_extract == 0:
  83.                     self.bytes_left_to_extract = None
  84.                     self.look_for_type = True
  85.         return processed_read
  86.  
  87.     def handle_read(self):
  88.         """Read from TCP client."""
  89.         read = self.recv(4096)
  90.         if self.mode == '1': # insert the secret key
  91.             # Implement simple framing ('d' for data packets, 'p' for padding packets)
  92.             read = 'd' + struct.pack('>h', len(read)) + read
  93.             rlen = 0
  94.             padding = 1
  95.             if padding == 0: # no padding
  96.                 rlen = 0
  97.             elif padding == 1 and len(read) < 1500: # padding
  98.                 if len(read) < 1000:
  99.                     rlen = random.randint(1000 - len(read), 1500 - len(read))
  100.                 else:
  101.                     rlen = random.randint(0, 1500 - len(read))
  102.             if rlen:
  103.                 read += 'p' + struct.pack('>h', rlen) + ('_' * rlen)
  104.             if self.zero_bytes_forwarded:
  105.                 read = self.secret + read
  106.                 self.zero_bytes_forwarded = False
  107.         elif self.mode == '2': # verify and remove the secret key
  108.             if self.zero_bytes_forwarded:
  109.                 if read.startswith(self.secret):
  110.                     read = read[len(self.secret):]
  111.                     self.zero_bytes_forwarded = False
  112.                 else:
  113.                     read = ''
  114.             read = self.detect_and_remove_framing(read)
  115.         # print '%04i -->'%len(read)
  116.         self.from_remote_buffer += read
  117.  
  118.     def writable(self):
  119.         return (len(self.to_remote_buffer) > 0)
  120.  
  121.     def handle_write(self):
  122.         sent = self.send(self.to_remote_buffer)
  123.         # print '%04i <--'%sent
  124.         self.to_remote_buffer = self.to_remote_buffer[sent:]
  125.  
  126.     def handle_close(self):
  127.         self.close()
  128.         if self.sender:
  129.             self.sender.close()
  130.  
  131. class sender(asyncore.dispatcher):
  132.     def __init__(self, receiver, remoteaddr, remoteport, client_ip):
  133.         asyncore.dispatcher.__init__(self)
  134.         self.receiver=receiver
  135.         receiver.sender=self
  136.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  137.         self.connect((random.choice(remoteaddr), remoteport))
  138.  
  139.     def handle_connect(self):
  140.         pass
  141.  
  142.     def handle_read(self):
  143.         """Read from TCP server."""
  144.         read = self.recv(4096)
  145.         # print '<-- %04i'%len(read)
  146.         self.receiver.to_remote_buffer += read
  147.  
  148.     def writable(self):
  149.         return (len(self.receiver.from_remote_buffer) > 0)
  150.  
  151.     def handle_write(self):
  152.         sent = self.send(self.receiver.from_remote_buffer)
  153.         # print '--> %04i'%sent
  154.         self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]
  155.  
  156.     def handle_close(self):
  157.         # when the buffer has not yet fully been written to the client, don't close quite yet.
  158.         # handle_close() will be automatically called again by asyncore
  159.         if not self.receiver.to_remote_buffer:
  160.             self.close()
  161.             self.receiver.close()
  162.  
  163. if __name__=='__main__':
  164.     import optparse
  165.     parser = optparse.OptionParser()
  166.  
  167.     parser.add_option(
  168.             '-l','--local-ip',
  169.             dest='local_ip',default='127.0.0.1',
  170.             help='Local IP address to bind to (for listening socket)')
  171.     parser.add_option(
  172.             '-p','--local-port',
  173.             type='int',dest='local_port',
  174.             help='Local port to bind to')
  175.     parser.add_option(
  176.             '-P','--remote-port',
  177.             type='int',dest='remote_port',
  178.             help='Remote port to connect to')
  179.     parser.add_option(
  180.             '-r','--remote-hosts',
  181.             type='string',dest='remote_hosts',default='127.0.0.1',
  182.             help='Remote host(s) to connect to, comma-separated')
  183.     parser.add_option(
  184.             '-m','--mode',
  185.             type='string',dest='mode',
  186.             help='Operating mode ("0" for not using a secret key, ' + \
  187.                     '"1:<secret>" for using/inserting the specified secret key, ' + \
  188.                     '"2:<secret>" for verifying/stripping the specified secret key')
  189.     options, args = parser.parse_args()
  190.     alladdresses = {}
  191.     for h in options.remote_hosts.split(','):
  192.         (name, aliaslist, addresslist) = socket.gethostbyname_ex(h)
  193.         for a in addresslist:
  194.             alladdresses[a] = None
  195.     if options.mode is None:
  196.         (mode, secret) = (None, None)
  197.     else:
  198.         (mode, secret) = options.mode.split(':', 1)
  199.         if len(secret) < 32:
  200.             raise Exception('secret specified in -m option needs to be at least 32 characters long')
  201.     #x = asyncake.AsynCake()
  202.     forwarder(options.local_ip, options.local_port, alladdresses.keys(), options.remote_port, mode, secret)
  203.     #x.loop()
  204.     asyncore.loop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement