We previously touched on some addresses and ports. For many circumstances you don't need to know any more than this, as your operating system will have sufficient tooling that everything just works out of the box.

However this stops being true when your computer is connected to multiple networks, as it then needs to manage multiple interfaces.

Inspecting Interfaces

You can run the ip link command to see which interfaces your computer has.

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether b8:88:e3:e1:3a:00 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 60:36:dd:13:98:22 brd ff:ff:ff:ff:ff:ff
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether e6:a6:ad:95:9f:27 brd ff:ff:ff:ff:ff:ff

The first column is the numeric ID of the interface, the second its name, and the rest is various configuration.

lo is the local only virtual interface, this is always available so that networking is always possible, even on machines that do not have external network ports, as you may want to use networking for IPC.

Names starting en or eth are generated by Linux for physical ethernet links. There is usually one of these per ethernet port on your computer.

Names starting wl are wireless interfaces.

Bridge interfaces have many names, usually with br in it. These allow physical devices to be virtually connected, which is useful to share a connection on one link to machines connected on another, or virtual connections to a physical one, which is what my virbr0 interface does.

veth interfaces are a virtual link pair. They can take any name, but the ones systemd manages are named ve-*, vb-* and host*. This is useful for network testing, and network isolation, so some processes only have access through the virtual link, and the other end of the link can decide to conditionally forward it on to its destination or block it.

macvlan or ipvlan virtual interfaces share a physical interface. This is useful for containers so you can host another network connected machine and let it manage its own address while sharing your interfaces.

*.[0-9] - vlan, layered on top of any of the others such that packets are tagged to only be visible to interfaces with the same vlan number.

A more complete list can be seen by running ip link help.

Configuring Interfaces

Virtual interfaces can be removed with the ip link del $NAME command, or added with the ip link add $NAME type $TYPE command.

We can safely make a virtual ethernet link pair without confusing your operating system's network configuration too much.

$ sudo ip link add left type veth peer name right

This left and right pair will be used in further examples rather than using one of the interfaces managed by your operating system.

There's no point making these interfaces if we can't prove they work, so let's demonstrate.

First we need to get the ip addresses of those interfaces. All interfaces have an ipv6 link-local address we can use.

$ getip(){ ip -o addr | grep "$1" | tr -s ' ' '\n' | sed -ne '/inet6/{n;p}'; }
$ leftip="$(getip left)"
$ leftip="${leftip%/*}"
$ rightip="$(getip right)"
$ rightip="${rightip%/*}"

Netcat has a few implementations with differing behaviour. IPv6 support is not guaranteed, so we're going to use socat, which is not shipped as standard in many Linux distributions, but has a consistent interface.

We can then start a simple echo service on the left.

$ socat "TCP6-LISTEN:12345,bind=${leftip}%left" - &

The number after the colon specifies to listen on port 12345, the bind= option specifies to bind the socket to the link local address by passing that address, and only on the left interface with the %left suffix.

The - just says to feed the socket input from your terminal and write output from the socket to your terminal.

We can then connect to this service from the right.

$ socat - "TCP6:[${leftip}%right]:12345,sourceport=${rightip}%right"

This says to connect the input from your terminal, to a tcp socket, connecting to the address of the left end of the veth link, by connecting to the right end, coming from the left end with the sourceport option.

Now by entering text in one terminal, it will also appear on the other.

Permanent network interface configuration with networkd

If you find this left-right veth link useful, you can make its configuration permanent, by running the following command, to add systemd-networkd netdev configuration.

$ sudo tee /etc/systemd/network/veth-pair.netdev >/dev/null <<EOF
[NetDev]
Name=left
Kind=veth
[Peer]
Name=right
EOF

Further reading

I could not find many resources on this topic, hence why I felt it would be useful to write about it. I found these and would happily take suggestions to extend this list.