Agilicus Connector Air Gap Machine With Containers

person-setup-machine

Agilicus Connector Air Gap Machine With Containers

Create a nearly-fully airgapped machine, with interior containers, no way in, and only 1 way out via Agilicus Connector.

Agilicus Connector Air Gap Machine With Containers

Imagine we have a complex set of orchestrated containers. They interoperate with each other. But, we don’t want them reaching the Internet, or the Internet reaching them.

Some or all of these containers have a need to use remote services. Perhaps a cloud provider, perhaps another set in another building.

In this example we show how to:

  1. Block all inbound traffic to a Debian 12 host
  2. Block all outbound traffic except for Agilicus API + Dataplane
  3. Use a service forwarder to allow specific containers to reach specific remote services

For the container runtime we will use docker. The example below is a Debian 12 host with all options default, with docker.io installed.

Debian 12: Default Firewall Rules

Before we start we can inspect the default firewall rules. In a nutshell these:

  1. allow all outbound traffic from the host to Internet
  2. allow all outbound traffic from containers to Internet
  3. allow all outbound traffic from containers to host

Setup: Block inbound traffic, block outbound except to Agilicus Cloud, Local DNS/DHCP

Note: you may wish to have console access rather than SSH access in case you make a mistake.

We can see the Agilicus required IP/hostnames. For this example, we will allow (on port 443), these two IP:

  • 34.95.12.47 (www.agilicus.com)
  • 35.203.36.11 (api.agilicus.com)

At this stage, we can test. First let us confirm that DNS works and that we can reach Agilicus WWW (for system updates):

Now let us check that we cannot reach other websites:

Now let us demonstrate that a docker container cannot escape:

Not so fast, we have now blocked docker hub. For our scheme to work, we will need to either get all containers on the machine out of band, or allow a docker registry. I will demonstrate the out-of-band technique:

OK, why did the container reach the Internet if the host cannot? For this we need to understand FORWARD (e..g routing) versus INPUT/OUTPUT. The Host is routing the docker traffic, we need some rules in the FORWARD path.

At this stage, lets test again. We have made the default forward policy be to drop, and we have removed the MASQUERADE (NAT) rule.

OK, we now have a set of containers which cannot reach the Internet on anything, and, a host that can reach a very limited set (DNS, DHCP, and Agilicus AnyX Cloud).

Let us now check that the container can still reach the host. For this we will use two windows. In one, we will run ‘netcat’ to listen on a port, in the other we will test from the host to itself. In green, window 1, we run netcat in listen mode:

$ nc -lvp 8888
listening on [any] 8888 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 38276

In black, we run netcat in connect mode, we observe it works.

Let us now try from within the container

Why did this hang? We are blocking all INPUT/OUTPUT except loopback (lo) and except for certain IP/port pairs. Let us add docker0 back in:

OK at this stage we can test again, and it works. The container can reach the host (on all ports), but not the Internet.

Install Agilicus Connector on Host

Let us install the Agilicus connector.

Why did this hang? As a shortcut in the command, it is using ‘agilicus.com’ and ‘http’. We can make a minor change:

This now works, demonstrating that our above firewall rules prevent port 80 access.

Next Steps

You can save/restore your iptables rules with iptables-save and iptables-restore. You can install iptables-persistent package to make these load on reboot (or put the rules in e.g. /etc/rc.local).

You may consider only allowing the containers to reach specific ports, where we would run the Agilicus connector.

The final rule set we ended up with: