ProxyChains (the maintained fork is proxychains-ng, run as proxychains4) makes a Linux program open its TCP connections through the proxies listed in proxychains4.conf, even when the program has no proxy setting. Put your proxy under [ProxyList] as socks5 IP PORT USERNAME PASSWORD, then prefix the command: proxychains4 curl https://api.ipify.org. It works by preloading a library into the program, which is also why some programs slip past it.

We ran every config and error below with proxychains-ng 4.16, the Debian 12 package, against a local SOCKS5 and HTTP proxy with username and password authentication.

Install and find the config

sudo apt install proxychains4

proxychains4 reads the first config it finds in this order:

  1. the file named by -f or the PROXYCHAINS_CONF_FILE environment variable,
  2. ./proxychains.conf in the current directory,
  3. ~/.proxychains/proxychains.conf,
  4. /etc/proxychains4.conf (the Debian and Ubuntu path).

A per-project file passed with -f keeps experiments out of the system config.

proxychains4.conf for one authenticated proxy

Copy the host, port, username and password from your order. The first proxy must be written as an IPv4 address, so resolve the host once:

getent hosts HOST

Then write the config:

strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000

[ProxyList]
socks5  IP  PORT  USERNAME  PASSWORD

For the HTTP port use http as the type instead; ProxyChains talks to it with CONNECT and sends Basic credentials. Run a command through it:

proxychains4 -f ./proxychains.conf curl -s "https://api.ipify.org?format=json"

On success the library prints its route before the output, ... Strict chain ... IP:PORT ... api.ipify.org:443 ... OK, and the JSON shows the proxy's address. Add -q to hide those lines once you trust the setup.

Give it a hostname as the first entry and it refuses to start: proxy HOST has invalid value or is not numeric.

strict_chain, dynamic_chain and the rest

Exactly one chain type should be uncommented; if several are, the last one wins.

OptionWith a dead proxy in the listUse it for
strict_chainThe connection failsOne proxy, or a fixed route you want to fail loudly
dynamic_chainSkipped; the rest are used in orderA primary IP with a fallback
round_robin_chainSkipped; each connection starts after the last one usedSpreading connections, with chain_len
random_chainPicks proxies at random, chain_len of themTesting, not production

In our test a strict chain whose first hop was unreachable printed timeout and curl exited with code 7. The same list as a dynamic chain timed out on the dead hop, then went through the second proxy. Every extra hop adds latency, and two paid hops bill the same bytes twice; the proxy chain entry covers when chaining is worth it.

proxy_dns: who resolves the hostname

With proxy_dns on, ProxyChains answers the program's lookup with a placeholder address from remote_dns_subnet (224.x.x.x by default) and sends the real hostname to the proxy, which resolves it. We gave the proxy a name only it could resolve: with proxy_dns the request succeeded, without it curl failed with Could not resolve host. Leave it on so lookups happen at the exit, the same idea as socks5h.

One side effect: localnet exclusions only match plain IP addresses while proxy_dns is on, because a hostname never resolves to a real address inside the program.

What ProxyChains cannot proxy

  • UDP. proxychains4 dig @1.1.1.1 example.com answered from our own network; the proxy logged nothing. The same query with dig +tcp went through the proxy as a CONNECT to port 53.
  • Statically linked binaries. busybox wget from busybox-static and a Go binary (Chisel 1.12) both connected directly. The tell: proxychains prints config file found and preloading, but never the DLL init or chain lines.
  • Anything that bypasses the C library's socket calls, for the same reason.

For those, redirect at the kernel instead with Redsocks, which catches every TCP connection the machine makes, static or not.

Troubleshooting

  • <--denied after the proxy address. The proxy refused: wrong username or password, or the port does not speak the type you wrote.
  • timeout on a hop. Address or port unreachable from this machine.
  • preloading and then no chain line. The program never loaded the library; it is static, see above.
  • Works in curl, fails in the real tool. Run the tool with -f pointing at the same file, then compare against a plain curl request through the proxy.

With ProxyHive

A command-line job usually wants one fixed exit with SOCKS5, which is what a datacenter IP is: static, sold one at a time, with HTTP, HTTPS and SOCKS5 listed in its specs and username and password authentication. Each IP is its own endpoint, so one [ProxyList] line is one address; give each project its own config file and its own IP.