systemd and "passive" security dependencies for services?

Christoph Anton Mitterer calestyo at scientia.net
Sun May 25 23:32:17 BST 2014


On Fri, 2014-05-23 at 16:46 +0200, Tollef Fog Heen wrote: 
> What's the deal about your use of ellipsises all the time?  It looks
> really weird and I'm not sure what you're trying to communicate by using
> them.
Uhm, guess I'm using that too much. It's just some kind of a break/pause
- as you seem to use "  ".


> > Sure... but that's how it is... I guess it's absolutely sure that there
> > will always be software, which doesn't use e.g. NM (and given the issues
> > I have with NM, I'm actually happy about that).
> > But even if all software _would_ use NM (or something similar)... NM
> > doesn't take care about e.g. netfilter rules.
> 
> This has nothing to do with NM.  Interfaces come and go on machines
> running BGP daemons for instance.  Or if you use IPv6 with
> autoconfigured addresses.
Ah, I thought you were thinking, that the daemon/system wich brings
up/down any dynamic interfaces/addresses could take the duty of starting
any "dependencies" like <load netfilter rules> as soon as the even of an
new interface occurs.


> > Sure... and don't get me wrong... I never tried to show that systemd is
> > worse than sysvinit.
> It's not about better or worse.
Well I think it's worse in how it's actually used, since with sysvinit,
simply "everyone" depended on $network, so one was automatically safe in
a way.

systemd could technically do better, but therefore I think we'd need
something as what I've proposed in my last mail.


> The same goes today.  Depend on network.target and you'll have the same
> things as you have today.
Okay... don't understand why:
On a server (not taking into account more complex scenarios when you
also have e.g. NM that brings up an interface) the service that gives me
e.g. eth0 is ifup at eth0.service (from ifup at .service).
That just requires basic.target.
network.target is only wanted by networkting.service from LSB, which
will eventually go away?!
So I don't get how it is assured, that ifup at eth0.service would run
before network.target, which btw: has just a Before=network.target... 


Still, AFIAU with systemd we try to reduce any single points like
$network where many services depend on for some stuff, but they may not
even need all of them.


> > Well the upstream documentation I've referenced uses that phrases...
> > claiming network.target was passive, while network-online.target was
> > active.
> 
> I did not find the phrase in the NetworkTarget web page at least.
See also systemd.special(7):
       network-online.target
[snip snap]
           Note the distinction between this unit and network.target. This
           unit is an active unit (i.e. pulled in by the consumer rather than
           the provider of this functionality) and pulls in a service which
           possibly adds substantial delays to further execution. In contrast,
           network.target is a passive unit (i.e. pulled in by the provider of
           the functionality, rather than the consumer) that usually does not
           delay execution much. Usually, network.target is part of the boot
           of most systems, while network-online.target is not, except when at
           least one unit requires it. Also see Running Services After the
           Network is up[1] for more information.
           network.target is a passive unit (i.e. pulled in by the provider of
           the functionality, rather than the consumer) that usually does not
           delay execution much. Usually, network.target is part of the boot
           of most systems, while network-online.target is not, except when at
           least one unit requires it. Also see Running Services After the
           Network is up[1] for more information.


> > Sure... what I meant was rather:
> > Even though it's probably highly specialised... there may be setups
> > which require the netfilter rules to beloaded even before the loopback
> > is up.
> >
> > Though admittedly I haven't seen such...
> 
> I'm not able to come up with a non-contrived case for that.  Sure, if
> somebody has compromised your init system, they can do bad things, but
> that's not because they can talk to loopback, it's because they've
> compromised your init system.
Well doesn't Debian claim to be the Universal Operating System? So just
because neither you or me can think now about some example, where have
netfilter rules on loopback might be important, doesn't mean that there
aren't any.
So I think _if_ it's no big deal for us, to ensure that rules are loaded
even before lo, then why not doing it?


> > > There's nothing in the LSB definition that says «firewalls are up».  If
> > > you want that, have a ferm.service (or iptables-persistent.service if
> > > you prefer that) that has Before=network.target and it will run before
> > > you have «useful networking».
> >
> > Okay but I though network.target itself is rather something legacy... is
> > it really like "policy" that all services that do networking depend on
> > that?
> 
> If they need it, sure.
Hmm.. aha,... well there seem to be quite some services which DO
networking but don't depend on it.

And again,... this simply seems to somehow contradict one of the ideas
of systemd.
network.target means implies many (vaguely defined) things (and
"netfilter rules loaded" is not even in their list)... why should a
daemon, that is able to dynamically discover new interfaces wait for
network.target, just so that it can be sure that netfilter rules are
there, if it could load much earlier?

Not to talk about that, AFAIU, this wouldn't allow us to have daemons
not started if e.g. loading of the netfilter rules failed.


> > It's good if a service doesn't depend (i.e. the daemon doesn't crash or
> > whatever) if networking isn't there.
> > Therefore most services would only say:
> > Wants=networking.target
> 
> Note that Wants/Requires does not imply ordering.
Oh, of course... I forgot about the After?



> > But if we do like you say above (i.e. iptables-persistent has
> > Before=network.target)... then we have no real guarantee that the rules
> > are up, when the service that Wants=networking.target starts.
> 
> That is why they should also have After=network.target

Okay so basically you say now:
Any service that does networking should have a
Wants=network.target
After=network.target

I think that's still much worse than what I proposed, since:
- the service would load, even if e.g. iptables-persistent failed during
loading
- anyone that just wants to have iptables-persistent in place, but can
live with "networking" (i.e. some interfaces up, DNS, etc.) being
available later... would be delayed with start up.



> > > you need the interface not to be brought up before you apply the
> > > iptables rules.
> >
> > Sure.. I didn't claim that, did I?
> > Actually the rules must be loaded BEFORE the ifaces are brougt up.
> You claimed that it was the service start time which was interesting.
Well it's both? Start it as early as possible,... but not before you're
sure that the rules are in place. And as I'd say, don't start listening
daemons at all, if the rules loading failed.


> > So  that means loading iptables could fail, but the services would still
> > start => security issue
> 
> If you require something harder, use RequiredBy.  Note that it might
> lead to stuff not loading if your iptables rules fail to load for some
> reason.  In some setups, that might be what you want, in other, you'd
> rather have SSH running so you can log in and fix it.
I guess the best solution here would be to have a BCP/default behaviour
as I've described, i.e. daemons should depend on some "network-security"
and they will not even start when that didn't load.

SSH might be a special exception... since it's usually secure per
default.
But even ssh may be used in a way where one strongly wishes to have
iptables in place... so in a case as SSH I would perhaps suggest to make
it easily configurable via debconf?


> If you care about security you need to monitor it.
Yeah,... well I wrote about that a bit later in this mail...
I don't think this is the right way to design systems:
i.e. designing them insecure... and monitor whether that insecure
condition really arises.
If you depend on netfilter (and this is what one generally needs to
assume) than you make your services not to start if it failed loading.

You don't make some nagios which runs every day or so to check whether
there are really some rules in place, or some port locked.
This may be an additional security measure of course, but not the basic
thing.


> If you don't monitor
> it, it doesn't exist.  And no, I'd rather have SSH running and no
> iptables rules loaded than no SSH and no iptables rules.  One I can fix,
> the other I can't (without physical or IPMI access).
Well _if_ you really depend that strongly on access such nodes, than
most definitely you want the to be secure even more than available.
And further... _if_ you really run such important nodes... than you
_have_ some other means of access (physical via support, remote console,
IMPI, whatever) and if not, than you should rather get that.


> > 2) These "things" must be in place, _before_ the service is used... e.g.
> > netfilter rules must be loaded, _before_ the daemons start, _before_ the
> > user could do any networking in his sessions, etc. ... or e.g. a TRNG
> > must be activated, _before_ services want to use high quality entropy.
> >
> > If not, then one might have a short time frame, where e.g. postfix
> > listens and networking is not secured... or where httpd makes TLS
> > connections, but it still uses poor entropy from right after the system
> > boot.
> No.  In some cases, having that window where an attacker might attack a
> surface is perfectly acceptable.  In other cases, it's a big deal.  It
> depends on the context.
Well, to be honest, that's quite some disturbing view about security.
An attacker usually doesn't have vacation when such "window" is open.

Either such window exists and is there, than we should set up things in
a way, that per default it's closed... or it's not there, then we don't
have to act of course.

But having services and user sessions depending on netfilter being up is
really not that special and commonly done - this is why we have it.
So if systemd is so nice to provide us with the means not to start
services if the rules weren't loaded - then why not using that?

The funny thing is that systemd folks is kinda known to "teach" people
how things should be done right (and some people complain that this
would break existing ways of handling stuff).
But teaching them how to properly handle security and availability is
not really accepted, with the reasons that things should work and being
available always and out of the box.
This is not a responsible way of running any system.


> > 3) In systemd, we only want to start things when necessary... and also
> > only want to pull in the least necessary stuff... i.e. if postfix
> > auto-discovers new interfaces that go up and starts listening on them...
> > we don't want it to depend on network.target (which already expects all
> > the ifaces to be up)... but we DO want it to depend on "netfilter rules
> > loaded".
> > And having the netfilter rules loaded as an even (e.g. just before a new
> > interface is brought up) just doesn't work in practise.
> > So neither can we delegate that task to postfix, or to the
> > program/service that brings up the interface (e.g. ifupdown, or NM).. we
> > have to do it in the system start.
> 
> If having netfilter rules is crucial to postfix' security (which I
> really hope is not true)
May be very easily the case, if you have e.g. mail submission secured
via the source address, which is commonly used.


> then it should depend on having the rules
> loaded.  If it's only a want to have it, use After=network.target and
> Wants=network.target.
Well it's not postfix or it's maintainer or any other daemon that
decides whether Wants or Required is necessary.
The thing is... it's perfectly valid to secure services by iptables
(which is why we have it), so we must expect that people use it that way
and depend on it.
No with systemd we have some good way of defining that strong
dependency ... why not doing it?

Normally nobody should notice anything, since the rules are simply
loaded and the Requires= is just as fine as the Wants=. And in case they
aren't loaded for some error reason, there is no scenario in which it's
better to have postfix started nevertheless and exposing you to some
potential attacks.

And THIS is actually what you should monitor: Whether or not your
services are running.
You cannot really monitor security, as you've said above, since one can
only monitor a limited set of conditions.


> > So if I didn't miss anything in that example,.. one sees how easy it can
> > happen, that security is missed out.
> 
> It's not black and white; not having the rules loaded for half a second
> is «you don't have any security».

Well it's not _guaranteed_ that you're screwed then... but it may happen
extremely easy.
Like most people have a rule which ACCEPTs any RELATED,ESTABLISHED
connections.
If your attacker connects to your service in just that half second, then
his connection is ESTABLISHED and it will stay, even once the rules are
loaded.
If your intranet httpd serves content at
httpd://company-secrets.example.org/ for just some second, that may be
plenty of time to download most valuable data from there.

So actually security done right _is_ black and white - I really wonder
that so many people still don't get this after all the NSA scandal,
where one can really see how powerful and sophisticated attacks are in
practise.


> > Now if I'm right so far, I guess two questions come up for each of such
> > "things" like iptables/TRNG/etc.
> > a) When and how (i.e. via which units) should it be pulled in?
> network.target.
See above

> If you want high-quality entropy, use /dev/random, not
> urandom.
Well that's simply not done by all services... and even
if... /dev/random may block, which may be undesirable.
And even if you have some TRNG, or haveged or similar which feeds the
kernel entropy pool to provide a high bandwidth in /dev/random, then
this just emphasizes my point, namely that systemd should facilitate
that it's loaded very early.


> > b) What should happen, if the "thing" couldn't be started by systemd or
> > if the daemon (if any) that runs "thing" fails/crashes.
> Local policy.
Sure,... but the default should be the secure one, which is that a
service shouldn't start then.

It may be local policy to allow remote root login without password - but
just because this is an option, Debian doesn't default to it.
It may be local policy to allow anyone in some local net in submitting
mails via postfix - but just because this might be okay, we don't
default to it.
It may be local policy that TCP connections to postgresql are trusted -
but we don't default to it.


