iptables-目标将数据包路由到特定接口?


25

我的家庭服务器有两个主要接口,eth1(标准Internet连接)和tun0(OpenVPN隧道)。我想iptables强制UID 1002拥有的本地进程生成的所有数据包都通过退出tun0,而所有其他数据包都通过退出eth1

我可以轻松标记匹配的数据包:

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

现在,我想在POSTROUTING链(可能是mangle表)中放置一些规则,以匹配标记为11的数据包并将其发送到tun0,然后是匹配所有数据包并将其发送到的规则eth1

我找到了ROUTE目标,但这似乎只重写了源接口(除非我读错了它)。

iptables有能力做到这一点吗?我是否必须弄乱路由表(通过ip route或仅通过旧route命令)?

编辑:我认为也许我应该提供更多信息。我目前没有其他iptables规则(尽管我将来可能会创建一些规则来执行无关的任务)。同样,输出ip route为:

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

我没有碰过路由表-这就是目前的样子(尽管看起来很脏)。抱歉,route这台计算机上没有安装旧命令。

并且ip addr(当然,可以忽略eth0和eth2 的输出-它们是目前不使用的NIC):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

编辑:我已经有点工作,但它不转发标记的数据包到tun0。基本上,我添加了一个表(11),并使用了:

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

当我刚sudo -u user1000 wget -qO- whatismyip.org获得时,我获得了我家的外部IP地址,但是如果sudo -u user1002 wget -qO- whatismyip.org获得了,我也获得了我家的IP地址(但我应该在OpenVPN隧道的另一端获得IP)。

运行iptables -vL确认数据包已被标记规则匹配,但它们似乎未遵循路由规则。

编辑:我已经花了很长时间了,尽管它仍然无法正常工作,但我想我离这儿还很近。

iptables规则必须在mangle表的OUTPUT链中。我想我还需要nat表的POSTROUTING链中的MASQUERADE规则来设置源地址。但是,OUTPUT的混乱之后发生的重新路由不能正常工作。

我现在已经花了5个小时了,所以我要休息一下,可能会在今晚晚些时候或明天的某个时候返回。

Answers:


26

我最近遇到了类似的问题,尽管略有不同。我想航线在一个OpenVPN tap0中接口的TCP端口25(SMTP),而路由所有其他流量(即使是相同的主机)在默认界面。

为此,我必须标记数据包并设置处理它的规则。首先,添加一条规则,使内核路由2通过表标记的数据包3(稍后说明):

ip rule add fwmark 2 table 3

您可以在上添加符号名称/etc/iproute2/rt_tables,但是我没有这样做。数量23是随机选择的。实际上,它们可以相同,但为清楚起见,在此示例中我没有这样做(尽管我是在自己的设置中这样做的)。

假设网关为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

仅当数据包来自本地计算机时,以上规则才适用。参见http://inai.de/images/nf-packet-flow.png。根据您的要求进行调整。例如,如果您只想通过该tap0接口路由传出HTTP流量,请将465更改为80。

为了防止通过发送的数据包将tap0您的LAN地址用作源IP,请使用以下规则将其更改为您的接口地址(假定10.0.0.2为interface的IP地址tap0):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.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

为什么使用SNAT代替MASQUERADE?MASQUERADE不会做同样的事情,只是IP地址是在“运行时”时从接口收集的,而不是硬编码到配置文件中的?
伊桑(Ethan)2012年

6
@Ethan From man iptables仅应与动态分配的IP(拨号)连接一起使用:如果您具有静态IP地址,则应使用SNAT目标。伪装等同于指定到数据包出接口的IP地址的映射,但是还具有当接口断开时会忘记连接的效果。没错,但是由于我的IP永远不会改变,因此我决定根据手册页的建议使用SNAT。
Lekensteyn 2012年

我认为(尽管未经测试)最后一步(反向路径源验证)不是必需的。您可以简单地将另一条规则添加到PREROUTING链中,DNAT以正确的源地址(根据您的默认网关)。
克里斯蒂安·沃尔夫

7

我解决了 问题在于表11中的路由规则。表11 遭到了攻击,但是路由规则使其无法使用。该脚本是我现在使用的脚本,似乎运行良好(尽管它显然特定于我的设置)。另外,我创建了一个新表21专门用于主上行链路(eth1)。

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCode编辑(因为我无法发表评论)

感谢您的回答!似乎这可能会变得混乱,因为您必须在此处维护路由信息(可能重复或破坏了其他可能要设置路由的内容)。

您可能会在OpenVPN的路由表中遇到“奇怪的事情”,因为服务器配置为“推送”路由,使所有流量都可以通过VPN网络接口而不是“裸”互联网进行路由。或者您的OpenVPN配置或任何设置它的脚本/应用程序正在设置路由。

在前一种情况下,你可以编辑你的OpenVPN的配置,把含有“路由nopull”一行
在为OpenVPN的或任何包装后,检查配置(网络管理器,OpenVPN的,例如在许多目前的Linux桌面发行版)
在无论哪种情况,消除运行设置的路由配置都比刷新表更安全,更安全,这取决于运行此脚本的时间以及系统在做什么。

干杯!


2

我想你要:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

http://lartc.org/howto/lartc.netfilter.html

但是我还没有测试以上内容。


第一条命令返回“错误:“至”重复,或“ 10.32.0.49”为垃圾。”
伊桑(Ethan)

对不起,忘记了默认值和IP之间的通孔。
mfarver 2011年

我尝试过这个。它似乎与default省略关键字具有相同的效果。
伊桑(Ethan)

要消除选项,您可以尝试在tun0上捕获数据包,并查看数据包是否最终在该接口上。tcpdump -i tun0 ..或者,您是否需要基于用户ID?您能根据目的IP地址(更简单)来做吗?通过10.32.0.49
mfarver 2011年

如果不使用目标IP地址,我将无法使用-其中会有很多。从理论上讲,我也可以将它作为pid的基础,但这更加困难,因为在守护程序启动之前我不知道pid。
伊桑(Ethan)

0

无需iptables命令即可完成此操作。

对于uid 1002:

ip rule add uidrange 1002-1002 table 502

在您要说的接口上为表502添加默认路由

eth0 ip rule add default via a.b.c.d dev eth0

我测试了该命令,但该命令不起作用:Error: argument "uidrange" is wrong: Failed to parse rule type
kasperd 2015年

@kasperd,您必须确定他做错了,因为它对我来说很好。
horseyguy
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.