是否可以在外部同一台PC的两个网卡之间发起IP连接?

是否可以在外部同一台PC的两个网卡之间发起IP连接?

如果 Linux 计算机中的两个 NIC 使用外部电缆直接相互连接,那么是否可以通过该电缆在这两个 NIC 之间启动 IP 连接?

我分别配置了两个 NICeth2eth3IP 地址。然后我从表中删除了与这两个接口关联的所有规则:10.10.123.2/2410.10.123.3/24local

# ip rule
0:      from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default 
# ip route show table local | grep -E "eth2|eth3"
# 

..并向main表中添加了连接10.10.123.3应经过的规则eth2和连接10.10.123.2应经过的规则eth3

# ip route get 10.10.123.3
10.10.123.3 dev eth2  src 10.10.123.2 
    cache 
# ip route get 10.10.123.2
10.10.123.2 dev eth3  src 10.10.123.3 
    cache 
# 

10.10.123.2现在,如果我向(源 IP 为)发送一条 ICMP“回显请求”消息10.10.123.3,则 ARP 请求消息将被放到线路上,我可以看到eth2接口收到Request who-has 10.10.123.2 tell 10.10.123.3,但由于某种原因它不会对此进行回复。有什么想法吗?

答案1

在不进行路线操作的情况下重试,但使用

ip netns add not-me
ip link set eth2 netns not-me

这将从默认网络命名空间中删除 eth2,并且您将无法看到它。恢复:ip link set eth2 netns 1。要在新命名空间中运行命令:ip netns exec not-me command....命令可能是bash打开第二个(嵌套)shell。

答案2

这是一个脚本ip交叉我不久前写过,但它应该仍然有效。它设置 iptables,以便您可以将数据包发送“给自己”,这通常是由内核短路的。它是基于这些答案

#!/bin/bash
# posted in http://unix.stackexchange.com/a/275888/119298 by meuh
# see https://serverfault.com/q/127636/294707
#  cmcginty Apr 2 '10 and Steve Kehlet answered Sep 8 '11

usage(){
        echo "$0: usage:
 config interface1 interface2
 show
 test
 tcpdump
 undo
This script sets up an iptables address translation to allow packets
to circulate over an external loopback cable between two interfaces.
You need to be root. Example usage:
 $0 config eth0:1 eth1
 $0 test
" >&2
        exit 1
}

getmac(){
        $setdebug
        local interface=${1?'interface'}
        ip link show $interface |
        awk '/link\/ether/ { print $2 }'
}
getaddr(){
        $setdebug
        local interface=${1?'interface'}
        ip addr show $interface |
        awk '/ inet / { split($2,x,"/"); print x[1] }'
}
# return true if have name of 2 interfaces
haveconfig(){
        $setdebug
        [ -n "$if1" -a -n "$if2" ] &&
        ip link show "$if1" &&
        ip link show "$if2"
}
# set variables from $if1 and $if2
setup(){
        $setdebug
        if ! haveconfig >/dev/null
        then    haveconfig >&2
                echo "Start with 'config' and 2 valid interfaces" >&2
                usage
        fi
        realprefix=10.50
        fakeprefix=10.60
        real1=$realprefix.0.1
        fake1=$fakeprefix.0.1
        real2=$realprefix.1.1
        fake2=$fakeprefix.1.1
        mac1=$(getmac $if1)
        mac2=$(getmac $if2)
}
doconfig(){
        doifconfig
        doiptables
        doroute
        doarp
        echo "eg: ping $fake2"
}
# Give IPs to the interfaces, and put them on separate networks:
doifconfig(){
        $setdebug
        ifconfig $if1 $real1/24
        ifconfig $if2 $real2/24
}

# set up a double NAT scenario: two new fake networks used to reach the
# other. On the way out, source NAT to your fake network. On the way in,
# fix the destination. And vice versa for the other network:
doiptables(){
        $setdebug
        # nat source IP $real1 -> $fake1 when going to $fake2
        iptables -t nat -A POSTROUTING -s $real1 -d $fake2 -j SNAT --to-source $fake1
        # nat source IP $real2 -> $fake2 when going to $fake1
        iptables -t nat -A POSTROUTING -s $real2 -d $fake1 -j SNAT --to-source $fake2

        # nat inbound $fake1 -> $real1
        iptables -t nat -A PREROUTING -d $fake1 -j DNAT --to-destination $real1
        # nat inbound $fake2 -> $real2
        iptables -t nat -A PREROUTING -d $fake2 -j DNAT --to-destination $real2
}

