sm4rtn0bit4

simple_proxy_using_socket

Mar 15th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.79 KB | None | 0 0
  1. #!/usr/bin/python3
  2. import time
  3. import socket
  4. import sys
  5. import select
  6. import threading
  7. import zlib,gzip
  8. #
  9. # manual input for necessary options/args
  10. #
  11. max_conn=200
  12. buffer_size=4096
  13. delay=0.001
  14. #
  15. try:
  16.     port=input('Enter port to listen: ')
  17. except KeyboardInterrupt:
  18.     print("User Interrupted the process execution")
  19.     sys.exit(0)
  20. ##
  21. #   data forward class
  22. ##
  23. class Forward:
  24.     def __init__(self):
  25.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  26.         #self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  27.  
  28. ##
  29. #   function for forwarding connections to it's desired target
  30. ##
  31.     def forward(self,clientsock,clientdata,clientaddr):
  32.         try:
  33.             data=clientdata.decode('utf-8')
  34.             #print("Data: ",data)
  35.             first_line=clientdata.split('\n')[0]
  36.             url=first_line.split(' ')[1]
  37.             #print("url: ",url)
  38.             http_pos=url.find("://")# finding positonn of http tag
  39.             #print("http_pos",http_pos)#########
  40.             if (http_pos==-1):
  41.                 temp=url
  42.             else:
  43.                 temp =url[(http_pos+3):]# concating rest url
  44.             #print("temp",temp)
  45.             port_pos=temp.find(':')# find the position of posrt if any
  46.             webserver_pos=temp.find("/")#end of web server
  47.             #print("port_pos",port_pos,"webserver_pos",webserver_pos)
  48.             if webserver_pos== -1:
  49.                 webserver_pos=len(temp)-(len(temp)-port_pos)
  50.             #webserver_pos=""
  51.                 port=temp[port_pos+1:]
  52.             else:
  53.                 port= -1
  54.             #print("port_pos1",port_pos,"webserver_pos1",webserver_pos,"port: ",port)
  55.             if (port == -1 or webserver_pos<port_pos):
  56.                 port=80
  57.                 webserver=temp[:webserver_pos]
  58.             #   print("Web and port 1 : ",webserver,port)
  59.             else:
  60.             #specific port
  61.                 #port=int((temp[(port_pos+1):])[:(webserver-port_pos-1)])
  62.                 webserver=temp[:port_pos]
  63.                 data=bytes(data.encode('utf-8'))
  64.             #print("Webserver and port : ",webserver,port)
  65.             #print("Web and port 3 : ",webserver,port)
  66. #
  67. #
  68.             try:
  69.                 print("webserver: ",webserver,"  Port: ",port)
  70.                 port=int(float(port))
  71.                 self.s.connect((webserver,port))
  72.                 print("client: %s and frwd data to: %s "%(clientaddr,webserver),self.s.getpeername())
  73.                 #print(self.s.getpeername())
  74.                 #print("connected Sucessfully server:port ",webserver,port)
  75.                 #clientdata=self.s.recv(4096)
  76.                 self.s.sendall(clientdata)
  77.                
  78.                 return self.s
  79.             except Exception, e:
  80.                 print (e,"Error in frwding request to target server/client")
  81.         #
  82.         #
  83.         except Exception as e:
  84.             print("\nException in connection_string\n")
  85.             print(e,'\n')
  86.  
  87. ##
  88. #
  89. #   preparing proxy server class and it's methods
  90. #
  91. ##
  92. class proxy_server:
  93.     current_input_list=[]
  94.     active_channels={}
  95.     client_sockobj_addr={}
  96. #  
  97. #   Prepared server socket for listening connections
  98. #
  99.     def __init__(self, host, port):
  100.         self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  101.         self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  102.         self.server.bind((host, port))
  103.         self.server.listen(max_conn)
  104. ##
  105. #   decompressing func for content
  106. ##
  107.     def decompress(self,compressed_data):
  108.         return zlib.decompress(compressed_data, -15)
  109. ##
  110. #   Defining continous loop for detecting
  111. #   new clients and requests to proxy server.
  112. ##
  113.     def loop(self):
  114.         self.current_input_list.append(self.server) # server socket appended as initial
  115.         count_on_rcv =0
  116.         count_on_accept=0
  117.         count_on_disconnect=0
  118.         while True:
  119.             time.sleep(delay)
  120.             ss=select.select
  121.             inputready, outputready, exceptready = ss(self.current_input_list, [], [])
  122.             for self.s in inputready:   # it's a new connection or client
  123.                 #self.data = self.s.recv(buffer_size).decode('utf-8')
  124.                 if self.s == self.server:
  125.                     #self.on_accept()
  126.                     count_on_accept+=1
  127.                     #print
  128.                     #print("*"*50)
  129.                     print
  130.                     print("# on_accept ",count_on_accept)
  131.                     t_accept=threading.Thread(target=self.on_accept)
  132.                     t_accept.start()
  133.                     t_accept.join()
  134.                     break
  135.                 self.data = self.recv_timeout(self.s)
  136.                 if not self.data:
  137.                     break
  138.                    
  139. #
  140. # disconnects if recv data is 0 Bytes
  141. #
  142.                 if len(self.data) == 0:
  143.                     #self.on_close()
  144.                     count_on_disconnect+=1
  145.                     print
  146.                     print("# on_close ",count_on_disconnect)
  147.                     t_disconnect=threading.Thread(target=self.on_close)
  148.                     t_disconnect.start()
  149.                     t_disconnect.join()
  150.                     #print
  151.                     #print("*"*50)
  152.                     print
  153.                     break
  154.                 else:                         # Recieve data fron end side
  155.                     #self.on_recv()
  156.                     count_on_rcv+=1
  157.                     print
  158.                     print("# on_rcv ",count_on_rcv)
  159.                     t_recv=threading.Thread(target=self.on_recv)
  160.                     t_recv.start()
  161.                     t_recv.join()
  162. ##
  163. #   DEFINING FUNCTION BLOCKS on_accept(), on_close(), and on_recieve()
  164. ##
  165.     def on_accept(self):
  166.         clientsock, clientaddr = self.server.accept()
  167.         clientdata = self.recv_timeout(clientsock)
  168.         print clientdata.decode('utf-8')
  169.         #clientdata=clientsock.recv(buffer_size).decode('utf-8')
  170. #
  171. # client sock is current socket state for specific client
  172. # client addr is like complete socket addr (127.0.0.1, 47523)
  173. #
  174.         #print(clientsock,clientaddr)
  175.         #t_frwd=threading.Thread(target=Forward().forward,args=(clientsock,clientdata,clientaddr))
  176.         #t_frwd.start()
  177.         #forward=t_frwd.join()
  178.         forward = Forward().forward(clientsock,clientdata,clientaddr)
  179.         if forward:
  180.             print clientaddr, "has connected (on_accept)"
  181.             #print("forward",forward)
  182.             self.current_input_list.append(clientsock)
  183.             self.current_input_list.append(forward)
  184.             self.active_channels[clientsock] = forward
  185.             self.active_channels[forward] = clientsock
  186.         else:
  187.             print "Can't establish connection with remote server.(on_accept exception)",
  188.             print "Closing connection with client side (on_accept exception)", clientaddr
  189.             clientsock.close()
  190.  
  191.     def on_close(self):
  192.         print self.s.getpeername(), " disconnected (on_close)"
  193. #remove objects from current_input_list
  194.         self.current_input_list.remove(self.s)
  195.         self.current_input_list.remove(self.active_channels[self.s])
  196.         out = self.active_channels[self.s]
  197. # close the connection with client
  198.         self.active_channels[out].close()  # equivalent to do self.s.close()
  199. # close the connection with remote server
  200.         self.active_channels[self.s].close()
  201. # delete both objects from channel dict
  202.         del self.active_channels[out]
  203.         del self.active_channels[self.s]
  204.  
  205.     def on_recv(self):
  206.         print self.s.getpeername()," recieved data from here (on_recv)"
  207.         data = self.data
  208. # here we can parse and/or modify the data before send forward
  209.         print data
  210.         self.active_channels[self.s].send(data)
  211. ##
  212. #   data recieving function for complete data fetch from socket
  213. ##
  214.     def recv_timeout(self,the_socket,timeout=0.1):
  215.         #make socket non blocking
  216.         the_socket.setblocking(0)
  217.         #total data partwise in an array
  218.         total_data=[];
  219.         data='';
  220.        
  221.         #beginning time
  222.         begin=time.time()
  223.         while 1:
  224.             #if you got some data, then break after timeout
  225.             if total_data and time.time()-begin > timeout:
  226.                 break
  227.              
  228.             #if you got no data at all, wait a little longer, twice the timeout
  229.             elif time.time()-begin > timeout*2:
  230.                 break
  231.              
  232.             #recv something
  233.             try:
  234.                 data = the_socket.recv(buffer_size)
  235.                 if data:
  236.                     total_data.append(data)
  237.                     #change the beginning time for measurement
  238.                     begin = time.time()
  239.                 else:
  240.                     #sleep for sometime to indicate a gap
  241.                     time.sleep(0.1)
  242.             except:
  243.                 pass
  244.          
  245.         #join all parts to make final string
  246.         #Send notification to proxy server#
  247.         data_recieved=float(len(str(''.join(total_data))))
  248.         data_recieved=float(data_recieved/1024)
  249.         data_recieved="%.3s"%str(data_recieved)
  250.         data_size="%s KB "%(data_recieved)
  251.         if data_recieved == "0.0":
  252.             pass
  253.         else:
  254.             print("[+]%s Data Recieved. "%(str(data_size)))
  255.         #
  256.         total_data=''.join(total_data)
  257.         #self.decompress(total_data)
  258.         return total_data
  259.  
  260. if __name__ == '__main__':
  261.         server = proxy_server('0.0.0.0',port)
  262.         try:
  263.             server.loop()
  264.         except KeyboardInterrupt:
  265.             print "Ctrl C - Stopping server"
  266.             sys.exit(1)
Add Comment
Please, Sign In to add comment