一个简单的Python脚本实现SOCKS5代理服务器的基本功能

时间:2025-03-02 08:24:59

以下是一个简单的Python脚本,实现了SOCKS5代理服务器的基本功能:

import socket
import select

class Socks5Proxy:
    def __init__(self, host, port):
         = host
         = port

    def run(self):
        with (socket.AF_INET, socket.SOCK_STREAM) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server_socket.bind((, ))
            server_socket.listen()

            print(f"SOCKS5 proxy is listening on {}:{}...")

            while True:
                client_socket, client_address = server_socket.accept()
                print(f"Accepted connection from {client_address}")

                with client_socket:
                    # 握手阶段
                    data = client_socket.recv(1024)
                    if not data:
                        continue
                    client_socket.sendall(b"\x05\x00")

                    # 请求阶段
                    data = client_socket.recv(1024)
                    if not data:
                        continue
                    version = data[0]
                    command = data[1]
                    address_type = data[3]
                    if address_type == 1:  # IPv4
                        address = socket.inet_ntoa(data[4:8])
                        port = int.from_bytes(data[8:], byteorder="big")
                    elif address_type == 3:  # 域名
                        address_length = data[4]
                        address = data[5:5+address_length].decode("utf-8")
                        port = int.from_bytes(data[5+address_length:], byteorder="big")
                    else:
                        client_socket.close()
                        continue

                    # 响应阶段
                    try:
                        remote_socket = (socket.AF_INET, socket.SOCK_STREAM)
                        remote_socket.connect((address, port))
                    except Exception as e:
                        client_socket.sendall(b"\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00")
                        client_socket.close()
                        continue

                    bind_address = remote_socket.getsockname()
                    bind_address_type = 1  # 只支持IPv4
                    bind_address_bytes = socket.inet_aton(bind_address[0])
                    bind_port_bytes = bind_address[1].to_bytes(2, byteorder="big")
                    response = bytearray([version, 0x00, 0x00, bind_address_type])
                    response += bind_address_bytes + bind_port_bytes
                    client_socket.sendall(response)

                    # 转发阶段
                    sockets = [client_socket, remote_socket]
                    while True:
                        rlist, wlist, xlist = (sockets, [], sockets, 5)
                        if xlist:
                            break
                        for rsock in rlist:
                            wsock = remote_socket if rsock is client_socket else client_socket
                            data = (4096)
                            if not data:
                                (rsock)
                                continue
                            (data)

                    print(f"Closed connection from {client_address}")

if __name__ == "__main__":
    proxy = Socks5Proxy("0.0.0.0", 1080)
    ()

以上代码中,我们创建了一个Socks5Proxy类,它继承自object类。我们在类的构造函数中指定了代理服务器的主机和端口。在run方法中,我们创建了一个socket对象,并将其绑定到指定的主机和端口上。然后,我们使用循环来接受客户端的连接,并在每个连接上执行以下步骤:

握手阶段:接收客户端发送的握手请求,并向客户端发送握手响应。

请求阶段:接收客户端发送的请求,并解析出请求的目标地址和端口号。

响应阶段:向客户端发送请求响应,并建立与目标服务器的连接。

转发阶段:使用select模块来实现双向数据传输,将客户端和目标服务器之间的数据互相转发。

最后,我们在main函数中创建了一个Socks5Proxy对象,并调用其run方法来启动代理服务器。