Bug 80169 - RFE: please introduce more special targets for facilities like entropy, or netfilter rules
Summary: RFE: please introduce more special targets for facilities like entropy, or ne...
Status: RESOLVED INVALID
Alias: None
Product: systemd
Classification: Unclassified
Component: general (show other bugs)
Version: unspecified
Hardware: All All
: medium enhancement
Assignee: systemd-bugs
QA Contact: systemd-bugs
URL: http://lists.alioth.debian.org/piperm...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-17 22:41 UTC by Christoph Anton Mitterer
Modified: 2014-06-23 21:45 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments

Description Christoph Anton Mitterer 2014-06-17 22:41:50 UTC
Hi.

Some weeks ago, I've started an (yet unfinished discussion) at the mailing list of Debian's systemd maintainers:
http://lists.alioth.debian.org/pipermail/pkg-systemd-maintainers/2014-May/002174.html


The original motivation was, how it can be assured that netfilter rules are loaded before any networking is done by the user and/or daemons.
Debian's iptables package doesn't have an rules loader itself (like e.g. RedHat has), but there are several other packages which can do this, e.g. netfilter-persistent, ferm, shorewall, etc..
Of course, these packages could just reverse-depend into some already existing special targest like basic.target, sysinit.target or network.target.

But none of that seems really well suited... after all... one of the core ideas of systemd is to start only necessary things and only when they're needed...
But why should some daemon need to depend on e.g. network.target (which implies all kinds of things)... if it just wants to make sure that netfilter rules are loaded before it is started... while e.g. any network interfaces will be dynamically detected and bound to when they're brought up.


The problem is IMHO more general then netfilter rules only:
A system has facilities which are very important (typically for security) but which daemons don't directly depend on (in the sense as e.g. some service xyz may depend on the PostgreSQL unix socket being there in order to start at all).

The most prominent example are surely the netfilter rules: depending on how services are used/configured it may be extremely important for security that netfilter rules are _successfully_ loaded before the services start up.
This may include access constraints based on IP address ranges or things like assuring (via netfilter) that some traffic is only accepted (outgoing and/or incomming) when it was IPsec'ed... or secured via some other VPN.

But netfilter is not the only security-facility.
Other things could be for example services that provide more/better entropy.



I think a framework for the most important of such facilities should be provided by upstream, so that a common practise is established how unit files for daemons depend on such facilities.

