I'm trying to simulate many network hops, similar to Star Wars Traceroute. The author provided a script here, however it's designed for Cisco routers by using vrf
, rather than Linux.
Here is my current attempt;
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
I've tried to accomplish the same thing using Source Based Routing, which apparently reproduces the effects of vrf
, see here, but attaching tcpdump -i br0
shows no traffic at all, and the packets are instead being picked up on lo0
.
Alternative solutions seem to include mangling source IPs and other trickery using iptables
which feels quite dirty, so I'm not sure where to focus my efforts.
Any tips/pointers would be appreciated
I made this idea into a script for those still finding this question trying to make their own Star Wars Traceroute using 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