Inilah solusi lengkap menggunakan grup kontrol (cgroups), yang memungkinkan kontrol sumber daya per proses. Grup kontrol jaringan memungkinkan isolasi rute VPN, dengan mudah memungkinkan proses apa pun dan anak-anaknya dijalankan secara selektif di dalamnya, memungkinkan pengguna non-root diberikan akses ke proses yang berjalan di dalam cgroup, dan menggunakan contoh kedua dnsmasq dapat mengisolasi DNS pertanyaan juga. Ini mengasumsikan Anda memiliki openvpn, dnsmasq, cgroup, dan versi 1.6+ dari iptables dengan dukungan cgroup diinstal. Ini semua dilakukan di Debian Jessie
Langkah pertama adalah membuat cgroup dan mengatur iptables yang sesuai. Ini harus dilakukan pada setiap reboot, jadi saya menempatkan yang berikut di /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
Langkah selanjutnya adalah mengedit file konfigurasi klien VPN pihak ke-3 Anda, mis. /etc/openvpn/client.conf . Biarkan sisa konfigurasi Anda tidak berubah.
# 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
Sekarang kita perlu membuat /etc/openvpn/routeup.sh skrip
#!/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
Dan sekarang kita perlu membuat versi modifikasi dari update-resolv-conf, yang biasanya terinstal di /etc/openvpn, untuk membuat instance kedua dari dnsmasq. Saya menyebutnya /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
Dan itu seharusnya. Sekarang Anda dapat memulai koneksi vpn dan menjalankan proses secara selektif melalui antarmuka tersebut (opsi --sticky memastikan bahwa proses anak dijalankan di cgroup yang sama).
cgexec -g net_cls:vpn --sticky chromium &
CATATAN:Untuk dnsmasq, pastikan /etc/resolv.conf mengarah ke localhost (nameserver 127.0.0.1). Instance dnsmasq utama Anda akan memproses kueri pada rute non-VPN normal Anda dan menggunakan (/var/run/dnsmasq/resolv.conf) yang biasanya terdiri dari gateway default Anda atau beberapa DNS publik (mis. Google 8.8.8.8). Instance kedua hanya digunakan oleh cgroup yang terisolasi