LXD with "iptables -P INPUT DROP"

Hi there,

My goal:
LXD container with static public ips on a host with iptables, that is managing the access to the containers.

Example:
a) Ports 80 and 443 on container A is available for a dinfed IP.
b) Every port on container B is just available for defined IPs (no public access).
c) Every port to all container for a defined IP

With the default LXC iptables configuration (after the installation), the containers are accessible and the containers are able to conntect to the internet (OUTPUT).

Problems:
With the following rules, the containers are not accessible and the containers are not able to connect to the internet (OUTPUT).

Here is my current example configuration (not working):

*filter
:INPUT DROP
:FORWARD DROP
:OUTPUT ACCEPT

-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

-A INPUT -p tcp --dport 80  -d 111.111.111.111 -j ACCEPT -m comment --comment "a) Allow access to container A with port 80"
-A INPUT -p tcp --dport 443 -d 111.111.111.111 -j ACCEPT -m comment --comment "a) Allow access to container A with port 443"
-A INPUT -s 222.222.222.222                     -j ACCEPT -m comment --comment "b) Allow single ip access to host and all containers"
-A INPUT -s 234.234.234.234 -d 123.123.123.123 -j ACCEPT -m comment --comment "c) Allow single ip access to container A"

-A INPUT -i br1 -p tcp -m tcp --dport 53 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A INPUT -i br1 -p udp -m udp --dport 53 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A INPUT -i br1 -p udp -m udp --dport 67 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A FORWARD -o br1 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A FORWARD -i br1 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A OUTPUT -o br1 -p tcp -m tcp --sport 53 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A OUTPUT -o br1 -p udp -m udp --sport 53 -m comment --comment "generated for LXD network br1" -j ACCEPT
-A OUTPUT -o br1 -p udp -m udp --sport 67 -m comment --comment "generated for LXD network br1" -j ACCEPT

COMMIT

*mangle
:PREROUTING ACCEPT
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
:POSTROUTING ACCEPT
-A POSTROUTING -o br1 -p udp -m udp --dport 68 -m comment --comment "generated for LXD network br1" -j CHECKSUM --checksum-fill
COMMIT

*nat
:PREROUTING ACCEPT
:INPUT ACCEPT
:OUTPUT ACCEPT
:POSTROUTING ACCEPT
-A POSTROUTING -s 10.4.186.0/24 ! -d 10.4.186.0/24 -m comment --comment "generated for LXD network br1" -j MASQUERADE
COMMIT

The list of containers:

+--------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
|  NAME  |  STATE  |              IPV4              |                     IPV6                      |    TYPE    | SNAPSHOTS |
+--------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
| con-a  | RUNNING | 111.111.111.111 (eth0)         | fd42:3c7a:19d4:228f:...:....:....:6dcc (eth1) | PERSISTENT | 0         |
|        |         | 10.4.186.195 (eth1)            | 2a01:4f8:221:1329::195 (eth0)                 |            |           |
+--------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
| con-b  | RUNNING | 222.222.222.222 (eth0)         | fd42:3c7a:19d4:228f:...:....:....:268b (eth1) | PERSISTENT | 0         |
|        |         | 10.4.186.194 (eth1)            | 2a01:4f8:221:1329::194 (eth0)                 |            |           |
+--------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
| con-c  | RUNNING | 123.123.123.123 (eth0)         | fd42:3c7a:19d4:228f:...:....:....:13d3 (eth1) | PERSISTENT | 0         |
|        |         | 10.4.186.201 (eth1)            | 2a01:4f8:221:1329::201 (eth0)                 |            |           |
+--------+---------+--------------------------------+-----------------------------------------------+------------+-----------+

I am a beginner with iptables - sorry for that :slight_smile:

Versions:

  • lxc version: 2.15
  • lxd --version: 2.15
  • lsb_release -a: Ubuntu 16.10
  • iptables --version: v1.6.0

thanks!

Hi!

It’s not clear when you mention accessible and defined. For accessible, you would need to specify from where when you use that word. defined=specific.

By default (the default LXD “lxd init” configuration), all containers have private IP addresses and are not accessible from the Internet. The typical practice is to designate a specific container (container A) to be a proxy, and install there HAProxy or nginx (as reverse proxy). Then, use iptables so that any connection to the host at ports 80 and 443, get forwarded to container A. The reverse proxy will then forward the connection to the appropriate (other) container with the web servers.

Have a look at the tutorial at https://www.digitalocean.com/community/tutorials/how-to-host-multiple-web-sites-with-nginx-and-haproxy-using-lxd-on-ubuntu-16-04 which describes just that.

You just need one iptables command per port, therefore two commands for ports 80 and 443.
Have a look at this,
PORT=80 PUBLIC_IP=your_server_ip CONTAINER_IP=your_container_ip sudo -E bash -c 'iptables -t nat -I PREROUTING -i eth0 -p TCP -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $CONTAINER_IP:$PORT -m comment --comment "forward to the reverse proxy"'

1 Like

Hi Simos, thank you very much for your answer.
We are planing to use the containers for development. The developer should be able to connect via SSH to the container and install stuff on it (if necessary for temporary tests).
For that I thought we can use LXD/LXC containers, which are like own litle servers on a very powerfull host.
At the moment I am using the hetzner firewall (hardware firewall). But there are just 10 rules possible.
And my containers have already lan and public (wan) ips.
And now it would be awesome to remove the hetzner firewall + configure iptables on the host.
Would that be possible? Our my thoughs/plans are not meaningful?
Thanks

One option for the developer would be to set a rule to redirect from port 2222 on the server to port 22 of a specific container. Then, set up on this container to be able to SSH to those other containers that it should connect to.

A default Ubuntu installation on Hetzner listens only on port 22 for SSH. iptables can do L3/L4 firewall. Is that Hetzner firewall an application firewall?

@brunzdulb, could developers ssh to the host on which containers are running? If yes, why they need to ssh to containers? lxc exec con-x -- sudo --login --user ubuntu should be sufficient. On the other hand, if containers have LAN and WAN IPs, I don’t understand why developers could not ssh directly to containers? Are developers on LAN/WAN?

iptables might not be the right tool for the task. Managing iptables could turn into a nightmare quickly. Did you consider using the new proxy device?

Perhaps it sounds like a crazy complex, but deploying OpenStack on LXD is quite easy. Having OpenStack private cloud would give you a flexibility of which one could only dream. You could assign a floating IP to desired VMs (by default Nova compute node will use KVM but if you are not happy with that you could opt for nova-lxd). After all, containers are not mini servers, but short-life, disposable units.

1 Like