Several questions/issues arise here:
- which targets/units shall we provide, so that only the least necessary stuff is loaded (i.e. it's IMHO a bad idea to just put everything into networking.target)
- when we have an abstract target, that provides e.g. that netfilter rules are loaded, how do we allow multiple different actual services (e.g. ferm, shorewall, netfilter-persistent) to actually implement that abstract facility
- how can we make sure that such important things are Wanted= very early (I mean mostly everything in the system should have netfilter rules in place, not only daemons but also user sessions or other things of the early boot process)... while they are definitely Required= to for daemons to start at all?
- how can we allow admins to easily change that hard (Requires=) to a soft (Wants=) dependency, e.g. if an admin is fine with that a daemon starts even if loading netfilter rules has failed (which is very stupid and shouldn't be the default, but people will cry out if it's too difficult to them to go back to their "good" old behaviour).


In the aforementioned mailing list thread I discussed about just these things a bit with the Debian maintainers.
Those two mails, probably contain the main ideas and proposals:
http://lists.alioth.debian.org/pipermail/pkg-systemd-maintainers/2014-May/002174.html
http://lists.alioth.debian.org/pipermail/pkg-systemd-maintainers/2014-May/002184.html

Would be great if you guys could read into that and perhaps it can be discussed then whether/what can actually be done in systemd upstream.


It's not really much that needs to be done from a technical POV,..
- some special targets for facilities like "netfilter rules successfully loaded", "entropy services started", etc. should be defined
- such facilities should be WantedBy+Before= the early boot process (i.e. sysinit.target)
- a policy or BCP document should be written, where people (those who write unit files for serivces) are advised things like.. "if you're service does networking, then you should Requires=netfilter-rules-special-target-with-some-yet-to-be-found-better-name.target"... if you need good entropy you should Requires=entropy-services-loaded.target"
- end users / admins should find documentation how easy they can change the behaviour that their daemons would still start up, even if e.g. loading of netfilter rules fails (which I think can be fairly easily done _without_ the need to change all the Requires= in each of their daemons) (but see the aforementioned thread about this).


Also I think, people should be told that using network.target is bad style - well at least I would think it is.
You say yourself, that it's not well defined, so by depending on it you can basically pull in anything that is somehow networking related.

In a modern world, daemons discover e.g. network interfaces and local addresses dynamically and bind to them... not longer depending on all the NICs already brought up.
So services shouldn't need depend on networking.target unless they need to.
But even in the modern world, services should (for security reason) most definitely want to have netfilter rules _successfully_ loaded _beofre_ the daemon starts an listens... but just for that one shouldn't need to wait for everything else that might be implied by network.target (DNS, interfaces up, whatever).


Cheers,
Chris.
Comment 1 Lennart Poettering 2014-06-18 15:04:49 UTC
What targets are you precisely looking for?

There's already one to cover firewalls, it's network-pre.target, added in the last release.

For things like entropy, there's already systemd-random-seed-load.service you can order yourself after. What else is required?
Comment 2 Christoph Anton Mitterer 2014-06-18 20:28:02 UTC
Hi Lennart.

First, I didn't knew about network-pre.target yet... reading it's documentation:
                                        <para>This passive target unit
                                        may be pulled in by services
                                        that want to run before any
                                        network is set up, for example
                                        for the purpose of setting up a
                                        firewall. All network
                                        management software orders
                                        itself after this target, but
                                        does not pull it in.</para>
it seems to me, that it's not much better than network.target itself...

It's very vaguely defined what it is... actually nothing is defined, just the info, that it's before network is up.

So depending somehow on network-pre.target can in the end mean that you pull in anything or nothing... starting from:
- netfilter rules
- local recursing nameserver running
- fail2ban running
- etc. pp.

So I really think that design wise, the whole network*.targets are rather unfortunate... especially since they're not well defined.


As I laid out in the thread at the Debian list,... there should be really specific target which is just for "netfilter rules loaded".
Or call it technique-neutrally "packetfilter rules loaded".... and it should be really defined to be just that.


On special problem, which is IMHO not solved with something like network-pre.target is the following:
I think we should basically teach/push writes of unit files to do things right.
For netfilter rules I'd say this means the following:

- they're _tried_ to be leaded very early in the boot process
  => the whole system (from user sessions to anything else) should be protected already
  => if the author of some daemon's unit file forgets to explicitly Require=netfilter.target (or whatever we call it)... the daemon will still be safe.
  => therefore,... such netfilter.target should be WantedBy+Before=sysinit.target

- but we don't want the boot process to fail, just because the loading of iptables rules failed (they might have a typo)... I mean from a security POV I'd personally rather want it to fail, but I guess one cannot convince people of that... therefore, I'd have chosen and WantedBy= instead of RequiredBy= above.


- But for any of the typical networking daemons (postfix, httpd, or maybe GNOME's VNC server) I think we should teach/push people to the behaviour that these services don't even start up, if the rules loading failed.
Having a typo in the netfilter rules can happen easy... and it will put the whole system at risk, if services depend on it for their security.
So not staring these daemons in such case seems to be easily justifiable... after all... people will more or less immediately notice and simply correct their rules.

=> Therefore, unit files of such daemons/services should more or less _generally_ contain a Require+After=netfilter.target
I really think that this should be advertised by you guys,... in whatever example unit files or documentation you provide. Actually your G+ and blog posts seem to be a good place for such advertisement.

This is also the point where I think the network-pre.target idea fails... since this can imply more or less "anything before the network is brought up"... unit file authors will be very reluctant to add it.


Technically, the actual services that provide the netfilter rules loading, e.g. Debian's netfilter-persistent or packages like ferm/shorewall etc. should than set a RequiredBy=netfilter.target.

=> If none of such packages is installed... than depending (regardless of whether {Wanted|Required}[By]) will cause no harm...
=> If any of such packages is installed, than if _any_ of them fails,.. the daemon (e.g. postfix) won't be loaded => great
=> For netfilter loaders... these packages usually will conflict anyway each other.
=> If an admin really really want's his daemons to start, even if e.g. netfilter rules are not successfully loaded - fine... he can very easily do this and slectively change the RequiredBy=netfilter.target of packages like netfilter-persistent/ferm/shorewall.

Everybody should be able to be happy with that:
- more secure out of the box (because services are not loaded if rules loading failed)
- if it's BCP that netfilter.target is added as Requires+After= to any dameon/software that does any networking... than this should become common practise as we've had $network on literally every daemon with sysvinit
- admins can easly change the hard reverse-dependency of ferm|shorewall to netfilter.rules to a soft one.
- services don't need to depend on network.target or network-pre.target... which may (or may not) pull in much more than a service actually wants. I mean the more such rather vague meta-targets (like network.target) we have... the more flexibility is lost in our boot and dependency tree.


That being said... one can easily imagine that people want something like a hypothetical netfilter.target also for software like fail2ban.
E.g. I might be so paranoid, that I only want my services to be started if fail2ban runs... and I really don't want having to edit the rules files of all my daemons.

So perhaps one could make the netfilter.target to be a "network-secured.target", clearly defining that this contains any services/stuff that secure the network, giving examples like:
- netfilter rules loaded
- fail2ban
- ...

I would however probably clearly except that such netfilter-secured.target contains things that set up connections (e.g. strongswan, openvpn, etc.)
All these are again quite heavyweight... and if an admin's system depend on e.g. ipsec for security... he should implement this via netfilter rules anyway.
Comment 3 Christoph Anton Mitterer 2014-06-18 20:34:39 UTC
Oh and for things like entropy (btw: please read the thread at Debian, since I think I've tried to explain most such questions/ideas there already)...

systemd-random-seed-load.service loads, AFAIU, the random seed file. Not more not less.

What I was talking about are entropy serivces like ekeyed (for the simtec entropy key), haveged, audioentropyd, etc.

I guess these should mostly not load that early... (at least not with a hard Required[By]= dependency)...

But for services like httpd... it maybe crucial that they're in place... actually not just from a security POV, but also (when they use blocking /dev/random) from a availability POV.


Basically, I'd propose the same schema for entropy, like the one for network-security.target above.

- Have a special target: entropy-services.target (or some better name)
- Teach people: If your service/program does any crypto or other usage of entropy which is more than throwing the dice in some game: Require+Before=entropy-services.target
- Services that actually provide these services (haveged, etc. pp.) should default to RequiredBy+Before=entropy-services.target
- Teach people how they selectively change the hard dependency to a soft one... e.g. by changing the RequiredBy=entropy-services.target in haveged.service to a WantedBy=

Bon!
Comment 4 Christoph Anton Mitterer 2014-06-18 20:41:17 UTC
Perhaps one last comment... about network.target, network-pre.target  vs.  network-secured.target

I think that "in the future" daemons should usually not depend on something like network.target... since networking get's more and more dynamic, a service like postfix would ideally discover network interfaces as they appear (and I think this is also one of the base ideas of systemd)...
Truth is of course, that most services don't do this already, some perhaps never will.

So in a way, one needs a "network.target"... but it should be rather made clear that this is legacy... and ideally it's defined meaning should be constrained to something like:
- main network interface(s) are up, routes set
- DNS for the main network is up
- full stop

What "main network" is should be undefined... this could be a intranet... or the internet.


So while network-secured.targed, should be something that really *every* daemon or other services that does networking should Require=...
network.target/network-pre.target should be rather something for legacy services and especially to be locally used (for hacks ;-) ) by sysadmins.


Cheers,
Chris.
Comment 5 Lennart Poettering 2014-06-20 10:54:44 UTC
Well, we will not lose ourselves in trying to come up with way too generic hook points. We can certainly add some, but you have to make very good, very specific requests for them. And I am pretty sure I have no interest in adding more hook points for the networking mess, this is already too complex:

http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/

We really have to strike the balance here between being generic and being to complex. And complexity starts already with dumping too many unused and weakly defined unit names on them. We shouldn't add all kinds of targets people *might* use one day. Also, it's not sufficient if only very specific setups need it, with systemd upstream we want to cover the general purpose cases.

Anyway, to keep this short: please make very specific, concise requests about additional targets and we will consider them.
Comment 6 Christoph Anton Mitterer 2014-06-20 19:28:15 UTC
>Well, we will not lose ourselves in trying to
>come up with way too generic hook points.
Well but isn't that just what you do with things like network.target or network-pre.target?
network.target says about "It only indicates that the network management stack is up after it has been reached."... okay but what does that in turn mean?
Okay you say, that it's primary purpose is for shutdown... but this whole definition is still quite vague.

>And I am pretty sure I have no interest in adding more
>hook points for the networking mess, this is already too complex:
>http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
Agreed... it's too complex...

But you just make this worse by how you define it... and even more worse with network-pre.target.
It again just vaguely defined "It's PRIMARY purpose is for usage with firewall services that want to establish a firewall before any network interface is up."... which implies "add any secondary purposes as you like".

Also the logic "Network management services hence should set After=network-pre.target, but avoid any Wants=network-pre.target or even Requires=network-pre.target. Services that want to be run before the network is configured should place Before=network-pre.target and also set Wants=network-pre.target to pull it in. This way, unless there's actually a service that needs to be ordered before the network is up the target is not pulled in, hence avoiding any unnecessary synchronization point." seems to me inferior to my proposal.

No strict guidline is given... it's not immediately clear which serivces are the ones setting up the firewall... and there's no such nice functionality to avoid starting services if the firewall loading failed.


>And complexity starts already with dumping too many unused and weakly
>defined unit names on them. We shouldn't add all kinds of targets
>people *might* use one day.
I fully agree... but targets named so extremely generic like "network-pre" just open the gates for this... people will just give any meaning to it as they think it seems to fit.
Comment 7 Christoph Anton Mitterer 2014-06-20 19:43:11 UTC
>please make very specific, concise requests about
>additional targets and we will consider them.
Well I've explained most of the reasons and workings already in my previous post so here the short action points:


1) possibly drop network-pre.target again,... it seems to be largely motivated by the same what I want here, but has a much too generic name and definition which will just lead to what you try to prevent ("We really have to strike the balance here between being generic and being to complex. And complexity starts already with dumping too many unused and weakly defined unit names on them.")


2) Introduce a new target e.g. called "network-secured.target", with the meaning, that anything that needs networking to be secured, must depend on it.
And anything that actually secures the network must be depended on by it.
Give examples of what this this typically involves:
- Things that depend on secured network:
  - user sessions (since any networking programs may run in there)
  - daemons
- Things that secure the network:
  - programs that load netfilter rules (netfilter-persistent, ferm, shorewall)
  - fail2ban
  - Things that are usually not counted here:
    - strongswan, openvpn, other things that set up secured connections
      Why? Cause people should rather secure this via netfilter.

3) Make it "softly" started by early boot process (literally ANY system that has any such facilities that secure the network, will want to have it started anyway always):
I'd suggest something like WantedBy=sysinit.target + Before=sysinit.target.
=> things providing network-secured.target are started early and everything benefits from it.
=> If it fails, the system still continues to boot (since it's only a WantedBy).
=> If there is nothing that network-secured.target is depended by... fine... nothing happens


4) Teach people to GENERALLY always add Requires=network-secured.target + After=network-secured.target ... to any service/unit which does any networking.


5) Providers of network-security (fail2ban, netfilter-persistent)... should give either a ReuiqredBy=network-secured.target (suggested default) or WantedBy=network-secured.target  + Before=network-secured.target.
=> admins can easily switch, whether they want their daemons to be started or not, when any such provider (fail2ban, netfilter-persistent) failed to load.
Comment 8 Christoph Anton Mitterer 2014-06-20 19:47:27 UTC
Further, I agree that we shouldn't add to much such targets, if they're not widely used...

But I think network-secured.target (i.e. firewall rules + things like fail2ban) are so common (even on desktops) that it's justified to add such target.


I would tend to say the same for entropy-services.target... and actually I cannot think of much more other such facilities that provide security... so it would be probably only two targets we've add at most.


If things are unclear,... we could also talk directly via phone... I guess somethings you're still not travelling and in Berlin,... and having a short call should be easy, since I', in Munich.
Comment 9 Zbigniew Jedrzejewski-Szmek 2014-06-22 17:10:48 UTC
network-pre.target means "network prerequisites" as much as "before network". This name is good because it follows the general naming, and we can easy have a number of such targets (remote-fs-pre, network-pre, cryptsetup-pre, ...). This is good because there's an established pattern and there isn't an additional name to remember. Also, it stays in the realm of systemd dependency language.

OTOH, systemd cannot really make any promises that the network is secure, even after network-secured.target has been reached. *That* is something that we don't to do.

I see some merit in adding a firewall.target, with the meaning "firewall has been configured". This would provide a measure of interchangedness between various firewall configuration mechanisms. Would that work for you?
Comment 10 Christoph Anton Mitterer 2014-06-23 20:20:28 UTC
>network-pre.target means "network prerequisites"
>as much as "before network". This name is good
>because it follows the general naming, and we
>can easy have a number of such targets
>(remote-fs-pre, network-pre, cryptsetup-pre, ...)

To be honest... it seems extremely ugly to me... I mean the concept itself.
Cause ordering is done via After=/Before=, i.e. semantically... ordering should be done by naming.
Cause what's next? Someone needs something that runs after networking, and we get network-post.target. And someone else needs something that is network related but runs even before network-pre.target... what then? network-pre-pre.target?