# tell the system how to get to each fake network
doroute(){
        $setdebug
        ip route flush cache
        ip route add $fake2 dev $if1 src $real1
        ip route add $fake1 dev $if2 src $real2
}
# prepopulate the arp entries
doarp(){
        $setdebug
        ip neigh add $fake2 lladdr $mac2 dev $if1
        ip neigh add $fake1 lladdr $mac1 dev $if2
}
doshow(){
        $setdebug
        iptables -L -t nat -v -n -x
        ip route get $fake1
        ip route get $fake2
        arp -n
}
# undo all configuration
doundo(){
        iptables -F -t nat
        ip route del $fake2 dev $if1
        ip route del $fake1 dev $if2 
        ip route flush cache
        #arp -i $realif1 -d $fake2
        #arp -i $realif2 -d $fake1
        ip neigh del $fake2 lladdr $mac2 dev $if1
        ip neigh del $fake1 lladdr $mac1 dev $if2
        ip addr del $real1/24 dev $if1
        ip addr del $real2/24 dev $if2
}
# tcpdump of just the wanted packets, in case using nfs on interface
dotcpdump(){
        tcpdump -n -e -i fm1-gb1 ether src $mac1 or ether src $mac2 or ether dst $mac1 or ether dst $mac2
}
showpacketcounts(){
        echo -n "$1 "
        local realif=${1%:*}
        ifconfig "$realif" |
        awk '/packets/{printf "%s %-20s",$1,$2; if(/TX/)printf "\n"}'
}
showiptablescounts(){
        iptables -L -t nat -v -x |
        awk '       $3~/[SD]NAT/ { result = result " " $1 " " $3}
                END {print "iptables counts " result }'
}
showcounts(){
        showpacketcounts $if1
        showpacketcounts $if2
        showiptablescounts
}
showdiffs(){
        echo -e "==\n$old\n==\n$new" |
        awk '/^==/{ part++; i = 0; next }
                { inp[part][++i] = $0 }
        END { end = i; for(i = 1;i<=end;i++)print inp[1][i] "\n" inp[2][i] }'
}
# use netstat -l -t to see what services you could test
dotest(){
        old=$(showcounts)
        for ip in $fake1 $fake2
        do      ping -c 4 $ip # -W 1
                echo
                traceroute -M udp $ip # -m 2
                echo
                rpcinfo -p $ip | head -3
                echo
        done
        new=$(showcounts)
        showdiffs
}

# eg ping $fake2 goes out $if1, the source IP $real1 gets NATted to $fake1,
# and as it comes into $if2 the destination $fake2 gets NATted to $real2.
# And the reply takes a similar journey.

# to use iperf to test throughput. Bind to the correct IPs, and be certain
# which IP you're contacting (the other end's fake address):
# server
#./iperf -B $real2 -s
# client: your destination is the other end's fake address
#./iperf -B $real1 -c $fake2 -t 60 -i 10

setdebug= 
case $- in
*x*)        setdebug='set -x' ;; 
esac
PATH=$PATH:/sbin:/usr/sbin

# read saved config
CONFIGFILE=~/.ipcrossover
if [ -s $CONFIGFILE ]
then        source $CONFIGFILE
fi

while [ $# -gt 0 ]
do      cmd=$1; shift
        case $cmd in
        config) if [ $# -ge 2 ] && ip link show "$1" >/dev/null
                then    if1=$1
                        if2=$2
                        shift 2
                        echo "if1=$if1; if2=$if2" >$CONFIGFILE
                fi
                setup
                doconfig ;;
        show|test|undo|tcpdump)
                setup
                do$cmd ;;
        *)      usage ;;
        esac
done

使用方法相当简单

sudo ipcrossover config eth0 eth1
ping 10.60.0.1
ping 10.60.1.1
sudo ipcrossover test

eth0:1 eth1:1(如果您不想干扰这些接口上的现有网络,则可以使用别名)。使用 拆除配置sudo ipcrossover undo。它的工作原理是在第一个接口上添加新的 IP 地址 10.50.0.1 和 10.60.0.1,在第二个接口上添加新的 IP 地址 10.50.1.1 和 10.60.1.1,并按照脚本中的设置进行操作:

        realprefix=10.50
        fakeprefix=10.60
        real1=$realprefix.0.1
        fake1=$fakeprefix.0.1
        real2=$realprefix.1.1
        fake2=$fakeprefix.1.1

例如,ping $fake2从接口 $if1 出去,源 IP $real1 被 NAT 转换为 $fake1,当它进入 $if2 时,目标 IP $fake2 被 NAT 转换为 $real2。回复也经历了类似的过程。

要用于iperf测试吞吐量,请绑定到正确的 IP,并确定您正在联系哪个 IP(另一端的假地址): 在服务器上./iperf -B $real2 -s。在客户端上,您的目的地是另一端的假地址: ./iperf -B $real1 -c $fake2 -t 60 -i 10

