根据进程将 IP 流量路由到不同的默认路由/接口

根据进程将 IP 流量路由到不同的默认路由/接口

我正在尝试确定是否可以通过特定接口选择性地路由来自进程或进程组的 IP 数据包,而所有其他数据包则通过另一个接口路由。也就是说,我希望所有来自 的流量都通过/usr/bin/testapp路由,eth1而所有其他数据包都通过eth0。在这种情况下,数据包可以是 TCP、UDP、ICMP 等,并且可以由最终用户配置为使用各种端口。

由于我无法轻松强制相关进程绑定到特定接口,因此我尝试通过路由实现相同的结果。这可能吗?

- - 编辑 - -

这里和其他地方都提出了一个有用的建议,那就是根据 UID 标记数据包;但这并不是真正的目标。目标是根据进程标记/过滤/路由无论用户也就是说,如果alicebobcharlie运行自己的 实例/usr/bin/testapp;则所有三个实例的所有数据包都应该通过 ,eth1而系统中的所有其他数据包都应该通过eth0

请注意,按源/目标端口、用户名/UID 等进行标记是不够的,因为不同的用户可能会运行testapp,并且他们可能会自行设置不同的端口~/.config/testapp.conf。问题在于按进程进行过滤。

尽管我不知道它有多大帮助,但有一个可用的选项是/bin/(ba|z)?sh对本机二进制文件使用基于的包装器。

- - 编辑 - -

我指的是在运行现代 Linux 内核(例如 4.0 或更高版本)的系统上进行路由。如果存在超出iproute2nftablesconntrack类似工具的软件依赖关系,我愿意探索开源解决方案,尽管基本工具更可取。

答案1

您通过 eth1 或 eth0 路由数据包。tables mangle 应该可以解决这个问题。为此,我必须标记数据包并设置处理它的规则。首先,添加一条规则,使内核通过 table 路由标记为 2 的数据包

ip rule add fwmark 2 table 3

添加一条路由,用于通过不同的接口重定向流量,假设网关为 10.0.0.1:

ip route add default via 10.0.0.1 table 3

刷新你的路由缓存。

ip route flush cache

现在,设置标记指定数据包的防火墙规则:

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

最后,放宽反向路径源验证。有人建议你将其设置为 0,但根据 ,2 似乎是更好的选择https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt。如果你跳过这一步,你会收到数据包(可以使用 确认tcpdump -i tap0 -n),但数据包不会被接受。更改设置以便数据包被接受的命令如下:

sysctl -w net.ipv4.conf.tap0.rp_filter=2

参考 :http://serverfault.com/questions/345111/iptables-target-to-route-packet-to-specific-interface

答案2

您可以使用特定用户运行该进程,并将数据包与 iptable 的owner扩展进行匹配。匹配后,您可以对其进行标记,并将其与另一个路由表一起使用,POSTROUTING或者使用您可能喜欢的任何解决方案。

帖子更好地解释了数据包匹配owner

答案3

可以使用网络命名空间隔离进程,使用虚拟以太网连接将该网络命名空间连接到主命名空间。然后,您可以使用 iptables 根据该源进行路由。

这是一个例子。我使用网络管理器执行一些命令,但你可以直接执行

# Create a namespace
ip netns add ns1

# create a bridge between them
nmcli connection add type veth ifname virt0 peer virt1
ip link set virt1 netns ns1
ip addr add 192.168.69.1/24 dev virt0
ip netns exec ns1 ip addr add 192.168.69.2/24 dev virt1
ip netns exec ns1 ip link up virt1
echo 1 > sudo tee /proc/sys/net/ipv4/ip_forward

# At this point traffic from ns1 will appear in your main network namespace as coming from ip 192.168.69.2 dev virt0, so you can handle it from there.  You will need NAT to make it go somewhere useful.
# In this case I want the traffic to go out through interface vpn1, which is not a default route on my system.

# Add your process-specific routing rules in a non-default table (12345 in this case)
ip route add default dev vpn1 table 12345 proto static scope link metric 50
# Set up a rule to use that table for the traffic coming from that IP, with lower priority than the default table's rule.
ip rule add priority 30000 from 192.168.69.0/24 lookup 12345
# Add the nat, so that the traffic can actually exist on your outbound interface
iptables -t nat -A POSTROUTING -o vpn1 -j MASQUERADE

# At this point traffic from ns1 will go out through interface vpn1. Now you can run command sin that netns to utilize this.

nsenter  --net=/var/run/netns/ns1 your_program

答案4

好吧,既然您告诉我们:

由于我无法轻松强制相关进程绑定到特定接口,因此我尝试通过路由实现相同的结果。这可能吗?

我们可以从这一点开始帮助您。FreeBSD 中曾jail出现过系统调用,目的是将进程或进程组限制到系统资源的某个子部分。特别是,可以指定那些“隔离”进程将用于其网络活动的 IP 地址。这太方便了,以至于我真的很想念 Linux 中的这个功能。但 Linux 也有一些方法可以实现类似的结果:

或者,最轻量级的只是手动修改命名空间:https://unix.stackexchange.com/questions/155446/linux-is-there-handy-way-to-exec-a-program-binding-it-to-ip-address-of-choice

相关内容