Linux

連接到 3rd 方 VPN 伺服器但不將其用作預設路由?

  • May 29, 2020

我想連接到 Linux 中的第 3 方 VPN 伺服器(例如 Debian Jessie),但預設情況下仍然使用我的 eth0 lan 介面作為預設路由,我很好奇如何實現這一點。我將使用策略路由或網路命名空間或規則集來選擇何時使用 3rd 方 VPN。

但是我不清楚 openvpn 在幕後做了什麼來建立它來引導所有流量通過它。為了克服這個問題,從我的客戶端連接時是否像覆蓋“重定向網關”一樣簡單?

這是一個使用控制組 (cgroups) 的完整解決方案,它允許每個程序的資源控制。網路控制組允許隔離 VPN 路由,輕鬆地允許任何程序及其子程序在其中有選擇地執行,允許非 root 使用者被授予訪問 cgroup 中正在執行的程序的權限,並且使用 dnsmasq 的第二個實例可以隔離 DNS查詢也是如此。這假設您已經安裝了 openvpn、dnsmasq、cgroup 和 1.6+ 版本的 iptables,並安裝了 cgroup 支持。這一切都是在 Debian Jessie 上完成的

第一步是創建 cgroup 並相應地設置 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 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

下一步是編輯您的第 3 方 VPN 的客戶端配置文件,例如*/etc/openvpn/client.conf*。保持其餘配置不變。

# 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

我們現在需要創建*/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

我們現在需要創建一個修改版本的 update-resolv-conf,它通常安裝在 /etc/openvpn 中,以創建 dnsmasq 的第二個實例。我稱之為*/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 連接並通過該介面有選擇地執行程序(–sticky 選項確保子程序在同一個 cgroup 中執行)。

cgexec -g net_cls:vpn --sticky chromium &

注意:對於 dnsmasq,確保 /etc/resolv.conf 指向 localhost(名稱伺服器 127.0.0.1)。您的主要 dnsmasq 實例將處理您正常的非 VPN 路由上的查詢並使用 (/var/run/dnsmasq/resolv.conf),它通常由您的預設網關或一些公共 DNS(例如 Google 的 8.8.8.8)組成。第二個實例只被隔離的 cgroup 使用

引用自:https://serverfault.com/questions/765989