Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
tun2socks TCP+UDP user-wide proxy through shadowsocks and udpgw
#--- Build tun2socks and udpgw (as the user who will use the proxy) ---
mkdir -p $HOME/src
cd $HOME/src
git clone "https://github.com/ambrop72/badvpn"
cd badvpn
mkdir -p build
cd build
export OUTDIR=$PWD
export SRCDIR=$(dirname $PWD)
export CC=gcc
export ENDIAN=little
bash $SRCDIR/compile-tun2socks.sh
bash $SRCDIR/compile-udpgw.sh
mkdir -p $HOME/bin/badvpn
cp tun2socks $HOME/bin/badvpn/
cp udpgw $HOME/bin/badvpn/
#--- We also need Shadowsocks ---
export GOPATH="$HOME/go"
go get "github.com/shadowsocks/shadowsocks-go"
go get "github.com/Yawning/chacha20"
go get "golang.org/x/crypto/blowfish"
go get "golang.org/x/crypto/cast5"
go get "golang.org/x/crypto/salsa20/salsa"
cd "$GOPATH/src/github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-local"
CGO_ENABLED=0 go build
cd "$GOPATH/src/github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-server"
CGO_ENABLED=0 go build
# Do install -- remember to set SHADOWSOCKS_VERSION
SHADOWSOCKS_VERSION=1.2.1
mkdir -p $HOME/bin/shadowsocks
cd $HOME/bin/shadowsocks
cp "$GOPATH/src/github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-local/shadowsocks-local" shadowsocks-local-linux64-${SHADOWSOCKS_VERSION}
cp "$GOPATH/src/github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-server/shadowsocks-server" shadowsocks-server-linux64-${SHADOWSOCKS_VERSION}
ln -sf shadowsocks-local-linux64-${SHADOWSOCKS_VERSION} shadowsocks-local
ln -sf shadowsocks-server-linux64-${SHADOWSOCKS_VERSION} shadowsocks-server
# Sample config file (same for client and server) -- "myserver.conf"
{
"server":"machine1.example.com",
"server_port":8888,
"local_port":8080,
"password":"xxxxxxxxxxxx",
"timeout":600,
"method":"aes-256-cfb",
"fast_open": false,
"workers": 1
}
# Server (with -u for UDP support -- though, I'm not sure if it can be used with tun2socks)
$HOME/bin/shadowsocks/shadowsocks-server -c $HOME/bin/shadowsocks/myserver.conf -u
# Client
$HOME/bin/shadowsocks/shadowsocks-local -c $HOME/bin/shadowsocks/myserver.conf
#--- Now, the start/stop script which proxifies a user ("foo" in this case) ---
##
## First, be sure to start Shadowsocks on 127.0.0.1 (on port 8080 in this case)
## Second, be sure to start the udpgw on the remote server (on port 7300 in this case)
##
## Then, put the following into a script like "tun2socks_proxy_foo.bash" which will be run as root
##
## If you need multple scripts, a more general naming scheme is as follows:
## tun2socks_proxy_${LOCAL_USER}_${NET_IFACE}_${REMOTE_SERVER}_${TCPPORT}_${TUN_IFACE}.bash
##
#!/bin/bash
LOCAL_USER=foo
NET_IFACE=wlan0
TUN_IFACE=tun0
REMOTE_USER=me
REMOTE_SERVER=100.200.300.400
ROUTER_IP=192.168.1.1
TCPPORT=8080
UDPPORT=7300
VPN_TUN_IP=10.0.0.1
VPN_GW_IP=10.0.0.2
TABLE_MARK=11
#--- Get Local Network ---
ROUTER_NET=$(echo $ROUTER_IP | sed -E 's/[[:digit:]]+$/0\/24/g')
#--- Redirect for $LOCAL_USER (as root) ---
echo "Setting up proxy for ${LOCAL_USER}"
ip tuntap add dev ${TUN_IFACE} mode tun user ${LOCAL_USER}
ip addr add ${VPN_TUN_IP}/24 dev ${TUN_IFACE}
ip link set ${TUN_IFACE} up
ip rule add fwmark ${TABLE_MARK} table ${TABLE_MARK}
ip route add $ROUTER_NET dev ${NET_IFACE} table ${TABLE_MARK}
ip route add ${REMOTE_SERVER}/32 via ${ROUTER_IP} table ${TABLE_MARK}
ip route add default via ${VPN_TUN_IP} table ${TABLE_MARK}
iptables -t mangle -A OUTPUT -m owner --uid-owner $(id -u ${LOCAL_USER}) -j MARK --set-mark ${TABLE_MARK}
iptables -t nat -A POSTROUTING -o ${TUN_IFACE} -j SNAT --to-source ${VPN_GW_IP}
sysctl -w net.ipv4.conf.${TUN_IFACE}.rp_filter=2
ip route flush cache
#--- start local redirection daemon (as user) ---
sudo -u ${LOCAL_USER} /home/${LOCAL_USER}/bin/badvpn/tun2socks --tundev ${TUN_IFACE} --netif-ipaddr ${VPN_GW_IP} --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:${TCPPORT} --udpgw-remote-server-addr ${REMOTE_SERVER}:${UDPPORT}
#--- Stop redirect for $LOCAL_USER (as root) ---
echo "Tearing down proxy for ${LOCAL_USER}"
ip rule del fwmark ${TABLE_MARK} table ${TABLE_MARK}
ip route flush table ${TABLE_MARK}
iptables -t mangle -D OUTPUT -m owner --uid-owner $(id -u ${LOCAL_USER}) -j MARK --set-mark ${TABLE_MARK}
iptables -t nat -D POSTROUTING -o ${TUN_IFACE} -j SNAT --to-source ${VPN_GW_IP}
sysctl -w net.ipv4.conf.${TUN_IFACE}.rp_filter=1
ip link set ${TUN_IFACE} down
ip tuntap del dev ${TUN_IFACE} mode tun
ip route flush cache
#--- Start the proxy ---
##
## Just run the script as root to start the proxy, and Ctrl-C to stop it.
##
## In the meantime, you can try "curl ip.ryansanden.com" to see your effective IP as the user ("foo") or another user.
## What should happen is that you see the $REMOTE_SERVER ip from "foo" only.
##
./tun2socks_proxy_foo.bash
#--- GUI applications ---
##
## Since you're usually running this proxy for a separate user, that user needs to be able to access your X session.
## Ensuring that user can access /dev/dri means it can fully use OpenGL (i.e. glxgears) as well.
##
xhost +SI:localuser:foo
sudo usermod -a -G video foo
# For the correct group ("video" in my case), see /dev/dri/card0:
#
# me@MyMachine:~$ getfacl /dev/dri/card0
# getfacl: Removing leading '/' from absolute path names
# # file: dev/dri/card0
# # owner: root
# # group: video
# user::rw-
# user:me:rw-
# group::rw-
# mask::rw-
# other::---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment