Discussion:
Users and system namespaces
(too old to reply)
Ben Boeckel
2014-01-23 18:54:05 UTC
Permalink
Hi,

As I mused on LWN[1] recently, I was wondering whether it was possible
to have user units be able to hook into namespaces (namely the
PrivateNetwork= and PrivateTmp= from systemd.exec(5) and more if other
namespacing options are added in the future).

I'm assuming that is not possible now to use JoinsNamespaceOf= (from
systemd.unit(5) across such boundaries since I see no way to limit which
users may do so.

The specific use case I'm looking to fulfill is to be able to set up VPN
for use for only specific service files (particularly user unit files).

My idea for how to implement it is to use a vpn.target directory to
collect everything then then following unit files:

vpn-namespace.service:
PrivateNetwork=true
vpn-***@.service:
After=vpn-namespace.service
Before=vpn.service
ExecStart=/usr/local/bin/setup-vpn-ns %i $NS_TO_SETUP
vpn.service:
JoinsNamespaceOf=vpn-namespace.service

The setup-vpn-ns script would create new interfaces to bridge over the
%i interface and clone the routing tables into it. I don't know how I
would get the name of the namespace setup in vpn-namespace.service
though (maybe something which does:

systemctl set-environment VPN_NS=$( find-ns /proc/self/net )

in ExecStartPost= of vpn-namespace.service?).

