Exposing ports of a container to the host

I need to make some ports of my containers accessible from the external IP of my host.

I found out that now LXD has internal support for this with the proxy device type, so to expose the container’s SSH server on port 2222 on the host I do :

$ lxc config device add  $container $devicename proxy listen=tcp:$hostip:2222 connect=tcp:127.0.0.1:22 

So far so good.

I was surprised to not see anything in my iptables regarding this, and found out that might be what is discussed in https://github.com/lxc/lxd/issues/2504#issuecomment-309292622

The current documentation (https://lxd.readthedocs.io/en/latest/containers/#type-proxy) being quite quick, I figured out this must be that ‘nat’ parameter in the proxy device configuration.
So I tried to use it :

$ lxc config device add  $container $devicename proxy listen=tcp:$hostip:2222 connect=tcp:127.0.0.1:22 nat=true
Error: Invalid devices: Only host-bound proxies can use NAT

Quite surprised by this error message, since host is supposed to be the default bind type.
If I explicitely set bind=host I get a new error message :

$ lxc config device add  $container $devicename proxy listen=tcp:$hostip:2222 connect=tcp:127.0.0.1:22 nat=true bind=host
Error: NIC IP doesn't match proxy target IP

How is nat supposed to be used ?

The fact that you get an error without bind=host is a bug, I’ll send a fix for that.

The second error is because for NAT to work, the connect= address must match the container’s address which must be set using ipv4.address on the nic device.

The proxy device without NAT can do all kind of weird forwarding including forwarding to localhost of another namespace (as is done in your case), but when requesting nat, that’s not an option and so LXD must make sure that the host is the container’s gateway, that the container’s IP won’t change and that the container’s IP matches the target of the proxy device.