通过特定接口为Linux中的进程路由流量


20

是否可以通过特定接口路由进程使用的流量?

例如,下载应用程序的网络流量应始终使用该接口,wlan0而计算机上的所有其他应用程序应使用eth0

Linux中可能有这种规则吗?

Answers:


22

可以使用Linux网络命名空间来完成。

这是一篇说明如何做的文章。基本上,您可以使用其他默认路由创建网络名称空间,然后在其中运行需要它的进程。您可以使用网桥将新创建的网络名称空间连接到物理适配器(当然也可以使用其他解决方案)。

更新:从内核3.14开始,使用控制组更加容易,如本文所述。你必须:

1)定义一个net_cls控制组,以使用classid(或进程组,请注意它们之间没有任何父子关系)注释来自给定进程的数据包

2)使用iptables cgroup模块(在Linux 3.14中添加)对数据包进行fwmark

3)使用策略路由(ip规则添加fwmark ....)为标记的数据包创建新的路由表

优点是我们不必做桥接工作,而且由于cgroups使得一切都更加动态。


14

我为此感到非常挣扎,所以这是一个完整的解决方案。它已在Ubuntu 15和16上进行了测试。您尤其可以将它与OpenVPN结合使用,以将某些应用路由到VPN隧道接口之外。

完整的“ cgroup”解决方案

如何运作?

  • Linux内核会将应用程序放入一个控制组。来自此cgroup中应用程序的网络流量将通过其在网络控制器级别的类别ID进行标识。
  • iptables将标记此流量并强制其使用正确的IP退出
  • ip route将在不同的路由表中处理标记的流量,并使用默认路由到您想要的任何网关IP。

自动化脚本

我制作了一个novpn.sh脚本来自动化依赖项的安装和运行。在Ubuntu上测试。

首先启动您的VPN。

wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/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 cgmanager cgroup-tools

重新启动(可能没有必要)。

您需要iptables 1.6 .0+。从iptables源目录获取iptables 1.6.0发布源,将其解压缩,然后运行此命令(--disable-nftables标志将避免错误):

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中的进程的类标识为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)。以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
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的开关


感谢您的出色回答,如何使它与apache一起使用?我试着cgexec -g net_cls:novpn apache2给了我完整的变量未定义错误列表!
razzak

2
通过apache2直接从终端运行,您将得到相同的错误。那是因为apache2通常是使用来启动的systemctl start apache2。但是,这不适用于cgexec。被调用程序必须是apache2net_cls cgroup要传播的所需()进程的父级。因此,您需要找到启动脚本。在这种情况下为sudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl start。用检查./novpn.sh --list
KrisWebDev '16

它不再在Ubuntu 16.04中工作!
razzak

2
我在Ubuntu 16.04上使用它,并且工作正常。接口名称在Ubuntu 16已经改变,你可以代替需要更换eth0的类似enp7s0。从ifconfig命令获取信息。
KrisWebDev

谢谢。但由于与systemd冲突而已删除了cpmanager,因此它在Ubuntu 18.04上不起作用
skonsoft


3

结合mariusmatutiae和KrisWebDev的出色答案,我创建了一个广泛修改的版本KrisWebDev的出色novpn.sh脚本。KrisWebDev的脚本旨在消除更具体的问题(在VPN内外运行和移动进程),而我的版本允许您在指定的网络环境中基本上运行任何命令。您可以指定要绑定的接口,默认路由,指定自己的iptables规则,静态路由,指定“测试”以确认一切正常,然后再运行命令...等等)。它允许您使用多个配置文件,以便您可以定义可在其中运行命令/进程的任意数量的特定网络环境。

我将其作为要点发布在这里:https : //gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

之后它甚至可以清理cgroup / iptables / routing表!

欢迎反馈。

PS-专为Debian 8(Jessie)设计


嗨@allnatural,我想使用您的altnetworking.sh脚本,但是我应该在配置文件中放什么呢?
Cris70 '17

0

不是每个应用程序,不是。您可以按端口或IP地址等进行操作,或者应用程序本身可以绑定(并使用)特定的网卡。

但是,您无法设置规则来执行此操作。


我有一个Java应用程序,是否可以将该应用程序绑定到接口?
Suresh

您拥有Java源代码的Java应用程序,并且可以对内部程序进行重新编程吗?
Majenko 2011年

我有一个使用apache http库的Java应用程序源代码。
Suresh

然后,我将转到stackoverflow.com,并询问那里的程序员如何更改程序。我从来没有用Java编程过。
Majenko 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.