[systemd-devel] Enable port forwarding via upnp

Lennart Poettering lennart at poettering.net
Wed Feb 25 10:17:00 PST 2015


On Wed, 25.02.15 08:16, Kai Krakow (hurikhan77 at gmail.com) wrote:

> Hello!
> 
> Is it possible to somehow create a service which enables port forwardings on 
> my router using upnp? Currently, I guess it is not possible (except maybe 
> using ExecPost or ExecPre and the upnpc program). But when my client IP 
> changes via DHCP, it should be reapplied. Also, it needs to be maintained as 
> the programmed port forwardings would timeout and be cleared from the router 
> after a while. So it needs to be hooked up to systemd-networkd somehow (at 
> least that is what I am using).

Not really. Such a upnp port setup tool could just subscribe to rtnl
and update the router's configuration dynamically each time the local
configuration is changed, without having to know anything about
networkd, NM or anything else.

That said I think it wouldn't be too far off I figure to add logic for
this to networkd. I mean, it speaks a variety of client side protocols
already, and this could just be one more. The major difference though
is that upnp is a frickin insane pseudo-HTTP XML craziness, while
DHCP, IPv4LL and so on are much more low-level. That said, I figure
we'll have some kind of HTTP logic in networkd eventually anyway to
support wispr and things like that, so maybe doing upnp wouldn't be
completely off either...

I figure if we can do this with existing deps, the internal XML parser
and so on, this could work. I.e. a minimal upnp port forwarding
library รก la sd-dhcp would be acceptable...

> So I guess this logic should be built into systemd-networkd, maybe offering 
> some dbus interface also. And service and/or socket files could have a flag 
> to enable upnp forwards. This way, systemd-networkd knows about the 
> registered forwards and maintains them, and systemd will trigger 
> registration/unregistration on it whenever services start or stop which have 
> such flags enabled. By using dbus, this could be an interface implemented by 
> other network management daemons, too.

This is already the second step... It kinda opens another can of worms
though: we discussed on and off how integration between mDNS/DNS-SD
and .socket units could look like. This port forwarding thing and the
mDNS hookup are somewhat related: in both cases we have a concept of
actively registering with some external code as long as as a socket is
up.

Originally, when we discussed that in the mDNS context I thought of
simply using ExecStartPre= and ExecStopPre= for this, and forking off
a tool that pushes the mDNS registration into avahi/resolved as long
as the socket is up. But I ended not liking this idea, since in most
cases this would mean having one addition process around, that does
some bits when it starts up, then only hangs around, and then does a
bit more when it shuts down. Hanging around pointlessly is bad
though. So the next idea was maybe then PID 1 could simply call
directly into avahi/resolved via async bus calls, so that we have no
extra pointless processes hanging around.

However, that idea I don't like either, because it makes PID 1 client
of another daemon, and I really don't like that, I'd really prefer it
the other way round: the higher level daemons should call into the
lower level daemons, and subscribe to them, but the lower level
daemons should never call into the higher level daemons...

In networkd we followed this correct stacking design quite
nicely. networkd never pushes NTP servers into timesyncd or DNS
servers into resolved. Instead, timesyncd and resolved subscribe to
what networkd announces and pull the data out that. Most likely that's
the logic we should follow here too: 

- For the port forwarding logic we should introduce a new .socket
  property, that PID 1 doesn't really do much with, except exporting
  it on the bus

- networkd susbcribes to .socket units starting and stopping in
  PID 1, and pulls out that one property of them, and acting on it.

Similar, we would handle the mDNS case: the .socket units would gain a
new DNSSDService property, that resolved then keeps track of an
operates on.

I hope that makes some sense?

Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list