如果 Linux 机器中的两个 NIC 使用外部电缆直接相互连接,那么是否可以通过该电缆在这两个 NIC 之间启动 IP 连接?
我配置我的两个网卡eth2,并eth3与IP地址10.10.123.2/24和10.10.123.3/24分别。然后我从local表中删除了与这两个接口相关的所有规则:
# 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"
#
Run Code Online (Sandbox Code Playgroud)
..并在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
#
Run Code Online (Sandbox Code Playgroud)
现在,如果我向10.10.123.2(源 IP 将是10.10.123.3)发送一个 ICMP“回显请求”消息,那么 ARP 请求消息会被放到线路上,我可以看到该eth2接口接收到Request who-has 10.10.123.2 tell 10.10.123.3,但由于某种原因它没有回复这个。任何想法为什么?
这是我不久前编写的ipcrossover脚本,但它应该仍然有效。它设置 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
Run Code Online (Sandbox Code Playgroud)
使用方法相当简单
sudo ipcrossover config eth0 eth1
ping 10.60.0.1
ping 10.60.1.1
sudo ipcrossover test
Run Code Online (Sandbox Code Playgroud)
(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
Run Code Online (Sandbox Code Playgroud)
例如,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 停止来验证它是否正常工作!请务必阅读链接的答案以了解发生了什么。