Advertisement
3nvisi0n

miniMitM

Feb 15th, 2015
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.51 KB | None | 0 0
  1. import BaseHTTPServer, select, socket, SocketServer, urlparse
  2.  
  3. #Http server + threading mixin
  4. class ThreadingHTTPServer (SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): pass
  5.  
  6. class HTTPProxy (BaseHTTPServer.BaseHTTPRequestHandler):
  7.     rbufsize = 0  #Unbuffered file reader
  8.  
  9.  
  10.     #Utility function to give a chance to modify self.headers before proxying
  11.     def modifyOutboundHeaders(self):
  12.         #Can add or modify outbound headers here, setting cookies or whatever
  13.         return
  14.  
  15.     #Utility to modify output data before proxying
  16.     def modifyOutboundData(self,data):
  17.         return data
  18.  
  19.     #utility function to modify response data(headers and body)
  20.     def modifyResponse(self, data):
  21.         #Modify data as fit
  22.         return data
  23.  
  24.     #Just a little function to handle output, didn't use it much but thought I might
  25.     def trace(self, msg):
  26.         print msg
  27.  
  28.     #Performs the actual proxy connection
  29.     def connect(self, location, soc):
  30.             #Parse connection information
  31.             i = location.find(':')
  32.             if i >= 0:
  33.                 host = location[:i]
  34.                 port = int(location[i+1:])
  35.             else:
  36.                 host = location
  37.                 port = 80
  38.             self.trace("Connecting to %s:%d" % (host,port))
  39.  
  40.             #Try to connect
  41.             try:
  42.                 soc.connect((host,port))
  43.             except socket.error, arg:
  44.                 try: msg = arg[1]
  45.                 except: msg = arg
  46.                 self.send_error(503, msg)
  47.                 return False
  48.             return True
  49.  
  50.     #Reads data from either proxied connection or client and redirects it to the other
  51.     def redirectData(self, soc, idleCount=50):
  52.         loops = 0 #Tracks loops without reading; if we idle too long kill the connection
  53.         while True:
  54.             loops += 1
  55.             (reads,_,errs) = select.select([self.connection, soc], [], [self.connection, soc])
  56.            
  57.             #Leave loop once we get an error as there is nothing left
  58.             if errs: break
  59.  
  60.             #Read the data if anything and send it to the other source
  61.             if reads:
  62.                 for i in reads:
  63.                     data = i.recv(8192)
  64.                     if data:
  65.                         loops = 0
  66.                         if i is soc:
  67.                             data = self.modifyResponse(data)
  68.                             self.connection.send(data)
  69.                         else:
  70.                             data = self.modifyOutboundData(data)
  71.                             soc.send(data)
  72.             if loops >= idleCount: break
  73.  
  74.     def do_CONNECT(self):
  75.         soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  76.         try:
  77.             if self.connect(self.path, soc):
  78.                 #Successful connection
  79.                 self.trace("Connected.")
  80.                 self.wfile.write(self.protocol_version + " 200 Connection established\r\n")
  81.                 self.wfile.write("\r\n")
  82.                 self.redirectData(soc, 300)
  83.         finally: soc.close()
  84.  
  85.  
  86.     def do_GET(self):
  87.         (proto, host, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
  88.         if proto != 'http' or not host:
  89.             self.send_error(500, "No support for HTTPS or no host provided.")
  90.             return
  91.         soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  92.         try:
  93.             if self.connect(host, soc):
  94.                 soc.send("%s %s %s\r\n" % (self.command,urlparse.urlunparse(('', '', path, params, query, '')),self.request_version))
  95.                 #Don't bother dealing with keep-alives
  96.                 self.headers['Connection'] = 'close'
  97.                
  98.                 self.modifyOutboundHeaders()
  99.                 #Send the headers to socket
  100.                 for key_val in self.headers.items():
  101.                     soc.send("%s: %s\r\n" % key_val)
  102.                 soc.send("\r\n")
  103.                 self.redirectData(soc)
  104.         finally:
  105.             soc.close()
  106.             self.connection.close()
  107.  
  108.     #GET is generic enough that it handles everything
  109.     do_POST   = do_GET
  110.     do_HEAD   = do_GET
  111.     do_PUT    = do_GET
  112.     do_DELETE = do_GET
  113.  
  114. if __name__ == '__main__':
  115.     #Run the server, default is port 8000 but argv[1] is read to determine port
  116.     BaseHTTPServer.test(HTTPProxy, ThreadingHTTPServer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement