Testing LAN broadcast App with Linux Namespaces
In our Computer Networks course we propose to implement an application which shares files within a LAN. Each application running in the LAN announce the files it shares through broadcast UDP messages. The files are then transmitted thorough standard TCP connections.
The broadcast announcements are received in a fixed and known UDP port and the TCP connections for downloads are also received in a fixed port.
So as to easily test the application I search for a way to run several applications locally. Of course, using several Virtual Machines or containers were valid options but do not scale good or are too complex to configure for such a simple test.
Therefore, I tried to use Linux network namespaces¹, a bridge and virtual interfaces². I find it more difficult than expected (although at the end is quite simple). The idea is to create a network namespace for each instance of the application we want to run. Then, each namespace will have one end of a virtual interface. The other end of the virtual interface will be connected to a bridge.
This are the steps I followed to tests three instances of the application.
Create Network Namespaces
Create the namespaces:
ip netns add namespace1
ip netns add namespace2
ip netns add namespace3
We can verify the namespace are created with:
ip netns list
We can execute any command within the namespace with ip netns exec
For example, we can check the interfaces available inside one of the created namespaces:
ip netns exec ip a
Create the virtual interfaces
The virtual interface pairs work as tunnels between the namespaces. So, the next step is to create the veth pairs and assign one end to the corresponding namespace:
ip link add veth1 type veth peer name br-veth1
ip link add veth2 type veth peer name br-veth2
ip link add veth3 type veth peer name br-veth3ip link set veth1 netns namespace1
ip link set veth2 netns namespace2
ip link set veth3 netns namespace3
We can now assign an IP address to each veth within the namespaces:
ip netns exec namespace1 \
ip addr add 192.168.1.101/24 dev veth1
ip netns exec namespace2 \
ip addr add 192.168.1.102/24 dev veth2
ip netns exec namespace3 \
ip addr add 192.168.1.103/24 dev veth3
Create a bridge to join the interfaces
The final step is to join the other ends of the virtual interfaces with a bridge to allow the switching of traffic between them.
Create and start the bridge:
ip link add name br1 type bridge
ip link set br1 up
Connect and start all the interfaces:
ip link set br-veth1 up
ip link set br-veth2 up
ip link set br-veth3 upip netns exec namespace1 ip link set veth1 up
ip netns exec namespace2 ip link set veth2 up
ip netns exec namespace3 ip link set veth3 upip link set br-veth1 master br1
ip link set br-veth2 master br1
ip link set br-veth3 master br1
We can check the bridge configuration with bridge link show br1
Allow forwarding in the bridge
After all the previous configurations, the setup still does not work on my machine. I was missing to allow the bridge to forward packets. The easiest way I found for this was to allow forwarding in the iptables:
iptables -P FORWARD ACCEPT
This off course can be solved with some specific rules for this case, but as I said before, I was looking for the most straightforward way.
Add IP address to the bridge
One more detail. If we want to connect to the namespaces from outside (the host machine) it is necessary to add an IP address to the bridge:
ip addr add 192.168.1.100/24 brd + dev br1
Execute the applications
Finally, we execute the application within the namespaces (python programs in my example):
ip netns exec namespace1 python app.py
ip netns exec namespace2 python app.py
ip netns exec namespace3 python app.py
The references I use
[1]Introducing Linux Network Namespaces https://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/
[2] Using network namespaces and a virtual switch to isolate servers https://ops.tips/blog/using-network-namespaces-and-bridge-to-isolate-servers/
[3] Introduction to Linux interfaces for virtual networking https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking/#macvlan