TCPパケットの中継サーバ(プロキシサーバ)をPythonで実装する場合のプログラム
使い方
ローカルの 9000/tcp へのパケットを別IPの 8000/tcp へ転送する場合:
python -m http.server 8000 &
python proxy.py 127.0.0.1 9000 192.168.0.10 8000 False &
curl 127.0.0.1:9000
実装
import sys
import socket
from threading import Thread
def hexdump(src, length=16):
result = []
for i in range(0, len(src), length):
s = src[i:i+length]
hexa = ' '.join(['{:02X}'.format(x) for x in s])
text = ''.join([chr(x) if x >= 32 and x < 127 else '.' for x in s])
result.append('{:04X} {}{} {}'.format(i, hexa, ((length-len(s))*3)*' ', text))
for s in result:
print(s)
def received_from(connection):
buffer = b''
connection.settimeout(2)
try:
recv_len = 1
while recv_len:
data = connection.recv(4096)
buffer += data
recv_len = len(data)
if recv_len < 4096:
break
except:
pass
return buffer
def request_handler(buffer):
return buffer
def response_handler(buffer):
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive_first:
remote_buffer = received_from(remote_socket)
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print('[<==] Sending {} bytes to localhost.'.format(len(remote_buffer)))
client_socket.send(remote_buffer)
while True:
local_buffer = received_from(client_socket)
if len(local_buffer):
print('[==>] Received {} bytes from localhost.'.format(len(local_buffer)))
hexdump(local_buffer)
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print('[==>] Sent to remote.')
remote_buffer = received_from(remote_socket)
if len(remote_buffer):
print('[<==] Received {} bytes from remote.'.format(len(remote_buffer)))
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
client_socket.send(remote_buffer)
print('[<==] Sent to localhost.')
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
server.bind((local_host, local_port))
except:
print('[!!] Failed to listen on {}:{}'.format(local_host, local_port))
print('Check for other listening sockets or correct permissions.')
sys.exit(0)
print('[*] Listening on {}:{}'.format(local_host, local_port))
server.listen(5)
while True:
client_socket, addr = server.accept()
print('[==>] Received incoming connection from {}:{}'.format(addr[0], addr[1]))
proxy_thread = Thread(target=proxy_handler,
args=[client_socket, remote_host, remote_port, receive_first])
proxy_thread.start()
def main():
if len(sys.argv[1:]) != 5:
print('Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]')
print('Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True')
sys.exit(1)
local_host = sys.argv[1]
local_port = int(sys.argv[2])
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
receive_first = sys.argv[5]
if 'True' in receive_first:
receive_first = True
else:
receive_first = False
server_loop(local_host, local_port, remote_host, remote_port, receive_first)
if __name__ == '__main__':
main()