[systemd-devel] Enable port forwarding via upnp
Lennart Poettering
lennart at poettering.net
Wed Feb 25 12:40:10 PST 2015
On Wed, 25.02.15 21:14, Kai Krakow (hurikhan77 at gmail.com) wrote:
> > 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...
>
> To make sure we speak the same language: I propose to have a upnp client
> only, not a server - my system is a desktop, not a router.
Yes, that's what I understood.
> I just want to offer some services on my public router IP to get
> access from outside without having to resort to static IP assignment
> and without having to edit port numbers in two or more places. As
> far as I know, there's already a upnp client library one could link
> to and use that to talk to the upnp server on the router.
Well, to get this natively integrated in networkd I'd prefer avoiding
an extra dep. I wonder if we can avoid pulling this in if we stick to
the minimal upnp bits necessary to set up the port forwarding. I mean,
this is after all just a client, not a server...
> My idea is to add a config option to socket activated services which just
> reuses the Listen directives to publish the ports to upnp on the router.
> Maybe something like
>
> [Socket]
> ListenStream=22
> PublishStream=yes
>
> which would instruct yet the to be planned upnp client to create a port
> forwarding for 22/tcp on the router. The same could work for ListenDatagram.
> Of course this only makes sense, if sockets are not bound to
> localhost only.
Yeah, I agree. Though I'd explicitly clarify that this is about
Upnp. Hence call it ExposeUPNP= or so.
> It may make sense to move "PublishStream" to the service section of a unit
> (as "PublishStreams=yes") so it could publish all sockets from each socket
> unit associated with it - though I'm not sure if this is wanted as it moves
> socket logic into another section. And it probably doesn't make sense either
> because the service is started lazily when triggered by the sockets - which
> suggests the upnp mapping should have run earlier (when the socket unit was
> started).
>
> But it would make sense for non-socket-activated services where the
> PublishStreams directive could just be reused in the following form:
>
> [Service]
> PublishStreams=22 # SSH server
I'd avoid this. If people don't use socket activation, then they
might as well configure this in networkd itself...
> It should not take much more than a wrapper around libminiupnpc.so, it's
> designed around having the smallest possible footprint:
>
> http://miniupnp.free.fr/
>
> It comes with a small test client program "upnpc" which provides all the
> stuff needed to implement the above ideas.
Hmm, the API doesn't look that great to me that I'd be enthusiastic to
depend on this I must say...
> > 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?
>
> Well, then I suppose it would be better to have a standalone daemon, let's
> call it systemd-upnpclientd.
>
> This service would subscribe to rtnl you mentioned above. This will make it
> independent of systemd-networkd and could support other implementations like
> NM etc.
Sure, you could hack that up with the daemon that miniupnp provides.
> Next step, I'm not sure however: It also needs to gain knowledge about every
> socket monitored by systemd and every socket mentioned in service files, as
> outlined in my examples. But I'm sure PID1 could simply export such
> information. Or alternatively: You mentioned that one could subscribe to
> units starting and stopping, so we could simply pull out the information
> needed.
PID 1 exports this already, via dbus. It's all readily accessible.
> I currently see problems with both approaches:
>
> When getting exported info from systemd about sockets to be published on the
> router: How do we get notified about changes introduced by starting or
> stopping units?
bus signals are sent out when units change their state.
> When subscribing to starting and stopping of units, how do we pull the info
> from the unit files if systemd-upnpclientd gets started after some units
> wanting to publish sockets are already up?
they are exposed as properties on the bus.
Lennart
--
Lennart Poettering, Red Hat
More information about the systemd-devel
mailing list