How to setup networking on Debian 9 Stretch with systemd
Debian 9 uses systemd by default to manage its network interfaces.
We are going to configure the public network interface and a private network interface. We also are going to add some additional ip addresses in alias mode to the public interface. Alias mode allows us to use multiple ip addresses for a single network interface.
Private network configuration
First, lets find the MAC address for each network interface.
~# ip address 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 26:c1:29:65:b1:c0 brd ff:ff:ff:ff:ff:ff 3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 62:76:42:35:5d:e9 brd ff:ff:ff:ff:ff:ff 4: ifb0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether 5e:6c:0c:62:0d:e2 brd ff:ff:ff:ff:ff:ff 5: ifb1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether 5a:41:08:e6:1a:ba brd ff:ff:ff:ff:ff:ff 6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether a4:bf:01:25:75:36 brd ff:ff:ff:ff:ff:ff inet 54.37.87.106/24 brd 54.37.87.255 scope global eth0 valid_lft forever preferred_lft forever inet6 2001:41d0:303:4f6a::/64 scope global valid_lft forever preferred_lft forever inet6 fe80::a6bf:1ff:fe25:7536/64 scope link valid_lft forever preferred_lft forever 7: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether a4:bf:01:25:75:37 brd ff:ff:ff:ff:ff:ff 8: teql0: <NOARP> mtu 1500 qdisc noop state DOWN group default qlen 100 link/void 9: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/ipip 0.0.0.0 brd 0.0.0.0 10: gre0@NONE: <NOARP> mtu 1476 qdisc noop state DOWN group default qlen 1 link/gre 0.0.0.0 brd 0.0.0.0 11: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 12: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/sit 0.0.0.0 brd 0.0.0.0 13: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1 link/tunnel6 :: brd ::
Here we can identify the two main network interfaces:
- the public network interface eth0 with MAC address
a4:bf:01:25:75:36
is assigned the ip address 54.37.87.106 and is currently up - the additional network interface eno2 with MAC address
a4:bf:01:25:75:37
is currently down with no ip address assigned yet. This interface will be used as a private network interface
We can take a look at the primary network interface configuration in /etc/systemd/network
folder. This folder contains 2 configuration files to setup the public interface. This configuration is already in place when you order a dedicated server provided by OVH.
~# ls /etc/systemd/network 50-default.network 50-public-interface.link
~# cat /etc/systemd/network/50-default.network # This file sets the IP configuration of the primary (public) network device. # You can also see this as "OSI Layer 3" config. # It was created by the OVH installer, please be careful with modifications. # Documentation: man systemd.network or https://www.freedesktop.org/software/systemd/man/systemd.network.html [Match] MACAddress=a4:bf:01:25:75:36 [Network] Description=network interface on public network, with default route DHCP=no Address=54.37.87.106/24 Gateway=54.37.87.254 #IPv6AcceptRA=false NTP=ntp.ovh.net DNS=127.0.0.1 DNS=213.186.33.99 DNS=2001:41d0:3:163::1 Gateway=2001:41d0:0303:4fff:ff:ff:ff:ff [Address] Address=2001:41d0:0303:4f6a::/64 [Route] Destination=2001:41d0:0303:4fff:ff:ff:ff:ff Scope=link
~# cat /etc/systemd/network/50-public-interface.link # This file configures the relation between network device and device name. # You can also see this as "OSI Layer 2" config. # It was created by the OVH installer, please be careful with modifications. # Documentation: man systemd.link or https://www.freedesktop.org/software/systemd/man/systemd.link.html [Match] MACAddress=a4:bf:01:25:75:36 [Link] Description=network interface on public network, with default route MACAddressPolicy=persistent NamePolicy=kernel database onboard slot path mac #Name=eth0 # name under which this interface is known under OVH rescue system #Name=eno1 # name under which this interface is probably known by systemd
We will take inspiration from these files to configure the private network interface by creating 2 new files /etc/systemd/network/50-private.network
and /etc/systemd/network/50-private-interface.link
:
~# vim /etc/systemd/network/50-private.network [Match] # The MAC address we noted earlier for the private interface MACAddress=a4:bf:01:25:75:37 [Network] Description=network interface on private network DHCP=no # The ip address we want to assign to this machine on the private network Address=192.168.0.20/16
~# vim /etc/systemd/network/50-private-interface.link [Match] # The MAC address we noted earlier for the private interface MACAddress=a4:bf:01:25:75:37 [Link] Description=network interface on private network MACAddressPolicy=persistent # The interface name will be defined automatically by the system NamePolicy=kernel database onboard slot path mac
Finally, we just have to tell systemd to load the new configuration:
~# systemctl restart systemd-networkd
We can now verify that everything is ok:
~# ip address 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 26:c1:29:65:b1:c0 brd ff:ff:ff:ff:ff:ff 3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 62:76:42:35:5d:e9 brd ff:ff:ff:ff:ff:ff 4: ifb0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether 5e:6c:0c:62:0d:e2 brd ff:ff:ff:ff:ff:ff 5: ifb1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether 5a:41:08:e6:1a:ba brd ff:ff:ff:ff:ff:ff 6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether a4:bf:01:25:75:36 brd ff:ff:ff:ff:ff:ff inet 54.37.87.106/24 brd 54.37.87.255 scope global eth0 valid_lft forever preferred_lft forever inet6 2001:41d0:303:4f6a::/64 scope global valid_lft forever preferred_lft forever inet6 fe80::a6bf:1ff:fe25:7536/64 scope link valid_lft forever preferred_lft forever 7: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether a4:bf:01:25:75:37 brd ff:ff:ff:ff:ff:ff inet 192.168.0.20/16 brd 192.168.255.255 scope global eno2 valid_lft forever preferred_lft forever inet6 fe80::a6bf:1ff:fe25:7537/64 scope link valid_lft forever preferred_lft forever 8: teql0: <NOARP> mtu 1500 qdisc noop state DOWN group default qlen 100 link/void 9: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/ipip 0.0.0.0 brd 0.0.0.0 10: gre0@NONE: <NOARP> mtu 1476 qdisc noop state DOWN group default qlen 1 link/gre 0.0.0.0 brd 0.0.0.0 11: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 12: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/sit 0.0.0.0 brd 0.0.0.0 13: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1 link/tunnel6 :: brd ::
The interface eno2 is up with the ip address 192.168.0.20 assigned to it.
We can now ping another server that is a member of the private network at the address 192.168.0.21:
~# ping 192.168.0.21 PING 192.168.0.21 (192.168.0.21) 56(84) bytes of data. 64 bytes from 192.168.0.21: icmp_seq=1 ttl=64 time=0.435 ms 64 bytes from 192.168.0.21: icmp_seq=2 ttl=64 time=0.235 ms 64 bytes from 192.168.0.21: icmp_seq=3 ttl=64 time=0.236 ms 64 bytes from 192.168.0.21: icmp_seq=4 ttl=64 time=0.233 ms 64 bytes from 192.168.0.21: icmp_seq=5 ttl=64 time=0.236 ms 64 bytes from 192.168.0.21: icmp_seq=6 ttl=64 time=0.237 ms 64 bytes from 192.168.0.21: icmp_seq=7 ttl=64 time=0.203 ms ^C --- 192.168.0.21 ping statistics --- 7 packets transmitted, 7 received, 0% packet loss, time 6126ms rtt min/avg/max/mdev = 0.203/0.259/0.435/0.073 ms
Additional ip address on the public interface
To add an aliased ip address to the public interface, we have to edit the public interface configuration file and add one line for the additional ip address:
~# vim /etc/systemd/network/50-default.network # This file sets the IP configuration of the primary (public) network device. # You can also see this as "OSI Layer 3" config. # It was created by the OVH installer, please be careful with modifications. # Documentation: man systemd.network or https://www.freedesktop.org/software/systemd/man/systemd.network.html [Match] MACAddress=a4:bf:01:25:75:36 [Network] Description=network interface on public network, with default route DHCP=no Address=54.37.87.106/24 # Here we add the additional ip address Address=178.33.18.200 Gateway=54.37.87.254 #IPv6AcceptRA=false NTP=ntp.ovh.net DNS=127.0.0.1 DNS=213.186.33.99 DNS=2001:41d0:3:163::1 Gateway=2001:41d0:0303:4fff:ff:ff:ff:ff [Address] Address=2001:41d0:0303:4f6a::/64 [Route] Destination=2001:41d0:0303:4fff:ff:ff:ff:ff Scope=link
We reload the network configuration:
~# systemctl restart systemd-networkd
We check whether or not the configuration has been applied:
~# ip address 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 02:01:de:2a:c5:58 brd ff:ff:ff:ff:ff:ff 3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether ce:30:48:31:20:46 brd ff:ff:ff:ff:ff:ff 4: ifb0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether 2e:09:09:4b:90:0a brd ff:ff:ff:ff:ff:ff 5: ifb1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 32 link/ether ee:bd:5a:f9:ea:1e brd ff:ff:ff:ff:ff:ff 6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether a4:bf:01:25:75:36 brd ff:ff:ff:ff:ff:ff inet 54.37.87.106/24 brd 54.37.87.255 scope global eth0 valid_lft forever preferred_lft forever inet 178.33.18.200/16 brd 178.33.255.255 scope global eth0 valid_lft forever preferred_lft forever inet6 2001:41d0:303:4f6a::/64 scope global valid_lft forever preferred_lft forever inet6 fe80::a6bf:1ff:fe25:7536/64 scope link valid_lft forever preferred_lft forever 7: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether a4:bf:01:25:75:37 brd ff:ff:ff:ff:ff:ff inet 192.168.0.20/16 brd 192.168.255.255 scope global eno2 valid_lft forever preferred_lft forever inet6 fe80::a6bf:1ff:fe25:7537/64 scope link valid_lft forever preferred_lft forever 8: teql0: <NOARP> mtu 1500 qdisc noop state DOWN group default qlen 100 link/void 9: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/ipip 0.0.0.0 brd 0.0.0.0 10: gre0@NONE: <NOARP> mtu 1476 qdisc noop state DOWN group default qlen 1 link/gre 0.0.0.0 brd 0.0.0.0 11: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 12: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1 link/sit 0.0.0.0 brd 0.0.0.0 13: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1 link/tunnel6 :: brd ::
We verify that we can now use this ip address:
~# curl --head --interface 178.33.18.200 https://example.com HTTP/2 200 accept-ranges: bytes cache-control: max-age=604800 content-type: text/html date: Mon, 30 Apr 2018 07:37:45 GMT etag: "1541025663+ident" expires: Mon, 07 May 2018 07:37:45 GMT last-modified: Fri, 09 Aug 2013 23:54:35 GMT server: ECS (dca/24C1) x-cache: HIT content-length: 1270