LXC/LXD Port Forwarding Containers Using UPnP

 •  Filed under lxc, lxd, containers, port forwarding, upnp, igd

So this is going to be a quick writing about the easiest way to manage networking for your containers as far as I know by setting up your container host system as a so-called Universal Plug and Play Internet Gateway Device.

Please note that all commands used in this post are aimed to be used on a Debian-based host and guest OS.

Here's an image of an example setup:

LXD

Before installing all needed software packages, it's good to have all the networking details on paper:

  • Our public interface is named ens33 and has the IP address 23.42.150.20
  • Our private (LXD Bridge Host) interface is named lxdbr0 and has the IP address 10.22.240.1
  • Our private subnet is a /24 subnet

On the container host, you'll need to install the linux-igd software package which takes care of incoming UPnP client requests. All containers need the miniupnpc package to provide the containers with UPnP client functionality.

Setting up linux-igd on the host

First of all, update your package cache with apt update. When done, use apt install linux-igd to install the IGD host software package.

Next up is the configuration process, which is fairly simple. There's a configuration file located at /etc/default/linux-igd which needs to be edited. Just add the following lines to the end of this file

EXTIFACE=ens33  
INTIFACE=lxdbr0  

And save the file. Don't forget to double-check your external and internal network interface names! Also, use sudo service linux-igd restart to make all changes effective.

Setting up miniupnpc on a container

Again, first of all update your package cache on the container with apt update and install the miniupnpc software package with apt install miniupnpc afterwards.


Forwarding a port

To forward a port, use the following command inside a container:

upnpc -a containerip containerport hostport protocol  

Here's an example:

upnpc -a 10.22.240.41 2368 80 tcp  


Make linux-igd work after a reboot

It could be that after a reboot systemctl status linux-igd.service returns a failed status, telling you that the LXD bridge interface does not (yet) exist. This can easily be fixed, but requires some trickery so I would call this a workaround.

First of all, disable linux-igd.service at startup:

systemctl disable linux-igd.service  

And edit the LXD bridge startup script:

nano /usr/lib/lxd/lxd-bridge.start  

Now right above the line that says exit 0 you place the following snippet:

systemctl start linux-igd.service  

Reboot your system. As soon as the bridge interface goes up, the linux-igd service will be started. No error and a working IGD :)

Thanks to Alex Hole for noticing this. 👍🏽