通过拔掉电缆并检查 ping 停止来验证它是否正常工作!请确保您阅读了链接的答案了解发生了什么事。

答案3

默认情况下,Linux 内核会响应来自任何接口的任何接口的 ARP 请求。这种行为有时是不可取的。

要更改此行为,您需要修改一些内核参数:

echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore 
echo 1 > /proc/sys/net/ipv4/conf/eth1/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/eth1/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_filter
echo 1 > /proc/sys/net/ipv4/conf/eth1/arp_filter

您还可以使用以下命令为计算机中的所有接口更改此设置:

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter

查看这些网络内核参数的含义,如果最后这些命令不能按您的预期工作,请根据您的特定需求进行调整:

arp_ignore- 整数

定义不同的模式来发送回复以响应接收到的解析本地目标 IP 地址的 ARP 请求:

  • 0 -(默认):回复任何本地目标 IP 地址,在任何接口上配置
  • 1 - 仅当目标 IP 地址是传入接口上配置的本地地址时才回复
  • 2 - 仅当目标 IP 地址是传入接口上配置的本地地址并且两者与发送者的 IP 地址属于该接口上的同一子网时才进行回复
  • 3 - 不回复使用范围主机配置的本地地址,仅回复全局和链接地址的解析
  • 4-7 - 保留
  • 8 - 不回复所有本地地址

当 {interface} 上收到 ARP 请求时,使用 conf/{all,interface}/arp_ignore 中的最大值

arp_announce- 整数

定义不同的限制级别,用于从接口上发送的 ARP 请求中的 IP 数据包中公布本地源 IP 地址:

  • 0 -(默认)使用在任何接口上配置的任何本地地址
  • 1 - 尽量避免使用不在该接口的目标子网中的本地地址。当可通过此接口访问的目标主机要求 ARP 请求中的源 IP 地址成为接收接口上配置的逻辑网络的一部分时,此模式非常有用。当我们生成请求时,我们将检查包含目标 IP 的所有子网,如果源地址来自此类子网,则将保留源地址。如果不存在这样的子网,我们根据级别 2 的规则选择源地址。
  • 2 - 始终使用该目标的最佳本地地址。在此模式下,我们忽略 IP 数据包中的源地址,并尝试选择我们喜欢与目标主机进行对话的本地地址。此类本地地址是通过在传出接口上查找包含目标 IP 地址的所有子网上的主 IP 地址来选择的。如果没有找到合适的本地地址,我们会选择在传出接口或所有其他接口上拥有的第一个本地地址,希望我们能够收到对我们的请求的答复,甚至有时无论我们宣布的源 IP 地址如何。

使用conf/{all,interface}/arp_announce 中的最大值。

增加限制级别可以有更多机会从已解决的目标接收答案,而降低级别则可以公布更多有效的发件人信息。

arp_filter- 布尔值

  • 1 - 允许您在同一子网上拥有多个网络接口,并根据内核是否将来自 ARP 的 IP 的数据包路由到该接口(因此您必须使用基于源的源)来应答每个接口的 ARP。使其工作的路由)。换句话说,它允许控制哪些卡(通常是 1 个)将响应 arp 请求。

  • 0 -(默认)内核可以使用来自其他接口的地址响应 arp 请求。这可能看起来是错误的,但通常是有道理的,因为它增加了成功沟通的机会。 IP 地址由 Linux 上的整个主机拥有,而不是由特定接口拥有。仅对于负载平衡等更复杂的设置,此行为才会导致问题。

如果conf/{all,interface}/arp_filter至少其中之一设置为TRUE,则接口的arp_filter将被启用,否则它将被禁用

您可以在中查看更多相关网络参数https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

答案4

我使用 Linux 网络命名空间来完成此任务。我ns1为其中一个端口创建了一个单独的命名空间,称之为。

我将接口添加eth1到该命名空间并为其分配了 IP 地址192.168.2.1/24。同样在ns1命名空间内,我强制所有进出该命名空间的网络流量使用eth1

ip route add default dev eth1

然后我将 IP 地址分配192.168.1.1/24给另一个以太网端口 ,该端口eth0仍然驻留在根命名空间中。我还在根命名空间中添加了一条到ns1命名空间的路由:

ip route add 192.168.2.0/24 dev eth0

现在您可以从 192.168.2.1 ping 192.168.1.1,反之亦然。拔掉 eth0 和 eth1 之间的电缆,观察数据包停止流动。

您还可以通过 iperf 检查带宽来验证您是否正在使用电缆。在ns1命名空间中,运行 iperf 服务器:

iperf -s -f m -i 5

在根命名空间中运行 iperf 客户端:

iperf -c 192.168.2.1 -t 60

相关内容