在单个Linux机器上模拟网络跃点

时间:2015-12-16 19:25:48

标签: linux networking routing iptables

我正在尝试模拟许多网络跃点,类似于Star Wars Traceroute。作者提供了一个脚本here,但是它是使用vrf而不是Linux而为Cisco路由器设计的。

这是我目前的尝试;

echo 1 > /proc/sys/net/ipv4/ip_forward

ifconfig br0 172.16.100.1 netmask 255.255.255.0
ifconfig br0:1 172.16.101.1 netmask 255.255.255.0
ifconfig br0:2 172.16.102.1 netmask 255.255.255.0
ifconfig br0:2 172.16.103.1 netmask 255.255.255.0

ip rule add iif br0 table 100
ip rule add iif br0:1 table 101
ip rule add iif br0:2 table 102

ip route add default table 100 dev 172.16.101.1
ip route add default table 101 dev 172.16.102.1
ip route add default table 102 dev 172.16.103.1

ping -I br0 172.16.103.2

我尝试使用Source Based Routing完成相同的操作,显然会重现vrf的效果,请参阅here,但附加tcpdump -i br0根本没有显示任何流量,然后在lo0上拾取数据包。

替代解决方案似乎包括使用iptables来破坏源IP和其他欺骗行为,感觉很脏,所以我不确定在哪里集中精力。

任何提示/指示都将不胜感激

2 个答案:

答案 0 :(得分:2)

我能够使用Linux命名空间,它目前是Linux等效的vrf。这只是一个手写的POC,您可能希望将其包装在脚本中并在程序上生成。

我花了8个多小时才弄明白,希望将来能帮助别人。

最终结果

$ ping 172.16.101.2
PING 172.16.101.2 (172.16.101.2) 56(84) bytes of data.
64 bytes from 172.16.101.2: icmp_seq=1 ttl=63 time=0.064 ms
64 bytes from 172.16.101.2: icmp_seq=2 ttl=63 time=0.043 ms

$ traceroute 172.16.101.2
traceroute to 172.16.101.2 (172.16.101.2), 30 hops max, 60 byte packets
 1  172.16.100.2 (172.16.100.2)  0.055 ms  0.006 ms  0.004 ms
 2  172.16.101.2 (172.16.101.2)  0.059 ms  0.009 ms  0.009 ms

解决方案

# add the namespaces
ip netns add hop1
ip netns add hop2

ip netns exec hop1   ip link set lo up
ip netns exec hop2   ip link set lo up

ip netns exec hop1   sysctl net.ipv4.ip_forward net.ipv4.ip_forward=1
ip netns exec hop2   sysctl net.ipv4.ip_forward net.ipv4.ip_forward=1

# create host link to first hop
ip link add hop1 type veth peer name veth1

ip addr change 172.16.100.1/24 dev hop1
ip link set hop1 up

ip link set veth1 netns hop1
ip netns exec hop1   ip link set veth1 name eth0
ip netns exec hop1   ip link set eth0 up
ip netns exec hop1   ip addr change 172.16.100.2/24 dev eth0

# create hop2 (link to hop1)
ip link add veth0 type veth peer name veth1

ip link set veth0 netns hop1
ip netns exec hop1   ip link set veth0 name eth1
ip netns exec hop1   ip link set eth1 up
ip netns exec hop1   ip addr change 172.16.101.1/24 dev eth1

ip link set veth1 netns hop2
ip netns exec hop2   ip link set veth1 name eth0
ip netns exec hop2   ip link set eth0 up
ip netns exec hop2   ip addr change 172.16.101.2/24 dev eth0

# set namespace routing
ip netns exec hop1   route add default gw 172.16.101.2
ip netns exec hop2   route add default gw 172.16.101.1

# set host routing
route add -net 172.16.101.0/24 gw 172.16.100.2

答案 1 :(得分:2)

对于那些仍在尝试使用Linux制作自己的《星球大战追踪路线》的人,我把这个想法写成脚本。

#!/bin/bash
#
# traceroute fun with linux namespaces
#  each namespace is basically a router we connect
#  to each other using fancy /32 networking
#
# scott nicholas <scott@nicholas.one> 2018-10-27
#

# how many levels deep are we going?
depth=16
prefix=192.168.99.

# can change function easily or just pre-populate ip array
calcip() { printf '%s%d' "$prefix" $((63 + i)); }

# instead of special casing things, if we bind init's netns into a name
# all of the code can use "-n ns"
touch /var/run/netns/default
mount --bind /proc/1/ns/net /var/run/netns/default

ns[0]=default if[0]=root ip[0]=${prefix}1

for ((i = 1; i <= depth; i++)); do
  ns[i]=hop$i if[i]=hop$i ip[i]=$(calcip $i)

  ip netns add "${ns[i]}"
  # interfaces are named by whom is on the other side
  # so it's kinda flip-flopped looking.
  ip -n "${ns[i-1]}" link add "${if[i]}" type veth peer name "${if[i-1]}" \
    netns "${ns[i]}"

  ip -n "${ns[i]}" a a "${ip[i]}"/32 dev "${if[i-1]}"

  # interfaces must be up before adding routes
  ip -n "${ns[i-1]}" link set "${if[i]}"   up
  ip -n "${ns[i  ]}" link set lo           up
  ip -n "${ns[i  ]}" link set "${if[i-1]}" up

  ip -n "${ns[i-1]}" route add "${ip[i  ]}" dev "${if[i]}"
  ip -n "${ns[i  ]}" route add "${ip[i-1]}" dev "${if[i-1]}"
  ip -n "${ns[i  ]}" route add default      via "${ip[i-1]}"

  # tell everyone above my parent that i'm down here in this mess
  for ((j = i - 2; j >= 0; j--)); do
    ip -n "${ns[j]}" route add "${ip[i]}" via "${ip[j+1]}"
  done
done