> > In my opinion, security always comes first, so I rather think that if
> > e.g. iptables can't be loaded (perhaps because I did a typo) then my
> > deamons should start neither.
> 
> In some cases, sure.  In other cases, no.
Well than it's still that the no-cases should have to be manually
selected by the admin,... and not the yes-cases.
Admins shouldn't need to opt-in for security, but rather opt-out.


> > [Actually I always have some slight hopes that you guys find some time
> > to also look over the unit files once packages get systemd support and
> > to see whether it's just some plain conversion from the sysvinit script
> > to systemd, or whether it really uses all nice features of systemd that
> > would make sense for the respective package (well at least I guess that
> > not all package maintainers are systemd geeks as well ;-) ).]
> 
> I know I won't have the time or interest to do so.  I suspect the same
> goes for the other systemd maintainers.
Well I expected that,... but right now some services seem to be rather
poorly converted from init-scripts to units... which somehow blocks a
lot of the benefits that systemd would give.

I don't say that this is your fault... it's just a pitty.


> > How do we handle network security "things" that run after ifaces are
> > brought up? Like VPNs or IPsec (actually I don't know, whether it's
> > necessary to have ifaces up for these to be configured, but I guess so).
> > I handle that via netfilter rules as well (i.e. I forbid any traffic
> > that is non IPsec'ed, which I consider to be security critical).
> > But for some people it may be useful to have a "network-secure-foo"
> > which is pulled in after ifaces are up (of course again the problem with
> > "which ifaces does that include?")... and which could pull in things
> > like strongwan.
> > 
> > But I guess this is a rather hacky thing and we should try to avoid it.
> > If you need IPsec/VPN for security,... set that up in your netfilter
> > rules (it's easy).
> > If you need DNSSEC,.. simply don't add any resolvers that don't
> > validate.
> 
> All of this is deep within local configuration.  Debian can offer some
> defaults, but things like «don't allow non-IPSec traffic» obviously
> won't fly in the default installation.  As a start, you would not be
> able to do network installations.
Sure... that's what I tried to say above ("and we should try to avoid
it").
I mean if someon depends on IPsec,... he must set up his netfilter rules
so to secure things up.
But _that_ in turn is what Debian should guarantee per default, that if
you have something like iptables-persistent installed... then this comes
"first", and services are only started if it worked.


> Lots of those targets can be supplied by the local admin or another
> package. If you do that and convince people to use them, more power to
> you.  We don't have the time and energy to do so within the systemd
> team.
Well I don't think there's so much you'd have to do, is there?
It's adding some new targets, like my proposed network-secured.target
(btw: fail2ban could be another candidate for being RequiredBy+Before by
that),... writing somewhere to the wiki what it means, adding it to e.g.
sysinit.target ... and if other maintainers ask you about "how do I
convert my init scripts,... you mention it when you give them help".
So the toughest part is probably thinking about some better name than
"network-secured".

I also don't think it should be supplied locally or by other packages...
actually it should rather go upstream.
If other packages provide it, then which? iptables-persistent? ferm?
shorewall? Something new, which all other packages whose daemons would
Require= it would need to depend on?

Having such units provided by local admins make it lot of a burden to
convert all your units to actually depend on it.
I don't quite see what a system as I proposed it would make worse. It
would be more secure out of the box, and if someone (like you with ssh)
really says well I don't want to have that strong dependency as in
Required= than it's easy to change it per service (e.g. change the
Requires=network-secured.target of ssh to wa Wants)... or globally per
security "thing", e.g. change the RequiredBy=network-secured.target of
fail2ban to a WantedBy= ... but perhaps leave it at RequiredBy= for
iptables-persistent

But if the base thing, i.e. the Requires=network-secured.target isn't
done by all daemons or other services that do networking,... than it's
like not practically doable by the sysadmin.



I mean even if you guys are not that much into strong security as it
should be expected on every system, I'm a bit surprised to not really
get some positive feedback here like "seems to be a good idea"...

Having something like network.target which can be anything seems to
contradict the systemd ideas... and I'd have expected it to be quite
legacy.



Cheers,
Chris.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5165 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-systemd-maintainers/attachments/20140526/be8db9db/attachment-0002.bin>


More information about the Pkg-systemd-maintainers mailing list