Linux Network Namespace

From W9CR
Jump to navigation Jump to search

This is an absolutely stupid use of a /24.

On linux/osx/bsd use traceroute -m255 becky.keekles.org

For Windoze users: tracert -h 255 becky.keekles.org

traceroute to becky.keekles.org (192.77.144.221), 255 hops max, 60 byte packets
 1  router.129.keekles.org (199.47.174.129)  1.021 ms  1.042 ms  1.003 ms
 2  flowman.tampa.coop (23.149.104.3)  0.550 ms  0.524 ms  0.585 ms
 3  Oh.my.god.Becky.look.at.her.butt (192.77.144.1)  0.586 ms  0.592 ms  0.567 ms
 4  It.is.so.big (192.77.144.3)  0.582 ms  0.518 ms  0.465 ms
 5  She.looks.like.one.of.those.rap.guys.girlfriends (192.77.144.5)  0.496 ms  0.412 ms  0.555 ms
 6  Who.understands.those.rap.guys (192.77.144.7)  0.605 ms  0.512 ms  0.440 ms
<snip>
111  Little.in.the.middle.but.she.got.much.back (192.77.144.217)  4.012 ms  3.935 ms  3.904 ms
112  . (192.77.144.219)  3.853 ms  1.753 ms  1.722 ms
113  routed.by.bryanfields.net (192.77.144.221)  1.698 ms  1.675 ms  3.585 ms

I've seen this done before but it was routing back and forth between two cisco routers. This is hosted on a single Linux host and self contained.

My first testing was using VRF's on Linux, but they are not true VRF's, ICMP will fail inside on them, and in general not an easy way to do it.

Second try was using GRE interfaces into VRF's across the loopback interface, but that didn't work for some reason. I did a bit of testing and saw them making it across the interface, but just dropping for some reason.

I then stumbled on the user mode linux and found Linux namespaces. This appeared to be the way to do it and I configured 10 by hand just to get a feel for it. I knew I'd have to write a script to generate the config as it was way to lengthy to do by hand.

Config

The basic concept was to have a chain of tunnels or name spaces with a left and right interface. Each interface would be connected to the next with a /31, so we can scale this to 127 name spaces for a /24. This makes efficient use of a limited resource for a stupid application.


Code Generator

This is a small python program to generate the config.

#!/usr/local/bin/python3
#  subnetmaker
#  Build /31 network interfaces and name space config
#  Copyright Bryan Fields, 2023
#  bryan@bryanfields.net
#  Licensed under the AGPL 3
#
import sys
import ipaddress
#set the base namespace
base_namespace = 'vnet'
basesubnet = ipaddress.ip_network('192.77.144.0/24')
net_array = list(basesubnet.subnets(new_prefix=31))

n=0
#setup the 000 interface
#ip link add veth001-L type veth peer name veth000-R
#ip addr add 192.77.144.0/31 dev veth000-L
#ip link set veth000-R up
#ip route add 192.77.144.0/24 via 192.77.144.1
network=str(net_array[0])
hosts=list(net_array[0].hosts())
nextHosts=list(net_array[0].hosts())
prefixlen=str(net_array[0].prefixlen)
host1=str(hosts[0])+"/"+prefixlen
host2=str(hosts[1])+"/"+prefixlen
thisNetdevL="veth""{:03d}".format(n)+ "-L"
thisNetdevR="veth""{:03d}".format(n)+ "-R"
nextNetdevL="veth""{:03d}".format(n+1)+ "-L"
nextNetdevR="veth""{:03d}".format(n+1)+ "-R"
nextHostL =str(hosts[1])

print ("ip link add "+nextNetdevL+" type veth peer name "+thisNetdevR)
print ("ip addr add "+ host1 +" dev " + thisNetdevR)
print ("ip link set "+thisNetdevR+" up")
print ("ip route add "+str(basesubnet)+" via "+nextHostL)
print ("#end of hostnet")

n=1
for n in range(1,128):
    thisNameSpace="vnet""{:03d}".format(n)
    network=str(net_array[n])
    hostsL = list(net_array[n-1].hosts())
    hostsR = list(net_array[n].hosts())
    prefixlen=str(net_array[n].prefixlen)
    hostL=str(hostsL[1])+"/"+prefixlen
    hostR=str(hostsR[0])+"/"+prefixlen
    thisNetdevL="veth""{:03d}".format(n)+ "-L"
    thisNetdevR="veth""{:03d}".format(n)+ "-R"
    nextNetdevL="veth""{:03d}".format(n+1)+ "-L"
    nextNetdevR="veth""{:03d}".format(n+1)+ "-R"
    nextHostR =str(hostsR[1])
    nextHostL =str(hostsL[0])
    print ("ip netns add "+thisNameSpace)
    print ("ip link add "+nextNetdevL+" type veth peer name "+thisNetdevR)
    print ("ip link set "+thisNetdevL+" netns "+thisNameSpace)
    print ("ip link set "+thisNetdevR+" netns "+thisNameSpace)
    print ("ip -n "+thisNameSpace+" link set "+thisNetdevL+" up")
    print ("ip -n "+thisNameSpace+" link set "+thisNetdevR+" up")
    print ("ip -n "+thisNameSpace+" link set lo up")
    print ("ip -n "+thisNameSpace+" addr add "+hostL+" dev "+thisNetdevL)
    print ("ip -n "+thisNameSpace+" addr add "+hostR+" dev "+thisNetdevR)
    print ("#Linux Sys settings")
    print ("ip netns exec "+thisNameSpace+" sysctl -w net.ipv4.ip_forward=1")
    print ("ip netns exec "+thisNameSpace+" sysctl -w net.ipv4.ip_default_ttl=255")
    print ("#Default Route Left")
    print ("ip -n "+thisNameSpace+" route add 0/0 via "+nextHostL)
    print ("#.0 Route Left")
    print ("ip -n "+thisNameSpace+" route add "+str(net_array[0])+" via "+nextHostL)
    print ("#Subnet /24 Right")
    print ("ip -n "+thisNameSpace+" route add "+str(basesubnet)+" via "+nextHostR)
exit