我想连接到Linux中的第三方VPN服务器(例如Debian Jessie),但默认情况下仍然使用我的eth0 lan接口作为默认路由 ,并且很好奇如何实现这一点。 我将使用策略路由或networking命名空间或规则集来select何时使用第三方VPN。
但是,我不清楚openvpn在幕后做了什么,它build立了所有的stream量通过它。 为了克服这个问题,当从我的客户端连接时,是否像覆盖“redirect网关”一样简单?
这是一个使用控制组(cgroups)的完整解决scheme,它允许进行每个进程的资源控制。 一个networking控制组允许隔离VPN路由,很容易允许任何进程及其subprocess在其中运行,允许非root用户被授予访问cgroup内正在运行的进程的权限,并且使用第二个dnsmasq实例可以隔离DNS查询也是如此。 这假定你有安装了cgroup支持的iptables的openvpn,dnsmasq,cgroup和1.6+版本。 这一切都是在Debian Jessie上完成的
第一步是创buildcgroup并相应地设置iptables。 这应该在每次重新启动时完成,因此我将以下内容放在/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 croup --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
下一步是编辑你的第三方VPN的客户端configuration文件,例如/etc/openvpn/client.conf 。 保持其余的configuration不变。
# 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
我们现在需要创build/etc/openvpn/routeup.sh脚本
#!/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
我们现在需要创buildupdate-resolv-conf的修改版本,通常安装在/ etc / openvpn中,以创builddnsmasq的第二个实例。 我把它叫做/ 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
这应该是。 现在你可以启动你的vpn连接,并有select地通过这个接口运行进程(–sticky选项可以确保subprocess在同一个cgroup中运行)。
cgexec -g net_cls:vpn --sticky chromium &
注意:对于dnsmasq,请确保/etc/resolv.conf指向本地主机(名称服务器127.0.0.1)。 您的主dnsmasq实例将处理您的正常非VPN路由上的查询,并使用(/var/run/dnsmasq/resolv.conf),通常由您的默认网关或某些公共DNS(例如Google的8.8.8.8)组成。 第二个实例仅被隔离的cgroup使用
我会build议使用路由表。 您可以指定所有stream量的默认路由,然后根据需要通过VPN添加路由。
我们在nx.xc上的朋友对此做了很好的写作。