You are not logged in.
Systemd starts the nftables.service before the network-pre.target so that a firewall is already up before the network interfaces are configured. This makes sense but leads to problems when interfaces are created by networkd.
In my case I let networkd build a bridge that is included in my firewall rules, of course. But the nftables.service fails as this bridge interface, referenced in my nftables.conf, is not yet available.
Adding
After=network.target
# or
After=network-online.target
to the nftables.service configuration doesn't help. Also enabling systemd-networkd-wait-online.service didn't help.
Using
After=systemd-networkd.service
# or
After=network-pre.target
leads to a dependency cycle. But the nftables firewall is started up at the correct point in bootup. So the firewall can start. But this is obviously somehow defect. "Dependency cycle" and red colours in the journal don't seem trustworthy, either ;-)
So where am I misunderstanding something? How can I start up my firewall correctly?
Thanks!
Offline
You seem aware and unconcerned with the security implications of what you are doing, so i won't speak to that.
After does not imply Wants, so you need this too. Also, you need to remove the existing dependency so you don't make a loop.
Enable systemd-networkd-wait-online.service, then use something like:
.include /usr/lib/systemd/system/nftables.service
[Unit]
Wants=
Wants=network-online.target
After=
After=network-online.target
Offline
TL;DR at the bottom
Thank you very much for answering.
You seem aware and unconcerned with the security implications of what you are doing, so i won't speak to that.
Thank you for pointing that out! But you're right that I understand the implications in this case. This is more about to understand how the network and firewall scripts/services work together.
I solved this specific problem (exactly to not have this kind of unsafe situation) by changing the iif entries to iifname. Those don't seem to work with defines, however (the name cannot be assigned to a constant with define)... But, according to the documentation, this has performance implications which is why I wanted to postpone adding this rule after the interface came to life (and is not configured with a address - so network-online.target is a bad choice in this case, anyways).
After does not imply Wants, so you need this too. Also, you need to remove the existing dependency so you don't make a loop.
Enable systemd-networkd-wait-online.service, then use something like:
.include /usr/lib/systemd/system/nftables.service [Unit] Wants= Wants=network-online.target After= After=network-online.target
I tried that, but journalctl still says
Feb 29 18:17:53 HOST systemd[1]: Set hostname to <HOST>.
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found ordering cycle on systemd-networkd.service/verify-active
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found dependency on network-pre.target/start
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found dependency on nftables.service/start
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found dependency on network-online.target/start
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found dependency on network.target/start
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Found dependency on systemd-networkd.service/verify-active
Feb 29 18:17:53 HOST systemd[1]: systemd-networkd.service: Breaking ordering cycle by deleting job network-pre.target/start
Feb 29 18:17:53 HOST systemd[1]: network-pre.target: Job network-pre.target/start deleted to break ordering cycle starting with systemd-networkd.service/verify-active
Just for clarification: the network is up and the firewall is activated afterwards (which is a safety problem, as you already pointed out). But I don't understand where these dependencies are coming from.
TL;DR Is there a correct way to start the nftables based firewall after all interfaces are set up by systemd-networkd but before they are configured with addresses and routes?
Offline
Right, I messed that up. It is the Before=network-pre.target that we need to clear to break the cycle, not an After. So try:
.include /usr/lib/systemd/system/nftables.service
[Unit]
Wants=
Wants=network-online.target
Before=
After=network-online.target
Offline
TL;DR Is there a correct way to start the nftables based firewall after all interfaces are set up by systemd-networkd but before they are configured with addresses and routes?
AFAIK, no. The only notification that systemd-networkd gives about its progress is when it has completed everything it was told to do. If the performance of nftables with "iifname" instead of "iif" is unsatisfactory, I think your only option is to configure either the bridge or the addresses/routes with something other that systemd-networkd so that you can set the dependencies for each operation independently.
Offline
Okay, thank you very much for your time
Offline
Okay, thank you very much for your time
I ran into the same problem 8 years later, so I am necrobumping this thread.
I also see no reason why nftables would use iifname instead of iif.
iifname looks into packet metadata and compares network interface names as strings, whereas iif does directly refers to interface id, the way it should be done.
For a VLAN interface to exist systemd-networkd needs to set it up first.
There is no security issue if:
1) systemd-networkd.service sets up VLAN (bridge etc) interfaces first (no IP addresses or routing yet, just interfaces)
2) then nftables.service runs loads the firewall which uses iif (and oif directives)
3) systemd-networkd.service sets up IP addresses and possibly routing afterwards.
However, it is not implemented this way. Why not? Would it require splitting systemd-networkd into two services?
Anyway, the solution I found useful is to add these lines to all /etc/systemd/network/*.network files
[Network]
ConfigureWithoutCarrier=true
[Link]
RequiredForOnline=no
Configure your IP addresses manually (no DHCP)
Override nftables.service
systemctl edit nftables.service
to add these lines:
[Unit]
After=
After=systemd-networkd-wait-online.service
Wants=
Wants=systemd-networkd-wait-online.service
Before=
Enable the service:
systemctl enable systemd-networkd-wait-online.service
Offline