Why Build a Custom Proxy Server

Custom proxy servers give you control over routing logic, authentication, logging, and protocol handling that off-the-shelf solutions don't provide. Use cases: building a proxy service (like ProxifyPRO), implementing custom auth schemes, routing requests through specific network interfaces (each 4G dongle as separate egress), and educational purposes.

The Three Proxy Protocols

ProtocolLayerHTTPS SupportAuthenticationCommon Port
HTTPApplicationVia CONNECTProxy-Authorization header8080, 3128
HTTPSApplication + TLSNativeProxy-Authorization header8443
SOCKS5TransportNative (TCP pipe)Username/password auth1080

SOCKS5 is more versatile — it proxies any TCP/UDP traffic, not just HTTP. Most scraping libraries support both HTTP and SOCKS5 interchangeably.

HTTP Proxy Mechanics

For plain HTTP requests, the proxy receives the full HTTP request from the client (with absolute URL), forwards it to the destination, and returns the response:

# Client sends:
GET http://example.com/page HTTP/1.1
Host: example.com
Proxy-Authorization: Basic dXNlcjpwYXNz

# Proxy strips Proxy-Authorization, forwards:
GET /page HTTP/1.1
Host: example.com

# Returns response to client

Key difference from a regular request: the URL is absolute (includes scheme and host), not relative. Proxy must parse the host from the URL and make a new connection to the upstream.

HTTPS CONNECT Tunnel

HTTPS uses the CONNECT method — the client asks the proxy to establish a raw TCP pipe to the destination. The proxy then transparently forwards bytes in both directions without decrypting.

# Client sends CONNECT request:
CONNECT example.com:443 HTTP/1.1
Host: example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz

# Proxy responds (tunnel established):
HTTP/1.1 200 Connection established

# Then: raw TLS bytes flow bidirectionally
# Proxy is transparent - doesn't see encrypted content

Implementing CONNECT in Node.js

const net = require('net')
const http = require('http')

const proxy = http.createServer()

proxy.on('connect', (req, clientSocket, head) => {
  const [host, port] = req.url.split(':')
  
  // Verify auth (Proxy-Authorization header)
  if (!verifyAuth(req.headers['proxy-authorization'])) {
    clientSocket.write('HTTP/1.1 407 Proxy Auth Required

')
    return clientSocket.destroy()
  }
  
  // Connect to upstream
  const serverSocket = net.connect(port || 443, host, () => {
    clientSocket.write('HTTP/1.1 200 Connection established

')
    serverSocket.write(head)
    // Bidirectional pipe
    serverSocket.pipe(clientSocket)
    clientSocket.pipe(serverSocket)
  })
  
  serverSocket.on('error', () => clientSocket.destroy())
})

proxy.listen(8080)

SOCKS5 Protocol

SOCKS5 operates at the transport layer. Handshake: client sends greeting (methods) → server selects auth method → client authenticates → client sends CONNECT/BIND/UDP request → server establishes upstream connection → bidirectional data flows.

SOCKS5 advantages over HTTP proxy: supports UDP (HTTP CONNECT is TCP only), no HTTP overhead, simpler protocol, no URL-based filtering (privacy benefit), supports IPv6 natively.

Production Challenges

Concurrency

Each proxy connection needs: 2 TCP connections (client + upstream), 2 buffers (~64KB each), event loop registration. At 1000 concurrent connections = 1000 upstream connections, 128MB buffers. Node.js handles this well with async I/O. Python threading doesn't scale — use asyncio.

Per-Interface Routing

ProxifyPRO's key feature: each dongle uses a different network interface. Proxy traffic through dongle 1 must egress via wwan0, dongle 2 via wwan1. This requires binding outgoing sockets to specific interfaces:

# Policy routing per dongle interface (Linux)
ip route add default via 192.168.1.1 dev wwan0 table 101
ip rule add fwmark 1 table 101

# iptables marks traffic from proxy port 40001 → table 101
iptables -t mangle -A OUTPUT -p tcp --sport 40001 -j MARK --set-mark 1

Framework Comparison

FrameworkLanguagePerfEaseBest For
3proxyCExcellentMediumProduction proxy engine
SquidCExcellentHardCaching proxy, enterprise
mitmproxyPythonMediumEasyInterception, analysis
CaddyGoVery GoodEasyTLS-forward proxy, modern
Node.js customJSGoodEasyCustom logic, control

3proxy: ProxifyPRO's Engine

ProxifyPRO uses 3proxy as its proxy engine — a lightweight (~50KB binary), battle-tested C proxy server that supports HTTP, HTTPS, SOCKS5, and per-interface binding. 3proxy handles thousands of concurrent connections on minimal CPU/RAM.

ProxifyPRO's Node.js layer handles: dongle management, authentication (Keygen license validation), health monitoring, rotation, SMS handling, dashboard, and marketplace. 3proxy handles: the actual TCP proxying. This separation gives C-level proxy performance with Node.js-level business logic flexibility.

// production insight

Building a proxy from scratch teaches the protocol. For production use, 3proxy + orchestration layer (Node.js/Python for business logic) is the proven architecture. ProxifyPRO has done this work — the Starter license gives you the complete production stack for $60/month.