题 强制本地IP流量到外部接口


我有一台具有多个接口的机器,我可以根据需要进行配置,例如:

  • eth1:192.168.1.1
  • eth2:192.168.2.2

我想通过另一个接口转发发送到这些本地地址之一的所有流量。例如,对192.168.1.1的iperf,ftp,http服务器的所有请求不应仅在内部路由,而应通过eth2转发(外部网络将负责将数据包重新路由到eth1)。

我试过看了几个命令,比如iptables,ip route等......但没有任何效果。

我能得到的最接近的行为是:

ip route change to 192.168.1.1/24 dev eth2

它在eth2上发送所有192.168.1.x,但192.168.1.1除外,它仍在内部路由。 也许我可以在eth1上执行针对假冒192.168.1.2的所有流量的NAT转发,在内部重新路由到192.168.1.1?我实际上正在努力使用iptables,但这对我来说太难了。

此设置的目标是在不使用两台PC的情况下进行接口驱动程序测试。

我正在使用Linux,但如果你知道如何用Windows做这件事,我会买的!

编辑:

外部网络只是eth1和eth2之间的交叉电缆。 假设我的机器上有一个http服务器。 现在我想从同一台机器访问此服务器,但我想强制TCP / IP流量通过此eth1 / eth2电缆。我该如何为此配置接口?


29
2018-03-30 12:09




您是说要通过接口1和2镜像所有流量,但只能从另一个路由器返回到接口2?难道不能在网络上做一些非常奇怪的东西吗?将镜像流量从接口2引导到另一个刚刚丢弃流量的系统,然后您可以监控它,还是使用虚拟化软件来捕获流量,会不会更好?也许我在描述中遗漏了一些东西。 - Bart Silverstrim
听起来他想要生成一个数据包,比如192.168.1.1,这是eth1的IP。但是,而不是完全在内部接收该数据包的Linux堆栈,他希望数据包被强制退出eth2(它将被外部传送回eth1,然后是Linux堆栈)。我不确定这是否可行;一旦网络层检测到地址是内部接口,它就没有理由查看路由表。其他人可能会更清楚。 - PP.


答案:


我扩展了caladona的答案,因为我看不到响应数据包。对于这个例子:

  1. 在我的本地PC上,我有不同子网上的NIC, 192.168.1 / 24192.168.2 / 24 
  2. 有一个外部路由器/ PC可以访问这两个子网。
  3. 我想通过本地PC上的NIC发送双向流量。
  4. 配置需要每个子网有两个未使用的IP地址。

本地PC iptable路由设置为SNAT和DNAT传出流量到'假'IP。

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100
iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1
iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100
iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

规则执行以下操作:

  1. 在传出数据包上将192.168.2.1源重写为192.168.2.100
  2. 在传入的数据包上将192.168.1.100目标重写为192.168.1.1
  3. 在传出数据包上将192.168.1.1源重写为192.168.1.100
  4. 在传入的数据包上将192.168.2.100目标重写为192.168.2.1

总而言之,本地系统现在可以与地址为192.168.1.100和192.168.2.100的“虚拟”机器通信。

接下来,您必须强制您的本地PC使用外部路由器来访问您的虚假IP。您可以通过路由器创建到IP的直接路由来完成此操作。您希望确保将数据包强制到目标子网的对面。

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 
ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

最后,为了使这一切工作,外部路由器需要知道如何到达本地PC上的伪造IP。您可以通过打开系统的代理ARP来执行此操作。

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

通过此设置,您现在可以将伪造的IP视为本地PC上的真实系统。将数据发送到.1子网将强制数据包退出.2接口。将数据发送到.2子网将强制数据包退出.1接口。

ping 192.168.1.100
ping 192.168.2.100

15
2018-04-02 03:34



你的方式好多了!请注意,我还需要一个ip_forward来使ARP工作正常:echo 1> / proc / sys / net / ipv4 / ip_forward - calandoa


我成功地在Linux上使用以下内容来测试新的双端口10Gbps卡在“环回”模式下的吞吐量,即一个端口直接插入另一个端口。这只是为了强制数据包通过线路而有点巫术,但如果你不这样做,Linux将只通过内核短路流量(因此OP的问题)。在凯西上面的回答中,我不确定是否真的有必要使用外部路由器或不在上面,但以下是完全独立的。这两个接口是eth2和eth3。

为接口提供IP,并将它们放在不同的网络上:

