A simple proxy server is implemented with just 50 lines of Python code

  • 2020-05-07 19:57:24
  • OfStack

The previous scenario is as follows:

I need to use the mongodb graphical client on my computer, but the server address of mongodb is not open to the external network, so I can only connect to mongodb server B by logging into the host A first, and then connecting to mongodb server B from A.

I intended to forward it via ssh port, but I don't have permission to connect ssh to B from machine A. So I wrote one in python.

 

The principle is simple.

1. Open one socket server to listen for connection requests

2. For each connection request received from a client, a connection request is made to the address to be forwarded. Namely client - > proxy- > forward. proxy is both an socket server (listening for client) and an socket client (requesting to forward).

3. The client - > proxy and proxy - > forward these two socket are bound with a dictionary.

4. Pass send/recv to data intact through the dictionary of this mapping

 

Here is the code.
 


#coding=utf-8 
import socket 
import select 
import sys 
  
to_addr = ('xxx.xxx.xx.xxx', 10000)# Forwarding address  
  
class Proxy: 
  def __init__(self, addr): 
    self.proxy = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
    self.proxy.bind(addr) 
    self.proxy.listen(10) 
    self.inputs = [self.proxy] 
    self.route = {} 
  
  def serve_forever(self): 
    print 'proxy listen...' 
    while 1: 
      readable, _, _ = select.select(self.inputs, [], []) 
      for self.sock in readable: 
        if self.sock == self.proxy: 
          self.on_join() 
        else: 
          data = self.sock.recv(8096) 
          if not data: 
            self.on_quit() 
          else: 
            self.route[self.sock].send(data) 
  
  def on_join(self): 
    client, addr = self.proxy.accept() 
    print addr,'connect' 
    forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    forward.connect(to_addr) 
    self.inputs += [client, forward] 
    self.route[client] = forward 
    self.route[forward] = client 
  
  def on_quit(self): 
    for s in self.sock, self.route[self.sock]: 
      self.inputs.remove(s) 
      del self.route[s] 
      s.close() 
  
if __name__ == '__main__': 
  try: 
    Proxy(('',12345)).serve_forever()# The address to which the proxy server listens  
  except KeyboardInterrupt: 
    sys.exit(1)


Related articles: