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:
192.168.0.0/16
10.0.0.0/8
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
- Find two computers not connected to any networks.
- Plug them into each others' ethernet ports.
- Configure the ethernet interfaces to addresses on the same subnet so that they can talk to each other.