It would be nice if, as a user, I could then start a service as a user
which JoinsNamespaceOf=system:vpn-namespace.service and
Wants=system:vpn.target (failing if it isn't already running) to create
user services which use the VPN rather than the default network setup
(my idea is to start a tmux server for this, but I guess something like
a custom Firefox profile instance could also be used).

What is needed (based on what I didn't see in the docs; probably not
exhaustive either):

- ability for a system service to expose what namespace it just
created (to avoid the set-environment hackery above);
- a directive to list users and groups allowed to enter into
namespaces created in a unit (something like
"ExposeNamespaceToUsers=group:vpn,wheel" maybe?); and
- a way for a systemd --user to get namespace file descriptors from
PID 1.

Thoughts?

Thanks,

--Ben

[1]https://lwn.net/Articles/582046/
David Timothy Strauss
2014-01-23 19:43:52 UTC
Permalink
To join a namespace, you'll need a file descriptor for the namespace
so you can run setns() [1]. It's possible to share a file descriptor
by keeping it open while forking (which is how socket activation
works) or passing it over a Unix domain socket [2].

I know this doesn't really answer your question, but I thought the
resources might be helpful.

[1] http://man7.org/linux/man-pages/man2/setns.2.html
[2] http://stackoverflow.com/a/2358843
Ben Boeckel
2014-01-23 19:51:18 UTC
Permalink
Post by David Timothy Strauss
To join a namespace, you'll need a file descriptor for the namespace
so you can run setns() [1]. It's possible to share a file descriptor
by keeping it open while forking (which is how socket activation
works) or passing it over a Unix domain socket [2].
Yeah, I'm aware; I was more interested in whether systemd would be
something I could have to it for me (using the declarative syntax)
rather than having a service sit around just for one fd to hand out[1].
I think some general ability to bring different services into namespaces
which get setup by another unit would be worthwhile in the long run, but
I only really have a use case for network sharing[2].

Thanks,

--Ben

[1]Plus, it'd probably be doing things with either D-Bus and PolicyKit
or a AF_UNIX socket with manual credential checking and that sounds like
a lot of stuff to code up just to hand out one fd when requested.
[2]I guess adding services to containers would be another, but you
already have a PID 1 in those anyways (the system/user boundary is the
sticking point here).
David Timothy Strauss
2014-01-23 21:21:30 UTC
Permalink
I think the intention for your needs (a lot of namespace sharing for a
family of services) would be to run another systemd in a namespece
using something like systemd-nspawn, libvirt-lxc, LXC, a user session,
or similar. Basically, a systemd instance would run in the namespace
itself. Is that a problem?
Ben Boeckel
2014-01-23 21:31:52 UTC
Permalink
Post by David Timothy Strauss
I think the intention for your needs (a lot of namespace sharing for a
family of services) would be to run another systemd in a namespece
using something like systemd-nspawn, libvirt-lxc, LXC, a user session,
or similar. Basically, a systemd instance would run in the namespace
itself. Is that a problem?
I'm sure that'd work, but that's hoops that I think might be able to be
avoided here.

Right now to VPN, I open a root shell, run "openvpn --config vpn.conf"
and ^C it when I'm done. The downside is that it makes *all* of my
traffic go over the VPN. My idea is to just shove a tmux server into a
network namespace with *just* the VPN and launch things from there as
needed (browsers, shells, SSH, etc.).

Being able to do this in a single user sessions would be nice without
having to make another user/seat which I then do X forwarding to get
into my main session (or start doing xauth madness to be able to just
set DISPLAY).

--Ben
Lennart Poettering
2014-01-24 10:07:18 UTC
Permalink
Post by Ben Boeckel
Hi,
As I mused on LWN[1] recently, I was wondering whether it was possible
to have user units be able to hook into namespaces (namely the
PrivateNetwork= and PrivateTmp= from systemd.exec(5) and more if other
namespacing options are added in the future).
WHat to you mean by "user units"? THose run off an unprivileged "systemd
--user" instance? Or those run off PID 1 but with User= set?

Note that the whole namespacing thing is only available from systemd
instances that themesleves are privileged, i.e. only from PID 1...
Post by Ben Boeckel
- ability for a system service to expose what namespace it just
created (to avoid the set-environment hackery above);
- a directive to list users and groups allowed to enter into
namespaces created in a unit (something like
"ExposeNamespaceToUsers=group:vpn,wheel" maybe?); and
- a way for a systemd --user to get namespace file descriptors from
PID 1.
The privileges thing is quite limiting. Joining namespces from
unprivileged code is hard... You need some kind of setuid binary
transition there, but I wouldn't see how you would make that
happen... And the complexity gives me headaches...

Lennart
--
Lennart Poettering, Red Hat
Ben Boeckel
2014-01-24 16:27:27 UTC
Permalink
Post by Lennart Poettering
Post by Ben Boeckel
As I mused on LWN[1] recently, I was wondering whether it was possible
to have user units be able to hook into namespaces (namely the
PrivateNetwork= and PrivateTmp= from systemd.exec(5) and more if other
namespacing options are added in the future).
WHat to you mean by "user units"? THose run off an unprivileged "systemd
--user" instance? Or those run off PID 1 but with User= set?
systemd --user. Would it be possible to use User= to do this though from
a system service?
Post by Lennart Poettering
Note that the whole namespacing thing is only available from systemd
instances that themesleves are privileged, i.e. only from PID 1...
Hrm, true.
Post by Lennart Poettering
The privileges thing is quite limiting. Joining namespces from
unprivileged code is hard... You need some kind of setuid binary
transition there, but I wouldn't see how you would make that
happen...
Probably some systemd-setns helper or whatever to shim in before the
exec.
Post by Lennart Poettering
And the complexity gives me headaches...
Agreed, but I was thinking that it'd be simpler to leverage systemd here
than start up a container and make it "seamless" to the user session.
Maybe there's a better approach available?

--Ben
Lennart Poettering
2014-01-24 17:35:30 UTC
Permalink
Post by Ben Boeckel
Post by Lennart Poettering
Post by Ben Boeckel
As I mused on LWN[1] recently, I was wondering whether it was possible
to have user units be able to hook into namespaces (namely the
PrivateNetwork= and PrivateTmp= from systemd.exec(5) and more if other
namespacing options are added in the future).
WHat to you mean by "user units"? THose run off an unprivileged "systemd
--user" instance? Or those run off PID 1 but with User= set?
systemd --user. Would it be possible to use User= to do this though from
a system service?
Yeah, you can do a lot of stuff with User= since we only drop privs in
such a case pretty late, so you can actually set up namespaces and stuff
with full priviliges...

Lennart
--
Lennart Poettering, Red Hat
Continue reading on narkive:
Loading...