In the previous article on interfaces, we added a virtual ethernet pair with the following command.

$ sudo ip link add left type veth peer name right

We can inspect the addresses owned by these interfaces with the ip address command.

$ ip address show dev left
6: left: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 56:9e:e6:2d:34:e6 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::549e:e6ff:fe2d:34e6/64 scope link 
       valid_lft forever preferred_lft forever

This shows that we currently don't have an inet (IPv4) address, but we have the default inet6 (IPv6) link-local address.

We can add any address we want to this interface, but first we need to invent a subnet for the virtual ethernet device.

Subnets

The IPv4 address space is sub-divided by saying that every address that starts with a specified prefix belongs to that subnet.

So the subnet 127.0.0.0/8 says that every address starting with 127. is in that subnet. The /8 says how long the prefix is, so that you can have a 0 component in a prefix without it being ambiguous as to whether it's not part of the prefix, or whether the prefix has a 0 byte in it.

The number after the / is how many bits long the prefix is, starting from the left.

So the network 127.0.0.0/8 has 224 addresses in it, from 127.0.0.0 to 127.255.255.255.

It just happens that usually only 127.0.0.1 is allocated, and only on the loopback interface, but you can configure more addresses for your loopback interface than you will feasibly ever need.

You should only ever see the 127.0.0.0/8 subnet on your loopback interface, as it is reserved for this purpose, so that you can't confuse a global address for a local-only loopback address.

There are other such reserved ranges, such as the private subnet only ranges:

  1. 192.168.0.0/16
  2. 10.0.0.0/8
  3. 172.16.0.0/12

These ranges are reserved so that you can have private addresses for machines reachable only on your subnet.

These ranges can be subdivided as much as you want, to provide further subnetting.

For the rest of the examples here we are going to use the subnet 10.248.179.0/24. Please note that this address was selected randomly, please check if addresses in this subnet are allocated to your local network.

For a more detailed explanation of subnets please read this article on subnets.

Assigning addresses

When you assign an address to an interface, you assign a given address in a given subnet. So 10.248.179.1 is not sufficient information to configure the address. You also need the prefix length, so if we want to assign 10.248.179.1 to the left virtual interface, we can use this command:

$ sudo ip address add 10.248.179.1/24 dev left

Now we can see that our left interface has this address.

$ ip address show dev left
6: left: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 56:9e:e6:2d:34:e6 brd ff:ff:ff:ff:ff:ff
    inet 10.248.179.1/24 scope global left
       valid_lft forever preferred_lft forever
    inet6 fe80::549e:e6ff:fe2d:34e6/64 scope link 
       valid_lft forever preferred_lft forever

We can prove this address works with a pair of netcat commands.

$ nc -l 10.248.179.1 1234 >out.txt &
$ echo hello | nc 10.248.179.1 1234
$ cat out.txt 
hello

Because left is paired with right, if we configure an address for the right end, we can send messages through the virtual ethernet link.

$ sudo ip address add 10.248.179.2/24 dev right
$ nc -l 10.248.179.1 1234 >out.txt &
$ echo hello | nc -s 10.248.179.2 10.248.179.1 1234

To make these addresses persist across a reboot, you can use networkd .network files.

$ sudo install -m644 /dev/stdin /etc/systemd/network/left.network <<'EOF'
[Match]
Name=left
[Network]
Address=10.248.179.1/24
EOF
$ sudo install -m644 /dev/stdin /etc/systemd/network/right.network <<'EOF'
[Match]
Name=right
[Network]
Address=10.248.179.2/24
EOF

Routes

Because we configured this new address with an address prefix, we now have a route configured.

$ ip route
default via 192.168.1.254 dev wlan0  proto static 
10.248.179.0/24 dev right  proto kernel  scope link  src 10.248.179.2 
10.248.179.0/24 dev left  proto kernel  scope link  src 10.248.179.1 
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.94  metric 9 

The first and last lines were added earlier by NetworkManager, but the ip address add commands added the two rules in the middle.

These routing rules are consulted when you need to make an IPv4 connection. Routing rules are selected most-specific first.

For our earlier call to nc -s 10.248.179.2 10.248.179.1 1234 we said we want to connect to 10.248.179.1 from 10.248.179.2.

While there's a default rule for connecting everything through wlan0, there is a more specific rule for connections coming from 10.248.179.2, and connecting to an address in the 10.248.179.0/24 subnet, so the following rule matched:

10.248.179.0/24 dev right  proto kernel  scope link  src 10.248.179.2

Which means that the connections must go through the right interface.

Since we bound a service to port 1234 at address 10.248.179.1, which is assigned to the left interface, the connection succeeded, as there was a service waiting for connections.

We can make this matching rule more generic by running:

$ sudo ip route change 10.248.179.0/24 dev right

So now all connections to addresses in 10.248.179.0/24 will go through the right interface.

We can make this configuration persist across reboots by replacing the .network file for our interface with this one:

$ sudo install -m644 /dev/stdin /etc/systemd/network/right.network <<'EOF'
[Match]
Name=right
[Network]
Address=10.248.179.2/24
[Route]
Destination=10.248.179.0/24
EOF

as we could connect to 10.248.179.1 without going through right, because it is one of our own addresses.

However if this were a real interface, this would allow us to connect to other machines on the network, that had chosen addresses in the 10.248.179.0/24 subnet.

Homework

  1. Find two computers not connected to any networks.
  2. Plug them into each others' ethernet ports.
  3. Configure the ethernet interfaces to addresses on the same subnet so that they can talk to each other.