You are not logged in.

#1 2016-02-29 13:19:37

OlafLostViking
Member
From: Lost
Registered: 2013-01-30
Posts: 59

start firewall _after_ network configuration

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

#2 2016-02-29 16:49:01

branch
Member
Registered: 2014-03-16
Posts: 209

Re: start firewall _after_ network configuration

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

#3 2016-02-29 17:31:04

OlafLostViking
Member
From: Lost
Registered: 2013-01-30
Posts: 59

Re: start firewall _after_ network configuration

TL;DR at the bottom

Thank you very much for answering.

branch wrote:

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).


branch wrote:

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

#4 2016-02-29 19:54:58

branch
Member
Registered: 2014-03-16
Posts: 209

Re: start firewall _after_ network configuration

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

#5 2016-02-29 20:07:19

branch
Member
Registered: 2014-03-16
Posts: 209

Re: start firewall _after_ network configuration

OlafLostViking wrote:

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

#6 2016-03-01 07:59:09

OlafLostViking
Member
From: Lost
Registered: 2013-01-30
Posts: 59

Re: start firewall _after_ network configuration

Okay, thank you very much for your time smile

Offline

#7 2024-11-06 20:01:31

merilius
Member
Registered: 2012-06-15
Posts: 49

Re: start firewall _after_ network configuration

OlafLostViking wrote:

Okay, thank you very much for your time smile

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

Board footer

Powered by FluxBB