October 03, 2013

Transparent SOCKS proxy for any program

Have you ever wonder how to make a program run via a specific SOCKS proxy if it doesn’t have built-in proxy support?

Here I will show you how to transparently socksify all traffic of process launched with specified group.

Create proxy group

# groupadd -r proxy
# gpasswd proxy
Changing the password for group proxy
New Password: [empty]
Re-enter new password: [empty]

Setup iptables rules

# Transparently proxy all traffic of processes launched with specified group to transocks daemon
PROXY_GROUP=proxy
# Port that is transocks will be listening on
TRANSOCKS_PORT=1212

# Location of our SOCKS-server
SOCKS_HOST="127.0.0.1"
SOCKS_PORT="9050"

iptables -t nat -X CHAINTRANSOCKS
iptables -t nat -N CHAINTRANSOCKS

# Only proxy traffic for programs run with group $PROXY_GROUP
iptables -t nat -I CHAINTRANSOCKS -m owner ! --gid-owner $PROXY_GROUP -j RETURN

# Exceptions for local traffic
iptables -t nat -I CHAINTRANSOCKS -o lo -j RETURN
iptables -t nat -I CHAINTRANSOCKS --dst 127.0.0.1 -j RETURN

# Do not redirect traffic for the SOCKS-Server
iptables -t nat -A CHAINTRANSOCKS -p tcp -d $SOCKS_HOST --dport $SOCKS_PORT -j RETURN
iptables -t nat -A CHAINTRANSOCKS -p udp -d $SOCKS_HOST --dport $SOCKS_PORT -j RETURN

# Add extra local nets to ignore here as necessary
iptables -t nat -A CHAINTRANSOCKS --dst 192.168.0.0/16 -j RETURN

# Send to transocks
iptables -t nat -A CHAINTRANSOCKS -p tcp -j REDIRECT --to-port $TRANSOCKS_PORT
iptables -t nat -A CHAINTRANSOCKS -p udp -j REDIRECT --to-port $TRANSOCKS_PORT

# Socksify traffic leaving this host
iptables -t nat -A OUTPUT -p tcp --syn -j CHAINTRANSOCKS
iptables -t nat -A OUTPUT -p udp -j CHAINTRANSOCKS

You can run your own SOCKS proxy if you have your own server with SSHD

$ ssh -D 9050 -N yourserver.com
$ netstat --inet -apn |grep 9050
tcp        0      0 127.0.0.1:9050              0.0.0.0:*                   LISTEN      26561/ssh

Get transocks_ev sources and compile them

# yum install libevent-devel -y
# wget -c -r http://oss.tiggerswelt.net/transocks_ev/
# cd oss.tiggerswelt.net/transocks_ev/
transocks_ev# make
gcc -c -g -O2 -DSOCKS -I/usr/include transocks_ev.c
gcc -o transocks_ev transocks_ev.o -L/usr/lib -Wl,--rpath -Wl,/usr/lib -levent

Starting transocks_ev

transocks_ev# ./transocks_ev -f -p 1212 -s 9050 -S 127.0.0.1

Examples

Firefox

$ sg proxy firefox
Password: [Press Enter]

Now check what is your IP at the http://whatismyip.com or http://icanhazip.com :)

Windows remote desktop (RDP)

$ sg proxy 'rdesktop -u admin123 -g 1200x800 -EPbz 10.150.20.27'

HP IP Console Viewer

$ sg proxy IPViewer

NOTE: SOCKSv5 protocol supports UDP, however UDP is not yet implemented in transocks_ev.

Disable iptables rules When finished you may want to disable iptables rules

PROXY_GROUP=proxy
TRANSOCKS_PORT=1212
SOCKS_HOST="127.0.0.1"
SOCKS_PORT="9050"

iptables -t nat -D OUTPUT -p udp -j CHAINTRANSOCKS
iptables -t nat -D OUTPUT -p tcp --syn -j CHAINTRANSOCKS
iptables -t nat -D CHAINTRANSOCKS -p tcp -j REDIRECT --to-port $TRANSOCKS_PORT
iptables -t nat -D CHAINTRANSOCKS -p udp -j REDIRECT --to-port $TRANSOCKS_PORT
iptables -t nat -D CHAINTRANSOCKS -p tcp -d $SOCKS_HOST --dport $SOCKS_PORT -j RETURN
iptables -t nat -D CHAINTRANSOCKS -p udp -d $SOCKS_HOST --dport $SOCKS_PORT -j RETURN
iptables -t nat -D CHAINTRANSOCKS --dst 192.168.0.0/16 -j RETURN
iptables -t nat -D CHAINTRANSOCKS --dst 127.0.0.1 -j RETURN
iptables -t nat -D CHAINTRANSOCKS -o lo -j RETURN
iptables -t nat -D CHAINTRANSOCKS -m owner ! --gid-owner $PROXY_GROUP -j RETURN
iptables -t nat -X CHAINTRANSOCKS

Troubleshooting

If you will get following error

transocks_ev]# make
gcc -c -g -O2 -DSOCKS -I/usr/include transocks_ev.c
gcc -o transocks_ev transocks_ev.o -L/usr/lib -Wl,--rpath -Wl,/usr/lib -levent
/bin/ld: skipping incompatible /usr/lib/libc.so when searching for -lc
/bin/ld: transocks_ev.o: undefined reference to symbol 'clock_gettime@@GLIBC_2.2.5'
/bin/ld: note: 'clock_gettime@@GLIBC_2.2.5' is defined in DSO /lib64/librt.so.1 so try adding it to the linker command line
/lib64/librt.so.1: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
make: *** [transocks_ev] Error 1

Just add “-lrt” to the end of the following line:

[root@arno transocks_ev]# grep lrt Makefile
$(CC) -o transocks_ev $(OBJ) -L$(LIBEVENT_LIB_DIR) -Wl,--rpath -Wl,$(LIBEVENT_LIB_DIR) -levent -lrt