ifconfig eth2 10.50.0.1/24
ifconfig eth3 10.50.1.1/24

接下来我们将设置一个双NAT场景:两个新的假网络用于到达另一个。在出路上,将NAT发送到您的虚假网络。在途中,修复目的地。对于其他网络反之亦然:

# nat source IP 10.50.0.1 -> 10.60.0.1 when going to 10.60.1.1
iptables -t nat -A POSTROUTING -s 10.50.0.1 -d 10.60.1.1 -j SNAT --to-source 10.60.0.1

# nat inbound 10.60.0.1 -> 10.50.0.1
iptables -t nat -A PREROUTING -d 10.60.0.1 -j DNAT --to-destination 10.50.0.1

# nat source IP 10.50.1.1 -> 10.60.1.1 when going to 10.60.0.1
iptables -t nat -A POSTROUTING -s 10.50.1.1 -d 10.60.0.1 -j SNAT --to-source 10.60.1.1

# nat inbound 10.60.1.1 -> 10.50.1.1
iptables -t nat -A PREROUTING -d 10.60.1.1 -j DNAT --to-destination 10.50.1.1

现在告诉系统如何到达每个虚假网络,并预先填充arp条目(确保替换你的MAC地址,不要使用我的):

ip route add 10.60.1.1 dev eth2
arp -i eth2 -s 10.60.1.1 00:1B:21:C1:F6:0F # eth3's mac address

ip route add 10.60.0.1 dev eth3 
arp -i eth3 -s 10.60.0.1 00:1B:21:C1:F6:0E # eth2's mac address

这足以让Linux足以将数据包放到线路上。例如:

ping 10.60.1.1

淘汰eth2,源IP 10.50.0.1获得NAT到10.60.0.1,当它进入eth3时,目标10.60.1.1被NATted到10.50.1.1。回复也是类似的旅程。

现在使用iperf测试吞吐量。绑定到正确的IP,并确定您正在联系哪个IP(另一端的虚假地址):

# server
./iperf -B 10.50.1.1 -s

# client: your destination is the other end's fake address
./iperf -B 10.50.0.1 -c 10.60.1.1 -t 60 -i 10

确保流量真正走向电线:

tcpdump -nn -i eth2 -c 500

您还可以观看/ proc / interrupts以确保正在使用该卡:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

无论如何,我发现这篇文章正在寻找如何做到这一点,感谢问答人员,并希望这有助于其他人在将来找到这篇文章。


28
2017-09-08 16:31



+1很棒的解决方案 - 这甚至不需要激活ip-forwarding!这正是我现在所需要的(通过环回进行10GB测试)。 - Nils
哇,谢谢@Nils的赏金! - Steve Kehlet


一如既往 - 我有点迟了 - 但现在可以使用网络命名空间来隔离接口并阻止任何本地转发(和摆弄iptables :))。

创建命名空间(全部使用所需权限完成,例如以root身份):

ip netns add ns_server
ip netns add ns_client

请注意,现在必须在其中访问interfaces status / config 指定命名空间的上下文 - 因此如果您运行裸体,它们将不会出现 ip链接 因为它是在默认命名空间的上下文中运行的。 可以使用在命名空间内运行命令

ip netns exec <namespace-name> <command>

作为前缀。

现在为接口分配名称空间,应用config并设置接口:

ip link set eth1 netns ns_server
ip netns exec ns_server ip addr add dev eth1 192.168.1.1/24
ip netns exec ns_server ip link set dev eth1 up
ip link set eth2 netns ns_client
ip netns exec ns_client ip addr add dev eth2 192.168.1.2/24
ip netns exec ns_client ip link set dev eth2 up

现在,您可以在命名空间内执行应用程序 - 用于运行iperf服务器

ip netns exec ns_server iperf -s -B 192.168.1.1

和客户:

ip netns exec ns_client iperf -c 192.168.1.1 -B 192.168.1.2

流量现在将通过物理接口发送,因为整个网络堆栈,接口,路由...被命名空间隔离,因此内核无法将流量中使用的地址与本地(可用)接口进行匹配。

如果您完成了实验,只需删除命名空间:

ip netns del <namespace-name>

接口将重新分配到默认命名空间,并且命名空间内完成的所有配置都将消失(例如,无需删除分配的IP地址)。


7
2017-07-11 09:12





好的,我终于成功设置了我的配置。

