4

On a Debian Stretch system with multiple interfaces, I need to define the default route via a specific interface ens3. This interface receives its ip address 10.33.34.2 through dhcp.

I adjusted the following guide to my needs:

5.3. The modern network configuration without GUI

Thus, I created a file /etc/systemd/network/route.network with the following content

[Match]
Name=ens3

[Network]
Gateway=10.33.34.1

However, the default route is not set correctly at startup.

I enabled debugging of systemd-networkd according to How to debug systemd-networkd?

After restarting systemd-networkd, I see the following in the logs:

Aug 21 13:43:13 vpn systemd-networkd[15671]: ens3: Setting routes
Aug 21 13:43:13 vpn systemd-networkd[15671]: ens3: Could not set route: Network is unreachable
Aug 21 13:43:13 vpn systemd-networkd[15671]: ens3: Routes set
Aug 21 13:43:13 vpn dhclient[15709]: Listening on LPF/ens3/52:54:00:3f:f1:d0
Aug 21 13:43:13 vpn dhclient[15709]: Sending on LPF/ens3/52:54:00:3f:f1:d0
Aug 21 13:43:13 vpn dhclient[15709]: Sending on Socket/fallback
Aug 21 13:43:13 vpn dhclient[15709]: DHCPDISCOVER on ens3 to 255.255.255.255 port 67 interval 8
Aug 21 13:43:13 vpn dhclient[15709]: DHCPREQUEST of 10.33.34.2 on ens3 to 255.255.255.255 port 67
Aug 21 13:43:13 vpn dhclient[15709]: DHCPOFFER of 10.33.34.2 from 10.33.34.1
Aug 21 13:43:13 vpn dhclient[15709]: DHCPACK of 10.33.34.2 from 10.33.34.1
Aug 21 13:43:13 vpn systemd-networkd[15671]: ens3: Adding address: 10.33.34.2/24 (valid forever)

It seems that networkd tries to set the route before the IP-address is assigned via dhcp.

How do I get the default route set to a specific interface with systemd?

== Edit ==

I was wrong in assuming that systemd-networkd brings up the interfaces. If I restart the system, I see

$ sudo service systemd-networkd status
● systemd-networkd.service - Network Service
   Loaded: loaded (/lib/systemd/system/systemd-networkd.service; disabled; vendor pres
  Drop-In: /etc/systemd/system/systemd-networkd.service.d
           └─10-debug.conf
   Active: inactive (dead)
     Docs: man:systemd-networkd.service(8)

Thus, configuration in /etc/systemd/network/route.network takes no effect when booting. Currently, I'm wondering what service is responsible to bring up all the network devices.

== Edit 2 ==

This article by Steven Iveson provides a good insight on how network devices are started by systemd-udevd and how to modify interface configuration.

By testing and further reading, I would also restate my problem: The multiple interfaces are brought up in random order. Each obtains a correct dhcp configuration. The first interface to be brought up will set the default route and therefore, 10.33.34.1 will not always be used as default route

4
  • 1
    Why are you trying to do this specifically via systemd? Why not configure dhclient to stop adding the routes you don't want? Aug 21, 2018 at 12:17
  • How do I confirm that the route is configured by dhclient?
    – DoRe
    Aug 21, 2018 at 13:45
  • Are you getting your 10.33.34.2 address from DHCP, or is it statically assigned? Please do not respond in comments; edit your question to make it clearer and more complete. Aug 21, 2018 at 16:20
  • Note that just stopping dhclient from adding the default route won't help as currently you are trying to add the route to early, before it is valid, so you'll end up without any default route. The correct point is after the DHCP offer is received, unless you want a static setup instead (after all, the route is static), but I can't help you with finding out where to put that into systemd, sorry. Another option would be to configure your DHCP server to distribute the correct route in the first place.
    – dirkt
    Aug 24, 2018 at 10:29

2 Answers 2

3

If all interfaces receive valid DHCP offers with a default route, then there will be no way around configuring dhclient to ignore those -- that isn't something you can do with systemd, udev, or anything else connected the init system.

One way to do that is described here: You create (of course, you can also use an editor) a shell script fragment in one of the "hook" directories of dhclient,

cat << EOF > /etc/dhcp/dhclient-enter-hooks.d/restrict-default-route
## Only the DHCP server talking to ens3 is allowed to give us a default
## route.  Other interfaces only get local-segment configuration.
case ${interface} in
  ens3)
    ;;
  *)
    unset new_routers
    ;;
esac
EOF

which will only accept the routers option with the default route for ens3. No problems with timing, no problems with figuring out which systemd files to use, and the route will only be valid when ens3 is up and has received the DHCP offer.

2
  • Sorry, I saw your post too late
    – DoRe
    Aug 24, 2018 at 13:03
  • 1
    @DoRe, still it's good you were able to find the solution and it's very good you've posted it! One nitpick I do not see articulated in the answers: you should probably make the names of your interfaces stable for such scripting to really have predictable results. See, for instance, here.
    – kostix
    Aug 26, 2018 at 14:48
0

For Debian Stretch, the interfaces are named by udev and basic configuration occurs in /etc/network/interfaces. As stated in edit 2, the multiple interfaces are brought up in random order. Each obtains a correct dhcp configuration. The first interface to be brought up will set the default route. We need to only accept the default route for the desired interface. This can be achieved by a hook to the dhcpclient

Add a new hook script /etc/dhcp/dhclient-enter-hooks.d/nodefaultroute:

#!/bin/sh
## Prevent DHCP server on eth0 from forcing a default route on us

case ${interface} in
  ens8|ens9)
     printf "executing ip route delete default via $new_routers\n" 
     ip route delete default via $new_routers
  ;;
     *)
  ;;
esac

Where ens8|ens9 can be extended to list all the interfaces for which the default route can not be accepted.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .