Python实现代理服务器

1,677 阅读2分钟

这里的代理服务器,是指二级代理服务器。

比如:A可以访问B,B可以访问C,A不能直接访问C。这时,如果在B开一个二级代理,就可实现A访问C。现有的工具有CCProxy。原文为python2

这里就是使用Python简单的实现一个二级代理。


import os
import logging

import socket
import select
import sys

logsDir = "logs"
if not os.path.isdir(logsDir):
    os.mkdir(logsDir)
logging.basicConfig(level=logging.DEBUG,
 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a,%d %b %Y %H:%M:%S ',
                    filename='logs/logs.log',
                    filemode='a')

to_addr=('136.158.20.3',3389)#目标主机,就是上面的C机
maxConnections = 32

class Proxy:
    def __init__(self,addr):
        self.proxy = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.proxy.bind(addr)
        self.proxy.listen(maxConnections)
        self.inputs = {self.proxy:None}
        self.route = {}

    def serve_forever(self):
        logging.info('proxy listen....')
        while 1:
            readable,_,_=select.select(list(self.inputs.keys()),[],[])
            for self.sock in readable:
                if self.sock == self.proxy:
                    self.on_join()
                else:
                    try:
                        data = self.sock.recv(8192)
                    except Exception as e:
                        logging.error(str(e))
                        self.on_quit()
                        continue

                    if not data:
                        self.on_quit()
                    else:
                        try:
                            self.route[self.sock].send(data)
                        except Exception as e:
                            logging.error(str(e))
                            self.on_quit()
                            continue
    def on_join(self):
        client,addr = self.proxy.accept()
        logging.info("proxy client "+str(addr)+' connect')
        forward = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        try:
            forward.connect(to_addr)
        except Exception as e:
            logging.error(str(e))
            client.close()
            return
        self.inputs[client] = None
        self.inputs[forward] = None

        self.route[client] = forward
        self.route[forward] = client
    def on_quit(self):
        ls = [self.sock]
        if self.sock in self.route:
            ls.append(self.route[self.sock])
        for s in ls:
            if s in self.inputs:
                del self.inputs[s]
            if s in self.route:
                del self.route[s]
            s.close()

if __name__ == "__main__":
    try:
        Proxy(('',8192)).serve_forever()
    except KeyboardInterrupt as e:
        logging.error("KeyboardInterrupt"+str(e))
# ————————————————
# 版权声明:本文为CSDN博主「xsjyahoo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/xsjyahoo/article/details/51568712

实现二:

# coding:utf8
# 创建一个 TCP 代理
 
import sys
import socket
import threading
 
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
 
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        # 服务器监听的 host和端口
        server.bind((local_host, local_port))
    except Exception as e:
        print("[!!] Failed to listen on %s:%d" % (local_host, local_port))
        print("[!!] Check for other listening sockets or correct permissions")
        sys.exit(0)
 
    print("[*] Listening on %s:%d" % (local_host, local_port))
 
    #开始监听TCP传入连接
    server.listen(5)
 
    while True:
        # 获取客户端请求过来的数据
        client_socket, addr = server.accept()
 
        # 打印出本地客户端连接的信息
        print("[==>] Received incoming connection from %s:%d" % (addr[0], addr[1]))
 
        # 开启一个线程 与 远程主机通信
        proxy_thread = threading.Thread(target=proxy_handler, args=(client_socket, remote_host, remote_port, receive_first))
 
        proxy_thread.start()
 
 
# 十六进制转储的函数
def hexdump(src, length=16):
    result = []
    digits = 4 if isinstance(src, bytes) else 2  #isinstance(src,unicode)
 
    for i in range(0, len(src), length):
        s = src[i:i+length]
        hexa = b' ' . join(["%0*X" % (digits, ord(x)) for x in s])
        text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
        result.append(b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text))
 
    print(b'\n'.join(result))
 
# 从远程服务器里面接受数据
def receive_from(connection):
    print("receive_from function start ........... ")
    buffer = ""
 
    # 我们设置了两秒的超时, 这取决于目标的情况, 可能需要调整
    connection.settimeout(2)
 
    try:
        # 持续从缓存中读取数据直到没有数据或者超时
        while True:
            data = connection.recv(4096)
            print("receive_from data is %s " % data)
            if not data:
                print("receive_from data is break .......")
                break
 
            buffer += data
 
    except Exception as e:
        print(str(e))
        #print(str(e))
        print('error for receive_from')
 
    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)
 
    print("remote_socket start ...... %s %d" % (remote_host, remote_port))
    remote_socket.connect((remote_host, remote_port))
 
    # 如果必要从远程主机接收数据
    if receive_first:
        remote_buffer = receive_from(remote_socket)
        hexdump(remote_buffer)
 
        # 发送给我们的响应处理
        remote_buffer = response_handler(remote_buffer)
 
        # 如果我们有数据传递给本地客户端,发送它
        if len(remote_buffer):
            print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
            client_socket.send(remote_buffer)
 
    # 现在我们从本地循环读取数据, 发送给远处主机和本地主机
    while True:
        # 从本地读取数据
        local_buffer = receive_from(client_socket)
        print("local_buffer is %s " % local_buffer)
        if len(local_buffer):
            print("[==>] Received %d bytes from localhost." % len(local_buffer))
            hexdump(local_buffer)
 
            # 这里可以改变我们请求的数据 过滤等功能
            local_buffer = request_handler(local_buffer)
 
            # 向远处主机发送数据
            remote_socket.send(local_buffer)
            print("[==>] Sent to remote.")
 
        # 接收响应的数据
        remote_buffer = receive_from(remote_socket)
        if len(remote_buffer):
            print("[<==] Received %d bytes from remote." % len(remote_buffer))
            hexdump(remote_buffer)
 
            # 发送到响应处理函数
            remote_buffer = response_handler(remote_buffer)
 
            # 将响应发送给本地socket
            client_socket.send(remote_buffer)
 
        # 如果两边都没有数据, 关闭连接
        if not len(local_buffer) or not len(remote_buffer):
            client_socket.close()
            remote_socket.close()
            print("[*] No more data. Closing connections.")
            sys.exit(0)
            break
 
 
 
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(0)
 
    # 设置本地监听参数
    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
 
    # 设置好我们的监听 socket
    server_loop(local_host, local_port, remote_host, remote_port, receive_first)
 
main()