rustybird / corridor

Tor traffic whitelisting gateway
ISC License
68 stars 6 forks source link

systemd WantedBy=multi-user.target correct - resulting in applications using networking before corridor firewall rules are load? #43

Closed adrelanos closed 4 years ago

adrelanos commented 4 years ago

systemd unit files using:

WantedBy=multi-user.target

Is this correct? Might this result in firewall rules not being load early enough before any other applications that might use networking?

Better...

WantedBy=sysinit.target

?

For comparison of other early boot systemd unit files. Perhaps we could compare with something else firewall related.

grep -r WantedBy /lib/systemd/system | grep sysinit
rustybird commented 4 years ago
WantedBy=multi-user.target

Might this result in firewall rules not being load early enough before any other applications that might use networking?

This only selects the bootup mode (normal startup, in contrast to some system maintenance mode?) in which corridor should be started at all - but not when it should be started (which is taken care of by Before=network-pre.target in corridor-init-forwarding.service).

adrelanos commented 4 years ago

I am not sure. Readying https://unix.stackexchange.com/questions/506347/why-do-most-systemd-examples-contain-wantedby-multi-user-target says. Trying to make head or tail of it. Quote:

systemd works on dependencies, and at boot time, if nothing Requires or Wants your service, it won't be started even if the service is enabled.

It may say Before=network-pre.target but since nothing Requires or Wants corridor-init-forwarding.service it might not be started.

There could be networking activity by some service after network-pre.target / network.target but before multi-user.target. And since nothing Requires or Wants corridor-init-forwarding.service during these "runlevels" it might not be started early enough.

I vaguely remember (during Qubes-Whonix development) that I had a service using WantedBy=multi-user.target as well as Before=sysinit.target. That didn't work. Couldn't run Before=sysinit.target since only when "runlevel" multi-user.target was reached.

My guess is Before= matters only in case a systemd unit gets actually activated through being pulled through the right target (WantedBy). In other words, WantedBy trumps Before=. Or in other words WantedBy is processed before Before=.

There is also a separate rescue.target.

rustybird commented 4 years ago

systemd doesn't load the dependency tree in stages though, but all at once (or rather, twice: first the units available in the initrd, then those in the root filesystem). It's able to pull in a unit that's only WantedBy=multi-user.target even though a more fundamental target hasn't been reached yet - because multi-user.target is nevertheless already in the process of being started! Probably best not to model this in terms of runlevels: "only one runlevel can be 'active' at a given time, while systemd can activate multiple targets concurrently, so the mapping to runlevels is confusing and only approximate." —runlevel(8)

For example, here's a stripped down excerpt from the systemd journal with corridor.target enabled:

Oct 12 13:24:50 localhost systemd[1]: systemd 243.51-1-arch running in system mode.
Oct 12 13:25:10 localhost systemd[1]: Reached target System Initialization.
Oct 12 13:25:10 localhost systemd[1]: Reached target Basic System.
Oct 12 13:25:10 localhost systemd[1]: Started corridor's relay list.
Oct 12 13:25:10 localhost systemd[1]: Starting corridor's logging...
Oct 12 13:25:11 localhost systemd[1]: Starting corridor's forwarding...
Oct 12 13:25:11 localhost systemd[1]: Starting corridor's source NAT...
Oct 12 13:25:12 localhost systemd[1]: Started corridor's source NAT.
Oct 12 13:25:13 localhost systemd[1]: Started corridor's forwarding.
Oct 12 13:25:59 localhost systemd[1]: Started corridor's logging.
Oct 12 13:25:59 localhost systemd[1]: Reached target corridor, a Tor traffic whitelisting gateway.
Oct 12 13:26:00 localhost systemd[1]: Reached target Network (Pre).
Oct 12 13:26:00 localhost systemd[1]: Starting Network Service...
Oct 12 13:26:00 localhost systemd[1]: Started Network Service.
Oct 12 13:26:00 localhost systemd[1]: Reached target Network.
Oct 12 13:26:01 localhost systemd[1]: Starting Anonymizing Overlay Network...
Oct 12 13:26:02 localhost systemd[1]: Started Anonymizing Overlay Network.
Oct 12 13:26:06 localhost systemd[1]: Reached target Multi-User System.
Oct 12 13:26:06 localhost systemd[1]: Reached target Graphical Interface.

I vaguely remember (during Qubes-Whonix development) that I had a service using WantedBy=multi-user.target as well as Before=sysinit.target. That didn't work.

Works for me:

# cat >/etc/systemd/system/foobar.service <<END
[Unit]
Description=foobar
Before=sysinit.target
DefaultDependencies=no

[Service]
ExecStart=/bin/echo foobar
Type=oneshot

[Install]
WantedBy=multi-user.target
END

# systemctl enable foobar.service
Created symlink /etc/systemd/system/multi-user.target.wants/foobar.service -> /etc/systemd/system/foobar.service.

# reboot

# journalctl -q -b -u sysinit.target -u foobar.service
Oct 12 13:42:51 localhost echo[280]: foobar
Oct 12 13:43:02 localhost systemd[1]: Reached target System Initialization.
rustybird commented 4 years ago

I think this can be closed, but please reopen if I got it wrong.