Whilst it is possible to use manual iptables rules to forward ports from outside to containers. It works, but not well, because it is impossible to connect from container to outside IP or connect from the host itself to outside IP’s ports (like my own DNS server).
Here are the steps to forward port from outside to container properly using LXD’s
proxy device in NAT mode (which automates the iptables rules required):
br_netfilter kernel module. This step is optional, but without it your container will not be able to connect to the proxy’s external address and have connections forwarded back to it. However caution should be taken with this step on systems running existing instances and a firewall as enabling
br_netfilter will cause all bridge traffic to flow through the firewall, and may cause some traffic to be unexpectedly blocked if an existing firewall rule matches bridge traffic that wasn’t previously filtered.
In Debian 10 you can do this:
modprobe br_netfilter echo br_netfilter > /etc/modules-load.d/lxd.conf
Second, set a static IP address on your container’s NIC. Look up your current dynamic address:
lxc list | grep testcontainer | testcontainer | RUNNING | 172.16.172.113 (eth0) | fd42:dad8:c4ad:e744:216:3eff:fecf:5770 (eth0) | CONTAINER | 0 |
And set that address as static IP:
Note: That when setting a static IPv6 address you will need to ensure that the parent managed network has
ipv6.dhcp.stateful enabled, otherwise setting a static IPv6 address will fail.
lxc stop testcontainer lxc config device override testcontainer eth0 ipv4.address=172.16.172.113 ipv6.address=fd42:dad8:c4ad:e744:216:3eff:fecf:5770 lxc start testcontainer
Third, add proxy device to your container, one per port:
lxc config device add testcontainer proxyv4 proxy nat=true listen=tcp:a.b.c.d:7777 connect=tcp:0.0.0.0:7777 Device proxyv4 added to testcontainer lxc config device add testcontainer proxyv6 proxy nat=true listen=tcp:[2001:db8::1]:7777 connect=tcp:[::]:7777 Device proxyv6 added to testcontainer
2001:db8::1 is your external IP address and
proxyvX is just a string identifier, so error messages about missing device are kinda misleading, it’s not a real network interface.
Now you can telnet to your external IP anywhere; inside the container, inside the host or outside, all iptables rules are created automatically.
To remove that port forward use remove command:
lxc config device remove testcontainer proxyv4 Device proxyv4 removed from testcontainer lxc config device remove testcontainer proxyv6 Device proxyv6 removed from testcontainer
For more information, see the
proxy device documentation: https://linuxcontainers.org/lxd/docs/master/instances#type-proxy