Ecco una soluzione completa che utilizza i gruppi di controllo (cgroup), che consente il controllo delle risorse per processo. Un gruppo di controllo di rete consente di isolare il percorso VPN, consente facilmente l'esecuzione selettiva di qualsiasi processo e dei suoi figli al suo interno, consente agli utenti non root di ottenere l'accesso ai processi in esecuzione all'interno del cgroup e l'utilizzo di una seconda istanza di dnsmasq può isolare il DNS anche le domande. Ciò presuppone che tu abbia openvpn, dnsmasq, cgroup e la versione 1.6+ di iptables con il supporto cgroup installato. Tutto questo è stato fatto su Debian Jessie
Il primo passo è creare il cgroup e configurare iptables di conseguenza. Questo dovrebbe essere fatto ad ogni riavvio, quindi metto quanto segue in /etc/rc.local
# enable ip forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# create cgroup for 3rd party VPN (can change 'vpn' to your name of choice)
mkdir -p /sys/fs/cgroup/net_cls/vpn
# give it an arbitrary id
echo 11 > /sys/fs/cgroup/net_cls/vpn/net_cls.classid
# grant a non-root user access (change user:group accordingly)
cgcreate -t user:group -a user:group -g net_cls:vpn
# mangle packets in cgroup with a mark
iptables -t mangle -A OUTPUT -m cgroup --cgroup 11 -j MARK --set-mark 11
# NAT packets in cgroup through VPN tun interface
iptables -t nat -A POSTROUTING -m cgroup --cgroup 11 -o tun0 -j MASQUERADE
# redirect DNS queries to port of second instance, more on this later
iptables -t nat -A OUTPUT -m cgroup --cgroup 11 -p tcp --dport 53 -j REDIRECT --to-ports 5354
iptables -t nat -A OUTPUT -m cgroup --cgroup 11 -p udp --dport 53 -j REDIRECT --to-ports 5354
# create separate routing table
ip rule add fwmark 11 table vpn
# add fallback route that blocks traffic, should the VPN go down
ip route add blackhole default metric 2 table vpn
# disable reverse path filtering for all interfaces
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done
Il passaggio successivo consiste nel modificare il file di configurazione del client della tua VPN di terze parti, ad es. /etc/openvpn/client.conf . Lascia invariato il resto della tua configurazione.
# redirect-gateway def1 <--- comment or remove the redirect-gateway line if it exists
# disable automatically configuring routes and run our own routeup.sh script instead
route-noexec
route-up /etc/openvpn/routeup.sh
# run our own update-dnsmasq-conf script on interface up/down; comment out existing up/down lines
up /etc/openvpn/update-dnsmasq-conf
down /etc/openvpn/update-dnsmasq-conf
Ora dobbiamo creare /etc/openvpn/routeup.sh script
#!/bin/bash
# add default route through vpn gateway to our separate routing table
/sbin/ip route add default via $route_vpn_gateway dev $dev metric 1 table vpn
exit 0
E ora dobbiamo creare una versione modificata di update-resolv-conf, che di solito viene installata in /etc/openvpn, per creare la seconda istanza di dnsmasq. Lo chiamo /etc/openvpn/update-dnsmasq-conf
#!/bin/bash
[ "$script_type" ] || exit 0
split_into_parts()
{
part1="$1"
part2="$2"
part3="$3"
}
case "$script_type" in
up)
NMSRVRS=""
for optionvarname in ${!foreign_option_*} ; do
option="${!optionvarname}"
split_into_parts $option
if [ "$part1" = "dhcp-option" ] ; then
if [ "$part2" = "DNS" ] ; then
NMSRVRS="${NMSRVRS:+$NMSRVRS }--server $part3"
fi
fi
done
dnsmasq $NMSRVRS --no-hosts --no-resolv --listen-address=127.0.0.1 \
--port=5354 --bind-interfaces --no-dhcp-interface=* \
--pid-file=/var/run/dnsmasq/dnsmasq2.pid
;;
down)
kill -9 $(cat /var/run/dnsmasq/dnsmasq2.pid)
;;
esac
E questo dovrebbe essere tutto. Ora puoi avviare la tua connessione VPN ed eseguire in modo selettivo i processi attraverso quell'interfaccia (l'opzione --sticky assicura che i processi figli vengano eseguiti nello stesso cgroup).
cgexec -g net_cls:vpn --sticky chromium &
NOTA:per dnsmasq, assicurarsi che /etc/resolv.conf punti all'host locale (server dei nomi 127.0.0.1). La tua istanza dnsmasq principale elaborerà le query sul tuo normale percorso non VPN e utilizzerà (/var/run/dnsmasq/resolv.conf) che di solito consiste nel tuo gateway predefinito o in qualche DNS pubblico (ad esempio 8.8.8.8 di Google). La seconda istanza è usata solo dal cgroup isolato