And you still have the problem that, as I've said, network and network-pre can more or less include anything or nothing.
Name and definition are IMHO _too_ generic and ambiguous.

I'd rather go the way to add more targets, which have a tightly defined meaning and clear naming,... e.g. "network-secured.target", "dns.target"... if such are needed.
Cause this really allows units to just depend on what they actually need/want... while for network-pre.target... how should e.g. the author of a postfix.service know what this really pulls in on distro XYZ?

One of the greater ideas of systemd was to just depend and start what you really need... don't destroy this by such too generic names.



>OTOH, systemd cannot really make any promises that the
>network is secure, even after network-secured.target
>has been reached. *That* is something that we don't to do.
I've never said that systemd should make or want to make this promise.

What I want to do is, provide abstract or virtual facilities (as said, like "network secured" or "entropy daemons loaded" or perhaps "auto backup system is running"...
Authors of unit files (and I think we rather want to have the unit files upstream and not per distro) can then rest assured, that *if* a package that provides such facility is installed on a system... it will be pulled in.
systemd should of course not implement this functionality by itself.

Example:
I have a unit file for the postfix.service... since we (would) teach people to do so, Wietse adds
Requires=network-secured.target
After=network-secured.target

On Fedora, where the iptables package ships some loader scripts (IIRC),... iptables would ship a unit file, that is (per default) RequiredBy=network-secured.target.
On Debian where we have e.g. netfilter-persistent.... that package would do the same.
Other packages like ferm/shorewall would do as well.

systemd would of course not guarantee that any such package is installed (this is still the duty of the sysadmin to take care of),... but *if* such package is installed... then one can be sure that postfix only starts if the netfilter rules were _successfully_ loaded.

And should the local sysadmin want to start his services even though the rules loading failed... he simply changes the unit file of e.g. netfilter-persistent from RequiredBy= to WantedBy=network-secured.target.


>I see some merit in adding a firewall.target, with the meaning
>"firewall has been configured".
While I don't insist on my proposed name "network-secured.target" I think firewall isn't good either.
Neither would I take "packet-filter" or something like that.

I guess my idea is to also hook in other services that secure the network,... fail2ban is a prominent example (even though this would also act on the firewall)... but think of some network intrusion detection system, that one may want to have running before any daemon starts up.



>This would provide a measure of interchangedness between
>various firewall configuration mechanisms. Would that work for you?
Well it's really not just providing such target. I you just add this and no one uses it, it's worthless.
I think it's really the steps I've written in comment 7, especially steps (2) through (5).
If we don't teach authors of unit files to use it that way,... than no one will and it's useless in the end.
Comment 11 Zbigniew Jedrzejewski-Szmek 2014-06-23 20:41:48 UTC
(In reply to comment #10)
> >network-pre.target means "network prerequisites"
> >as much as "before network". This name is good
> >because it follows the general naming, and we
> >can easy have a number of such targets
> >(remote-fs-pre, network-pre, cryptsetup-pre, ...)
> 
> To be honest... it seems extremely ugly to me... I mean the concept itself.
> Cause ordering is done via After=/Before=, i.e. semantically... ordering
> should be done by naming.
> Cause what's next? Someone needs something that runs after networking, and
> we get network-post.target. And someone else needs something that is network
> related but runs even before network-pre.target... what then?
> network-pre-pre.target?
After=network.target means exactly what it seems to mean. So network-pre.target
and network.target cover pretty much all common cases.

If you need more specific dependencies, they can be specified on the level
of individual units.

> Authors of unit files (and I think we rather want to have the unit files
> upstream and not per distro) can then rest assured, that *if* a package that
> provides such facility is installed on a system... it will be pulled in.
> systemd should of course not implement this functionality by itself.
> 
> Example:
> I have a unit file for the postfix.service... since we (would) teach people
> to do so, Wietse adds
> Requires=network-secured.target
> After=network-secured.target
No, no, no. Individual services should be able to listen (securely) at any point
in time. Teaching them about network configuration stages is very wrong.

BTW. we already have the equivalent of dns.target — nss-lookup.target.

> >I see some merit in adding a firewall.target, with the meaning
> >"firewall has been configured".
> While I don't insist on my proposed name "network-secured.target" I think
> firewall isn't good either.
> Neither would I take "packet-filter" or something like that.
> 
> I guess my idea is to also hook in other services that secure the
> network,... fail2ban is a prominent example (even though this would also act
> on the firewall)... but think of some network intrusion detection system,
> that one may want to have running before any daemon starts up.
Great. They can run Before=network-pre.target. I think that this shows
why existing targets are sufficient.
Comment 12 Christoph Anton Mitterer 2014-06-23 21:34:32 UTC
I'm not really happy with closing that bug before discussion has reached an end or even consensus... o.O


>After=network.target means exactly what it seems to mean.
>So network-pre.target and network.target cover pretty much all common cases.
Well then why would you need "network-pre.target" if you can just say Before=network.target ...

That's what I've meant... the concept of having and "*-pre" or "*-post" targets or units is IMHO quite ugly and more sysvinit style.

And that applies to other ordering names as well,... like in Debian we've had
cryptsetup and cryptsetup-early sysv-init scripts... the -early version simply was the same than the other just running before MD or LVM (forgot which)...
It is a mess, never worked really well.

That's what I've said... I think design-wise unit names shouldn't contain qualifiers that order them.



>No, no, no.
Yes, yes, yes :P

>Individual services should be able to listen (securely)
>at any point in time.
What do you mean with this?

>Teaching them about network configuration stages is very wrong.
I haven't said we should teach them about network configuration or how they listen to addresses...
I said we should teach them:
"If you write a unit file for something that does networking,... then include
Requires=network-secured.target
After=network-secured.target
cause this will make sure that any system services that secure networking are already running.

And this guidelines or call it BCP doesn't change at all how some software would be written... at most it changes how the sysadmin configures his systems,... now giving him some easy way to control that services are not even started if securing the network failed... or even then started (as I've described).


>Great. They can run Before=network-pre.target.
>I think that this shows why existing targets are sufficient.
Well I don't really agree here....

For all the reasons laid out in my previous comment, I think network-pre.target is too genetically named and vaguely defined.
All kinds of stuff will sooner or later use to hook on to network-pre...and services/daemons will try to not use it, because these targets can more or less pull anything which the service may not need/want at all.
Comment 13 Zbigniew Jedrzejewski-Szmek 2014-06-23 21:45:00 UTC
(In reply to comment #12)
> >After=network.target means exactly what it seems to mean.
> >So network-pre.target and network.target cover pretty much all common cases.
> Well then why would you need "network-pre.target" if you can just say
> Before=network.target ...
Because their meaning is different. Once again, network.target means that
network has been configured. network-pre.target means that network configuration
has not yet started, and by ordering before it, units can run before any
network configuration is brought up.

[snip]

> I'm not really happy with closing that bug before discussion has reached an
> end or even consensus... o.O
Bugzilla is not a place for design discussions. If you want to, please take
it up on the mailing list.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.