#!/bin/bash # socksvpn SOCKS VPN start/stop script # Copyright (C) 2015 Michal Trojnara # Version: 1.03 # Release date: 2015.09.07 VPN_HOST=example.com VPN_PORT=9080 SECRETS=/usr/local/etc/stunnel/secrets.txt PID_DIR=/run PID_STUNNEL=$PID_DIR/socksvpn.pid PID_TOR_DNS=$PID_DIR/tor-dns.pid stunnel_start() { stunnel -fd 0 << EOT pid = $PID_STUNNEL client = yes PSKsecrets = $SECRETS connect = $VPN_HOST:$VPN_PORT [SOCKS Client Direct] accept = :::9050 [SOCKS Client Transparent IPv4] accept = 127.0.0.1:9051 protocol = socks [SOCKS Client Transparent IPv6] accept = ::1:9051 protocol = socks EOT } do_netfilter() { $1 -t nat -F $2 if [[ $2 = OUTPUT ]]; then # traffic of local processes $1 -t nat -A $2 -p tcp -d $VPN_HOST --dport $VPN_PORT -j ACCEPT 2>/dev/null $1 -t nat -A $2 -o lo -j ACCEPT # internal OS IPC fi $1 -t nat -A $2 -p tcp --dport 9050 -j ACCEPT # non-transparent SOCKS $1 -t nat -A $2 -p tcp -j REDIRECT --to-ports 9051 } netfilter_start() { for PROG in iptables ip6tables; do for TABLE in PREROUTING OUTPUT; do do_netfilter $PROG $TABLE done done } netfilter_stop() { for PROG in iptables ip6tables; do for TABLE in PREROUTING OUTPUT; do $PROG -t nat -F $TABLE done done } pf_start() { sysctl -w net.inet.ip.forwarding=1 # the PF configuration needs to be implemented: # echo "rdr on en2 inet proto tcp to any port 443 -> 127.0.0.1 port 9051" >"$0.pf" # pfctl -f "$0.pf" pfctl -e } pf_stop() { pfctl -d } do_start() { stunnel_start netfilter_start rm -f $PID_TOR_DNS nohup tor-dns >/dev/null 2>&1 & echo $! >$PID_TOR_DNS cp /etc/resolv.conf /etc/resolv.conf.socksvpn-backup echo "nameserver 127.0.0.1" >/etc/resolv.conf echo "$0 started" } do_stop() { cp /etc/resolv.conf.socksvpn-backup /etc/resolv.conf netfilter_stop kill -TERM $(cat $PID_STUNNEL) kill -TERM $(cat $PID_TOR_DNS) rm -f $PID_TOR_DNS echo "$0 stopped" } if [[ $EUID -ne 0 ]]; then echo "$0 must be run as root" >&2 exit 1 fi case "$1" in start) do_start ;; restart|reload|force-reload) do_stop sleep 3 do_start ;; stop) do_stop ;; *) echo "Usage: $0 start|stop|restart|reload|force-reload" >&2 exit 3 ;; esac