Tutorial: IP Whitelisting for Docker Containers
You can use iptables
to restrict network access to an individual container without altering the Host’s rules or introducing external firewalls.
Why?
Some potential use cases:
- I have an app that’s not ready for production but needs to be tested on a production server.
- I have multi-tenancy in my SaaS and the customers want to restrict usage of a container just to their IP range.
- I host services (databases, proxies, cache…) that rely on IP-based whitelist authorization
How?
Install IP tables in a docker container and use the docker exec
command to alter the rules.
Here’s an example of IP based restriction for an Nginx container
Requirements
- A VPS ( DigitalOcean or Vultr work— Free $10 Credit) with Docker
- 2 different public IP addresses to test from. You can toggle a VPN or SSH into another machine you have.
Getting Started
I have a staging container on a shared VPS that should be accessed only from a range of IPs (say an office VPN )
We will call the machines and IPs as follows
A ) 222.100.100.100 — The VPS
B) 222.200.200.200 — Trusted Source IP
Step 1. Prepare your VPS
Install Docker and confirm that you can access your firewall is open. Some providers like EC2 require that you manually override Security Groups to allow external incoming traffic.
Launch a basic Nginx container that listens on all IP addresses (0.0.0.0) on port 8080
Using iptables within a container requires additional network capabilities forreasons stated here. So, we also add NET_ADMIN and NET_RAW capabilities.
docker pull nginx
docker run --cap-add=NET_ADMIN --cap-add=NET_RAW --name app1 -d -p 0.0.0.0:8080:80 nginx
Test that it works
curl http://222.100.100.100:8080
should print the Nginx welcome screen on all machines.
Step 2. Install IP Tables
Many Docker images come with iptables
pre-installed. Just in case, install it via exec:
docker exec app1 apt update
docker exec app1 apt install iptables -y
Verify it works:
docker exec app1 iptables -S
It should output:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
Step 3. Block All Traffic
First, we block all traffic to the port that is bound in the container. Here, it is port 80, not 8080.
docker exec app1 iptables -A INPUT -p tcp --dport 80 -j DROP
Verify that it’s blocked
From an external machine, curl http://222.100.100.100:8080
should not work.
Step 4. Whitelist IPs
Then, we white list the trusted source IPs:
docker exec app1 iptables -I INPUT -p tcp --dport 80 --source 222.200.200.200 -j ACCEPT
Notice the -I flag which prepends to the rule file ensuring the white lists have higher precedence over the rule we added in Step 3.
curl http://222.100.100.100:8080
This will work only from the white listed IP. If you can access it from another source, it means something was misconfigured.
Step 5. Remove Whitelist IPs
To remove a whitelist, you can retrieve a list of all your rules:
docker exec app1 iptables -S
and then copy/paste the rule to the -D command, which drops it
docker exec app1 iptables -D INPUT -p tcp — dport 80 — source 222.200.200.200 -j ACCEPT
Step 6. Testing
You can use https://www.geoscreenshot.com to test HTTP access from many IPs.