我有一台 Linux 机器,它通过 OpenVPN 连接路由其整个互联网流量。它被明确配置为以这种方式工作。
但是,该机器有几个应用程序不应该使用 VPN 连接(tun+)而应该通过开放连接(eth0)。
由于它不是基于目标 IP 的路由,我的第一个想法是创建一个本地 socks5 代理,应用程序应该使用它来避免使用 openVPN 通道。但是,我尝试使用 ssh -D 或其他软件执行此操作失败了(可能是我的错),我现在想知道是否有不同的更好的解决方案。
答案1
我最近发过另一个答案解决了这个特定情况,但问题并不重复,因为这个问题更具体到 OpenVPN。由于有些人喜欢对答案链接投反对票,而不是直接将答案放在问题中,所以我将其复制/粘贴到这里。
我为此苦苦挣扎,所以这里有一个完整的解决方案。它已在 Ubuntu 15 到 19.10 上测试过。您尤其可以将其与 OpenVPN 一起使用,以将某些应用程序路由到 VPN 隧道接口之外。
完整的“cgroup”解决方案
它是如何工作的?
- Linux 内核将把应用程序放入控制组。来自此 cgroup 中应用程序的网络流量将通过网络控制器级别的类 ID 进行识别。
- iptables 将标记此流量并强制其以正确的 IP 退出
- ip route 将在不同的路由表中处理标记的流量,并使用默认路由到您想要的任何网关 IP。
自动化脚本
我做了一个novpn.sh用于自动安装和运行依赖项的脚本。已在 Ubuntu 15 至 19.10 上测试。
首先启动您的 VPN。
wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help
手动操作指南
首先,安装 cgroup 支持和工具:
sudo apt-get install cgroup-lite cgroup-tools
你需要 iptables1.6.0+。获取 iptables 1.6.0 发布源,提取它,然后--disable-nftables
从 iptables 源目录运行此命令(标志将避免错误):
iptables --version
sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr \
--sbindir=/sbin \
--disable-nftables \
--enable-libipq \
--with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version
现在,真正的配置。定义一个名为的控制组novpn
。此 cgroup 中的进程将具有 classid 0x00110011
(11:11)。
sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid
现在,我们假设您想要用于特定应用程序的实际接口的eth0
网关 IP 为10.0.0.1
。代替这些是你真正想要的(从中获取信息ip route
),特别是在较新的 Ubuntu 版本中,接口有奇怪的名称。仍然以 root 身份运行:
# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11
# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE
# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables
# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn
# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn
# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done
最后,在特定界面上运行你的应用程序:
exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
killall firefox; cgexec -g net_cls:novpn firefox
或者如果您想将已经运行的进程移至 cgroup,那么......你不能!这似乎是由于 NAT(伪装)功能造成的:iptables -nvL -t nat
在切换 cgroup 时不匹配,但iptables -nvL -t mangle
确实匹配。
# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls
致谢:没有答案按预期工作,但其中的一些确实做到了:chripell 答案 evolware 文章每个进程路由需要 2:使用 cgroups、iptables 和策略路由,如何使特定进程不通过 OpenVPN 连接?,基于 iptables 的 OpenVPN 终止开关