AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 127636
Accepted
calandoa
calandoa
Asked: 2010-03-31 04:09:18 +0800 CST2010-03-31 04:09:18 +0800 CST 2010-03-31 04:09:18 +0800 CST

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

  • 772

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

  • 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 电缆。我应该如何为此配置我的接口?

linux networking command-line-interface ip iptables
  • 8 8 个回答
  • 79947 Views

8 个回答

  • Voted
  1. Steve Kehlet
    2011-09-09T08:31:46+08:002011-09-09T08:31:46+08:00

    我成功地在 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 被 NAT 到 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
    

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

    • 36
  2. Thomas Tannhäuser
    2017-07-12T01:12:42+08:002017-07-12T01:12:42+08:00

    和往常一样——我来晚了——但现在可以使用网络命名空间来隔离接口并防止任何本地转发(以及摆弄 iptables :))。

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

    ip netns add ns_server
    ip netns add ns_client
    

    请注意,现在必须在分配的命名空间的上下文中访问接口状态/配置 - 因此,如果您运行裸ip 链接,它们将不会出现,因为这是在默认命名空间的上下文中运行的。在命名空间中运行命令可以使用

    ip netns exec <namespace-name> <command>
    

    作为前缀。

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

    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 地址)。

    • 33
  3. Best Answer
    cmcginty
    2010-04-02T19:34:39+08:002010-04-02T19:34:39+08:00

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

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

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

    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
  4. calandoa
    2010-03-31T07:52:11+08:002010-03-31T07:52:11+08:00

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

    这个想法是使用另一个假地址,强制这个假地址到接口 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,由 FAKE_ADDR 代替。

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

    • 2
  5. RarkyMan
    2017-08-23T14:51:35+08:002017-08-23T14:51:35+08:00

    Thomas Tannhäuser 上面给出的答案是正确的!

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

    不幸的是,iptables 方法不直观且充满问题。经过几个令人沮丧的小时后,我放弃了这个攻击计划。受到 Thomas 建议的启发,我在 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
    
    • 2
  6. Peter
    2010-03-31T04:35:12+08:002010-03-31T04:35:12+08:00

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

    Linux 路由器项目

    路由器或防火墙分布列表

    Linux LiveCD 路由器

    Linux 日志 - Linux 路由器

    根据更多信息更新:

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

    • 0
  7. lkraav
    2011-12-29T07:29:05+08:002011-12-29T07:29:05+08:00

    这里有很多东西要经过,所以我不能完全保证我的准确性,但最初的问题似乎是在寻找所谓的“发送给自己”技术。链接搜索显示了我认为维护得最好的内核补丁作为顶级链接+讨论以及各种邮件列表上的其他方法的补丁,特别是。LKML。

    我认为还应该看看网络命名空间,用 iproute2 的"ip netns"完成。这也需要一些额外的接口和路由魔法,因此可能不会比其他答案中的大量 iptables hoopla 更复杂。

    如果有人发现对这些有用的东西,绝对欢迎发表评论 - 关于您的实施的方式、内容、地点。

    • 0
  8. robm
    2014-12-12T14:27:01+08:002014-12-12T14:27:01+08:00

    这就是我如何让它为 IPV6 工作

    分配静态ip

    /sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
    /sbin/ifconfig eth3 inet6 add 2001:db8::2/127 
    

    设置仅主机路由到“假”地址

    ip -6 route add 2001:db8::2/128 dev eth1 metric 1
    ip -6 route add 2001:db8::1/128 dev eth3 metric 1
    

    填充邻居表...就像 arp

    ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
    ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address
    

    添加了 ip6tables 条目

    ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
    ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
    ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
    ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2
    
    • -1

相关问题

  • 更改 PHP 的默认配置设置?

  • 有什么软件可以模拟局域网?

  • 保护新的 Ubuntu 服务器 [关闭]

  • 带宽利用工具?[关闭]

  • (软)Ubuntu 7.10 上的 RAID 6,我应该迁移到 8.10 吗?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    从 IP 地址解析主机名

    • 8 个回答
  • Marko Smith

    如何按大小对 du -h 输出进行排序

    • 30 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    MikeN 在 Nginx 中,如何在维护子域的同时将所有 http 请求重写为 https? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 bash中的双方括号和单方括号有什么区别? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    Kyle Brandt IPv4 子网如何工作? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve