Introduction
SOCKS5 (Socket Secure 5) is a widely-used internet protocol that enables clients to connect through a proxy server to external servers. Unlike HTTP proxies that operate at the application layer, SOCKS5 works at the session layer (Layer 5), making it protocol-agnostic and capable of handling any traffic type including TCP and UDP.
This comprehensive guide covers SOCKS5 protocol mechanics, authentication methods, implementation patterns, security considerations, and practical applications. Understanding SOCKS5 is essential for network administrators and developers building proxy-based architectures.
What is SOCKS5?
SOCKS5 is the fifth version of the SOCKS protocol, designed to provide flexible proxy functionality for network applications. It supports both TCP and UDP connections and includes authentication mechanisms.
Key Features
Protocol Agnostic: Works with any application protocol (HTTP, FTP, SMTP, etc.).
TCP and UDP Support: Handles both connection-oriented and connectionless traffic.
Multiple Authentication Methods: From anonymous to strong username/password and GSS-API.
IPv6 Support: Native IPv6 address handling.
UDP Relay: Enables UDP-based applications through the proxy.
SOCKS Protocol Family
| Version | Features | Status |
|---|---|---|
| SOCKS4 | TCP only, IPv4, limited auth | Legacy |
| SOCKS4a | SOCKS4 with DNS resolution | Legacy |
| SOCKS5 | TCP, UDP, IPv6, auth | Current |
| SOCKS5h | SOCKS5 with hostname resolution | Current |
Protocol Mechanics
Connection Flow
Client SOCKS Server Target Server
| | |
|--- Greeting (ver=5) ----->| |
| | |
|<-- Auth Methods --------- | |
| | |
|--- Auth (username/pass) ->| |
| | |
|<-- Auth Success ----------| |
| | |
|--- Connect Request ------>| |
| (addr, port, command) | |
| | |
|<-- Connect Reply ---------| |
| (bind_addr, bind_port) | |
| | |
|======== TCP RELAY ======= |===========================|
| | |
Client Greeting
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1-255 |
+----+----------+----------+
Example:
05 02 00 02
05 = SOCKS version
02 = 2 authentication methods
00 = No authentication (anonymous)
02 = Username/Password authentication
Server Response
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
Methods:
- 0x00: No authentication
- 0x01: GSSAPI
- 0x02: Username/Password
- 0xFF: No acceptable methods
Username/Password Authentication
Request:
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1-255 | 1 | 1-255 |
+----+------+----------+------+----------+
Response:
+----+------+
|VER | STAT |
+----+------+
| 1 | 1 |
+----+------+
Status: 0x00 = Success, else = Failure
Connect Request
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | 0x00 | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
CMD:
- 0x01: CONNECT
- 0x02: BIND
- 0x03: UDP ASSOCIATE
ATYP (Address Type):
- 0x01: IPv4 address
- 0x03: Domain name
- 0x04: IPv6 address
Connect Reply
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | 0x00 | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
REP (Reply Code):
- 0x00: Succeeded
- 0x01: General server failure
- 0x02: Rule set violation
- 0x03: Network unreachable
- 0x04: Host unreachable
- 0x05: Connection refused
- 0x06: TTL expired
- 0x07: Command not supported
- 0x08: Address type not supported
Implementation
Python Server
import socket
import struct
import threading
import selectors
class SOCKS5Server:
def __init__(self, host='0.0.0.0', port=1080):
self.host = host
self.port = port
self.auth_methods = {0x00: self.no_auth, 0x02: self.username_auth}
self.username_db = {'user': 'password'}
def start(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((self.host, self.port))
server.listen(5)
print(f"SOCKS5 server listening on {self.host}:{self.port}")
while True:
client, addr = server.accept()
threading.Thread(target=self.handle_client, args=(client,)).start()
def handle_client(self, client):
# Greeting
version, nmethods = self.recv(2, client)
if version != 0x05:
client.close()
return
methods = self.recv(nmethods, client)
# Select auth method
if 0x02 in methods and self.username_db:
client.send(struct.pack('BB', 5, 0x02))
self.handle_auth(client)
elif 0x00 in methods:
client.send(struct.pack('BB', 5, 0x00))
else:
client.send(struct.pack('BB', 5, 0xFF))
client.close()
return
# Handle connection request
self.handle_request(client)
def handle_auth(self, client):
version, ulen = self.recv(2, client)
username = self.recv(ulen, client).decode()
plen = self.recv(1, client)[0]
password = self.recv(plen, client).decode()
if self.username_db.get(username) == password:
client.send(struct.pack('BB', 1, 0x00))
else:
client.send(struct.pack('BB', 1, 0x01))
client.close()
def handle_request(self, client):
version, cmd, _, atyp = self.recv(4, client)
if cmd != 0x01: # CONNECT only
client.send(struct.pack('BBBB', 5, 0x07, 0x00, 0x01))
client.close()
return
# Parse address
if atyp == 0x01: # IPv4
addr = socket.inet_ntoa(self.recv(4, client))
elif atyp == 0x03: # Domain
length = self.recv(1, client)[0]
addr = self.recv(length, client).decode()
elif atyp == 0x04: # IPv6
addr = socket.inet_ntop(socket.AF_INET6, self.recv(16, client))
else:
client.send(struct.pack('BBBB', 5, 0x08, 0x00, 0x01))
client.close()
return
port = struct.unpack('!H', self.recv(2, client))[0]
# Connect to target
try:
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote.connect((addr, port))
# Success response
client.send(struct.pack('BBBB', 5, 0x00, 0x00, 0x01) +
socket.inet_aton('0.0.0.0') + struct.pack('!H', 0))
# Relay data
self.relay(client, remote)
except Exception as e:
client.send(struct.pack('BBBB', 5, 0x05, 0x00, 0x01))
client.close()
def relay(self, client, remote):
while True:
data = client.recv(4096)
if not data:
break
remote.sendall(data)
data = remote.recv(4096)
if not data:
break
client.sendall(data)
def recv(self, n, sock):
data = b''
while len(data) < n:
chunk = sock.recv(n - len(data))
if not chunk:
break
data += chunk
return data
if __name__ == '__main__':
server = SOCKS5Server()
server.start()
Client Implementation
import socket
import struct
class SOCKS5Client:
def __init__(self, proxy_host, proxy_port, username=None, password=None):
self.proxy_host = proxy_host
self.proxy_port = proxy_port
self.username = username
self.password = password
self.sock = None
def connect(self, target_host, target_port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.proxy_host, self.proxy_port))
# Greeting
methods = [0x00]
if self.username and self.password:
methods.append(0x02)
self.sock.send(struct.pack('BB', 5, len(methods)) + bytes(methods))
# Get auth method
version, method = struct.unpack('BB', self.sock.recv(2))
if method == 0xFF:
raise Exception("No acceptable auth method")
# Authenticate
if method == 0x02:
self._authenticate()
# Connect request
self._connect(target_host, target_port)
return self.sock
def _authenticate(self):
username = self.username.encode()
password = self.password.encode()
auth = struct.pack('BB', 1, len(username)) + username + \
struct.pack('B', len(password)) + password
self.sock.send(auth)
version, status = struct.unpack('BB', self.sock.recv(2))
if status != 0:
raise Exception("Authentication failed")
def _connect(self, host, port):
# Build request
if host.replace('.', '').isdigit():
atyp = 0x01
addr = socket.inet_aton(host)
else:
atyp = 0x03
addr = struct.pack('B', len(host)) + host.encode()
request = struct.pack('BBBB', 5, 0x01, 0x00, atyp) + addr + \
struct.pack('!H', port)
self.sock.send(request)
# Get reply
reply = self.sock.recv(10)
version, rep, _, atyp = struct.unpack('BBBB', reply[:4])
if rep != 0:
raise Exception(f"Connection failed with code {rep}")
# Usage
client = SOCKS5Client('proxy.example.com', 1080, 'user', 'pass')
sock = client.connect('target.example.com', 80)
sock.send(b'GET / HTTP/1.1\r\nHost: target.example.com\r\n\r\n')
print(sock.recv(4096).decode())
SSH as SOCKS5 Proxy
# Create SOCKS5 proxy via SSH
ssh -D 1080 -N [email protected]
# Or with key authentication
ssh -D 1080 -N -f [email protected]
# Test with curl
curl -x socks5h://user:pass@localhost:1080 https://example.com
Authentication Methods
No Authentication
# Simplest case - allow all
def no_auth(self, client):
client.send(struct.pack('BB', 5, 0x00))
Username/Password
# Store credentials securely
username_db = {
'admin': hash_password('secret123'),
'user1': hash_password('pass1'),
}
def username_auth(self, client):
# Read auth packet
# Verify credentials
# Return success/failure
GSS-API (Kerberos)
# For enterprise environments
def gssapi_auth(self, client):
client.send(struct.pack('BB', 5, 0x01))
# Implement GSSAPI handshake
UDP Relay
UDP Associate Command
def handle_udp_associate(self, client):
# Get client UDP binding address
client_addr = client.getpeername()
# Send bind response
bind_addr = socket.inet_aton('0.0.0.0')
bind_port = 0
client.send(struct.pack('BBBB', 5, 0x00, 0x00, 0x01) +
bind_addr + struct.pack('!H', bind_port))
# Handle UDP relay
self.handle_udp_relay(client)
UDP Packet Format
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
Use Cases
Firewall Traversal
# Bypass corporate firewall
# Client -> SOCKS5 (on permitted server) -> External service
# Configuration
SOCKS5_SERVER = 'accessible-server.example.com'
SOCKS5_PORT = 1080
# Applications can now connect through the proxy
Privacy and Anonymity
# Route traffic through SOCKS5 for privacy
# All traffic appears to come from proxy server
client = SOCKS5Client('privacy-proxy.example.com', 1080)
# Browse, download, etc. with proxy IP
Application Development
# Any TCP/UDP application can use SOCKS5
# Database connections, API calls, file transfers
# Database example
import socks
socks.set_default_proxy(socks.SOCKS5, "proxy.example.com", 1080)
socket.socket = socks.socksocket
# Now all socket connections go through proxy
conn = pymysql.connect(host='db.example.com', port=3306)
Security Considerations
Encryption
SOCKS5 itself doesn’t provide encryption. For sensitive traffic:
# Wrap with TLS
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
wrapped = context.wrap_socket(client_socket, server_hostname='proxy.example.com')
Access Control
# Implement IP-based access control
ALLOWED_IPS = ['10.0.0.0/8', '192.168.0.0/16']
def check_access(client_ip):
for network in ALLOWED_IPS:
if ip_in_network(client_ip, network):
return True
return False
Logging and Auditing
import logging
from datetime import datetime
logging.basicConfig(
filename='socks5.log',
level=logging.INFO,
format='%(asctime)s - %(message)s'
)
def log_connection(client, target, success):
logging.info(f"{client} -> {target} - {success}")
Performance Optimization
Connection Pooling
class ConnectionPool:
def __init__(self, max_connections=10):
self.pool = []
self.max_connections = max_connections
def get(self):
if self.pool:
return self.pool.pop()
return SOCKS5Client(proxy_host, proxy_port)
def put(self, client):
if len(self.pool) < self.max_connections:
self.pool.append(client)
Non-blocking I/O
import selectors
selector = selectors.DefaultSelector()
def handle_client(client):
events = selector.select(client)
for key, mask in events:
callback = key.data
callback(key.fileobj)
Troubleshooting
Common Issues
# Connection refused
# - Check firewall rules
# - Verify SOCKS5 server is running
# Authentication failed
# - Verify username/password
# - Check auth method negotiation
# Timeout
# - Check network connectivity
# - Verify UDP relay support if using UDP
Testing
# Test with netcat
nc -vv proxy.example.com 1080
# Test with curl
curl -v -x socks5h://user:pass@proxy:1080 https://example.com
# Test with nmap
nmap -p 1080 -sV proxy.example.com
Best Practices
Security
- Always use authentication in production
- Implement access control lists
- Use TLS for encryption when needed
- Monitor and log all connections
- Keep proxy software updated
Performance
- Enable TCP keepalive
- Use connection pooling for multiple requests
- Implement request timeouts
- Monitor bandwidth usage
Reliability
- Implement reconnection logic
- Use health checks
- Set up monitoring and alerting
- Plan for high availability
Conclusion
SOCKS5 remains a fundamental protocol for network proxying in 2026. Its simplicity, flexibility, and protocol-agnostic nature make it ideal for a wide range of applications from firewall traversal to privacy protection. Understanding SOCKS5 implementation and security considerations enables developers and administrators to build robust proxy infrastructure.
While newer protocols like WireGuard offer modern VPN capabilities, SOCKS5’s simplicity and broad support ensure it will continue serving as a valuable tool in network architectures.
Resources
- RFC 1928 - SOCKS Protocol Version 5
- RFC 1929 - SOCKS Username/Password Authentication
- SOCKS5 Wikipedia
Comments