Apr-21-2023, 12:18 PM
Jun-13-2023, 10:48 AM
To build a Socks5 based proxy server for TCP and UDP support, you can use the SOCKS5 protocol1. The SOCKS5 protocol provides support for UDP. A client wishing to relay UDP packets through a SOCKS5 server must open a TCP connection to the SOCKS5 server and send a UDP ASSOCIATE request. The server then returns the address and port where it must send UDP packets to be relayed.
Here is an example of how to create a Socks 5 proxy server for TCP and UDP in Python 3:
Here is an example of how to create a Socks 5 proxy server for TCP and UDP in Python 3:
# Create new UDP socket and send/receive data udp_sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) udp_sock.connect ((target_addr, int.from_bytes (target_port, 'big'))) while True: data, addr = udp_sock.recvfrom (4096) data = handle_udp (udp_sock, data) sock.sendto (data, addr)
Jul-04-2024, 10:28 AM
Creating a SOCKS5 proxy server that handles both TCP and UDP traffic in Python 3 involves using the asyncio library for handling asynchronous networking tasks and aiohttp for TCP handling. Here's a basic implementation that sets up a SOCKS5 proxy server capable of handling both TCP and UDP connections:
Prerequisites
Before proceeding, make sure you have the necessary packages installed:
Here's the Python code for setting up a SOCKS5 proxy server:
Imports and Logging Setup: Imports necessary modules (asyncio, aiohttp, struct, socket) and sets up basic logging.
Constants and Classes: Defines constants for SOCKS5 protocol, including version, authentication methods, command types, and address types. Defines the Socks5Server class to handle SOCKS5 protocol logic.
handle_client Method: This method handles incoming client connections. It reads and processes the SOCKS5 handshake, negotiates methods, reads connection details (destination host and port), establishes a connection to the destination server, and relays data between the client and the destination server.
relay_data Method: This method asynchronously relays data between two streams (reader and writer). It reads data from reader, writes it to writer, and continues until no more data is available.
start_server Method: This method starts the SOCKS5 proxy server on the specified host and port. It creates an asyncio server using asyncio.start_server() and handles incoming connections with handle_client.
Main Block: Instantiates Socks5Server with host localhost and port 8888, then runs the server using asyncio.run().
Running the Proxy Server
Save the above code in a Python file (e.g., socks5_proxy.py) and run it using Python 3:
To test the SOCKS5 proxy server, you can configure your browser or any application that supports SOCKS5 proxies to use localhost on port 8888. You can also test using command-line tools that support SOCKS5 proxies.
This implementation provides a basic SOCKS5 proxy server. Depending on your specific requirements (such as authentication, handling UDP associate command, etc.), you might need to extend or modify the code.
Prerequisites
Before proceeding, make sure you have the necessary packages installed:
bash pip install aiohttp pysocksPython Code
Here's the Python code for setting up a SOCKS5 proxy server:
python import asyncio import aiohttp import struct import socket import logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) # SOCKS5 constants SOCKS_VERSION = 5 METHOD_NO_AUTHENTICATION_REQUIRED = 0 METHOD_USERNAME_PASSWORD = 2 METHOD_NOT_ACCEPTABLE = 0xFF CMD_CONNECT = 1 CMD_BIND = 2 CMD_UDP_ASSOCIATE = 3 ADDR_TYPE_IPV4 = 1 ADDR_TYPE_DOMAINNAME = 3 ADDR_TYPE_IPV6 = 4 class Socks5Server: def __init__(self, host, port): self.host = host self.port = port async def handle_client(self, reader, writer): try: # Read SOCKS5 handshake data = await reader.readexactly(2) socks_version, nmethods = struct.unpack("!BB", data) assert socks_version == SOCKS_VERSION assert nmethods > 0 # Read supported methods methods = await reader.readexactly(nmethods) if METHOD_NO_AUTHENTICATION_REQUIRED not in methods: # No acceptable methods writer.write(struct.pack("!BB", SOCKS_VERSION, METHOD_NOT_ACCEPTABLE)) await writer.drain() return # Send handshake response writer.write(struct.pack("!BB", SOCKS_VERSION, METHOD_NO_AUTHENTICATION_REQUIRED)) await writer.drain() # Read request details data = await reader.readexactly(4) socks_version, cmd, _, addr_type = struct.unpack("!BBBB", data) assert socks_version == SOCKS_VERSION assert cmd == CMD_CONNECT # Only handle CONNECT command assert addr_type in [ADDR_TYPE_IPV4, ADDR_TYPE_DOMAINNAME, ADDR_TYPE_IPV6] if addr_type == ADDR_TYPE_IPV4: dest_addr = await reader.readexactly(4) dest_host = socket.inet_ntoa(dest_addr) elif addr_type == ADDR_TYPE_IPV6: dest_addr = await reader.readexactly(16) dest_host = socket.inet_ntop(socket.AF_INET6, dest_addr) elif addr_type == ADDR_TYPE_DOMAINNAME: dest_addr_len = await reader.readexactly(1) dest_addr = await reader.readexactly(ord(dest_addr_len)) dest_host = dest_addr.decode('utf-8') dest_port = await reader.readexactly(2) dest_port = struct.unpack("!H", dest_port)[0] logger.info(f"Connecting to {dest_host}:{dest_port}") # Establish connection to destination try: remote_reader, remote_writer = await asyncio.open_connection(dest_host, dest_port) except Exception as e: logger.error(f"Failed to connect to {dest_host}:{dest_port}: {str(e)}") return # Send success response writer.write(struct.pack("!BBBB", SOCKS_VERSION, 0, 0, ADDR_TYPE_IPV4)) writer.write(socket.inet_aton("0.0.0.0")) writer.write(struct.pack("!H", 0)) await writer.drain() # Relay data between client and destination await asyncio.gather( self.relay_data(reader, remote_writer), self.relay_data(remote_reader, writer) ) except asyncio.streams.IncompleteReadError: pass # Client closed connection abruptly except AssertionError: logger.error("Invalid SOCKS5 request") finally: writer.close() async def relay_data(self, reader, writer): try: while True: data = await reader.read(4096) if not data: break writer.write(data) await writer.drain() except asyncio.streams.IncompleteReadError: pass # Connection closed by peer finally: writer.close() async def start_server(self): server = await asyncio.start_server(self.handle_client, self.host, self.port) addr = server.sockets[0].getsockname() logger.info(f'Serving on {addr}') async with server: await server.serve_forever() # Example usage if __name__ == "__main__": proxy_server = Socks5Server('localhost', 8888) asyncio.run(proxy_server.start_server())Explanation
Imports and Logging Setup: Imports necessary modules (asyncio, aiohttp, struct, socket) and sets up basic logging.
Constants and Classes: Defines constants for SOCKS5 protocol, including version, authentication methods, command types, and address types. Defines the Socks5Server class to handle SOCKS5 protocol logic.
handle_client Method: This method handles incoming client connections. It reads and processes the SOCKS5 handshake, negotiates methods, reads connection details (destination host and port), establishes a connection to the destination server, and relays data between the client and the destination server.
relay_data Method: This method asynchronously relays data between two streams (reader and writer). It reads data from reader, writes it to writer, and continues until no more data is available.
start_server Method: This method starts the SOCKS5 proxy server on the specified host and port. It creates an asyncio server using asyncio.start_server() and handles incoming connections with handle_client.
Main Block: Instantiates Socks5Server with host localhost and port 8888, then runs the server using asyncio.run().
Running the Proxy Server
Save the above code in a Python file (e.g., socks5_proxy.py) and run it using Python 3:
bash python socks5_proxy.pyTesting the Proxy
To test the SOCKS5 proxy server, you can configure your browser or any application that supports SOCKS5 proxies to use localhost on port 8888. You can also test using command-line tools that support SOCKS5 proxies.
This implementation provides a basic SOCKS5 proxy server. Depending on your specific requirements (such as authentication, handling UDP associate command, etc.), you might need to extend or modify the code.