想法是使用另一个假地址,强制将这个假地址的路由到接口2,然后使用NAT / iptables将真实地址2转换为假地址。

我的设置实际上是由一个路由器组成的,我可以在IF1(接口1)和IF2之间进行远程登录

在我的设置中,FAKE_ADDR和IF1_ADDR位于同一子网上。

ifconfig $IF1 $IF1_ADDR netmask 255.255.255.0
ifconfig $IF2 $IF2_ADDR netmask 255.255.255.0

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR
iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

在路由器上:

route add $FAKE_ADDR gw $IF2_ADDR

如果我向FAKE_ADDR发送内容,则pkt通过IF1转发到路由器,再次转发到IF2,然后FAKE_IP被IF2_ADDR替换。数据包由服务器处理,结果从IF2_ADDR发送回IF1_ADDR,IF2_ADDR由FAKE_ADDR替换。

可能只使用一根交叉电缆就可以使用更简单的配置,但正如我没试过的那样,我更愿意提供我的工作解决方案。


3
2018-03-30 15:52



如果路由器发送$ FAKE_ADDR到$ IF2_ADDR,你的DNAT规则不是“-i $ IF2”而不是“-i $ IF1”吗? - cmcginty
你是对的凯西,纠正完成。 - calandoa


ThomasTannhäuser上面给出的答案就是现场!

我有类似的情况:一台机器有两个enet接口。我的计划是使用一个接口作为服务器(接收方),另一个接口作为客户端(发送方)。每个接口都将连接到路由器,iperf将通过路由器驱动流量,以测量吞吐量,PPS,延迟等。

不幸的是,iptables方法不直观,充满了问题。经过几个令人沮丧的时间后,我放弃了这个攻击计划。受托马斯建议的启发,我在Linux IP命名空间上做了一些功课,并开始欣赏这个解决方案的简洁和优雅。

下面列出了我用来配置我的Fedora FC26以此容量服务的确切命令。这两个接口是enp1s0和enp3s0。路由器有两个接口,地址为192.168.2.112和172.16.16.2。每个FC26 ENET连接器都直接连接到相应的路由器接口。

# How to configure the IP Namespaces
ip netns add iperf-server
ip netns add iperf-client
ip link set enp1s0 netns iperf-server
ip link set enp3s0 netns iperf-client
ip netns exec iperf-server ip addr add dev enp1s0 192.168.2.139/20
ip netns exec iperf-client ip addr add dev enp3s0 172.16.16.2/24
ip netns exec iperf-client ip link set dev enp3s0 up
ip netns exec iperf-server ip link set dev enp1s0 up
ip netns exec iperf-server route add default gw 192.168.2.112
ip netns exec iperf-client route add default gw 172.16.16.1

# Test the interfaces and network using ping
ip netns exec iperf-client ping -c1 172.16.16.1
ip netns exec iperf-server ping -c1 192.168.2.112
ip netns exec iperf-server ping -c1 172.16.16.2
ip netns exec iperf-client ping -c1 192.168.2.139

# Start Iperf Server for UDP test
ip netns exec iperf-server iperf -u -s
# Run Client against Iperf server for UDP test
ip netns exec iperf-client iperf -u -c 192.168.2.139

1
2017-08-22 22:51





听起来你想把你的linux盒子变成路由器/网桥/网关/防火墙类型的盒子。您可能正在寻找以下资源:

Linux路由器项目

路由器或防火墙分发列表

Linux LiveCD路由器

Linux Journal - Linux路由器

根据进一步信息更新:

我认为你不能做你想做的事。操作系统总是会查看其内部路由表并在本地“查看”两个IP地址。然后,它将在OS内路由流量,并且永远不会将其置于线路上。您将需要第二台机器或两台虚拟机(退房 Xen的)。


0
2018-03-30 12:35





很多东西要经过这里,所以我无法完全保证我的准确性,但最初的问题似乎是寻找所谓的 “发送给自己”的技巧。链接搜索显示了我的想法 保存最好的内核补丁 作为顶级链接+讨论和补丁与各种邮件列表上的其他方法,尤其是LKML。

我想也应该看一下 网络名称空间,用iproute2完成 “ip netns”。这也需要一些额外的界面和路由魔法,所以甚至可能没有其他答案中的大量iptables hoopla复杂。

如果有人发现了一些有用的东西,那么评论肯定会受到欢迎 - 你的实施的方式,内容,地点。


0
2017-12-28 15:29