More than 1 month ago, someone sent a question in the article How to install Netdata as follows: “Can you tell me how to block access through a specific ip:port address, currently I use ufw to block port 19999 but when I access it through the vps ip in the form of xxxx:19999, I can still access the netdata page.“
Then I checked again and discovered that on the Linux server, the UFW firewall will not work if Docker is enabled: UFW does not block access to ports declared by Docker
Specifically the error and how to fix the error you see below will be clear.
Table of contents
I. Enable UFW
Install UFW with the command sudo apt install ufw -y
then open port 22 and enable UFW on the system
ufw allow ssh
ufw default deny incoming
ufw enable
Check ufw working status with command ufw status
will see the active status (active)
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
I use another computer to check the port 8888
of the server (IP: xxx.xxx.xxx.xxx
) is open. Use command:
nmap -Pn -p 80 xxx.xxx.xxx.xxx
The returned result will see that port 8888 is being blocked (STATE: filtered)
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 17:17 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up.
PORT STATE SERVICE
8888/tcp filtered sun-answerbook
Nmap done: 1 IP address (1 host up) scanned in 2.06 seconds
II. Enable Docker
I enabled Smokeping on the server, using file docker-compose.yml
with the following content
---
version: "2.1"
services:
smokeping:
image: lscr.io/linuxserver/smokeping
container_name: smokeping
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Ho_Chi_Minh
volumes:
- ./config:/config
- ./data:/data
ports:
- 8888:80
restart: unless-stopped
III. Port 8888 is now open!
Port check time 8888
again from another computer
nmap -Pn -p 80 xxx.xxx.xxx.xxx
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 17:21 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up (0.28s latency).
PORT STATE SERVICE
8888/tcp open sun-answerbook
Nmap done: 1 IP address (1 host up) scanned in 0.34 seconds
Surprise! Port 8888 is now open, despite setting UFW to block all ports except SSH port 22.
This is a dangerous security error because the system was thought to be protected by UFW, but it turned out not to.
IV. Cause of error
The reason why UFW no longer works is because Docker has direct editing permissions to the system’s iptables. When Smokeping is enabled, Docker automatically adds the DNAT Rule to iptables, helping to access the port 8888
from the outside.
Check iptables with the following command
iptables -t nat --list | grep 8888
You will see the result as below
DNAT tcp -- anywhere anywhere tcp dpt:8888 to:172.20.0.2:80
V. How to fix it
There are two ways to fix the UFW not working error when using Docker.
1. Prevent Docker from editing iptables
Edit files /etc/docker/deamon.json
sudo nano /etc/docker/daemon.json
Add to line { "iptables" : false }
and save.
Restart Docker with the command
sudo service docker restart
Check the connection from the outside, now rest assured port 8888 is locked.
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 16:27 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up.
PORT STATE SERVICE
8888/tcp filtered http-proxy
Nmap done: 1 IP address (1 host up) scanned in 2.04 seconds
The pros and cons of this approach are as follows:
- Advantages: fast editing, compact, fast, suitable for servers running only 1-2 Docker services.
- Cons: Docker’s network management feature is disabled, making it impossible for network services to be initiated later on.
If you want the Docker service to access the Internet, you must edit the UFW configuration file:
nano /etc/default/ufw
Add the following line to open the network connection for the Docker network:
-A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
In there 172.17.0.0/16
is the subnet of the Docker network. If there are more than one Docker network, add the corresponding lines
2. Using ufw-docker
To both ensure the smooth operation of UFW’s firewall rules and help Docker maintain network management, we will rely on the help of the ufw-docker tool.
The details of how it works are quite confusing, documented on the Github page. For ease of understanding, I just download and use.
sudo wget -O /usr/local/bin/ufw-docker
https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker
If you have edited the file /etc/docker/deamon.json
follow the instructions in method 1, need to delete it and restart Docker
sudo rm /etc/docker/deamon.json
sudo service docker restart
Install ufw-docker with the following command, it will add some rules to the file after.rules
by ufw
ufw-docker install
Then re-enable Smokeping, you will see the port 8888
outside access is now blocked.
To open access to all open ports of Smokeping, I use the following command
ufw-docker allow smokeping
The system will display a notice that the rules are added to ufw as below
allow smokeping 80/tcp smokeping_default
ufw route allow proto tcp from any to 172.18.0.2 port 80 comment allow smokeping 80/tcp smokeping_default
Check again from the external machine, port 8888 is now successfully accessed
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-28 19:27 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up (0.35s latency).
PORT STATE SERVICE
8888/tcp open sun-answerbook
Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
To view more commands of ufw-docker
type
ufw-docker help
Result
Usage:
ufw-docker <list|allow> [docker-instance-id-or-name [port[/tcp|/udp]] [network]]
ufw-docker delete allow [docker-instance-id-or-name [port[/tcp|/udp]] [network]]
ufw-docker service allow <swarm-service-id-or-name <port</tcp|/udp>>>
ufw-docker service delete allow <swarm-service-id-or-name>
ufw-docker <status|install|check|help>
Examples:
ufw-docker help
ufw-docker check # Check the installation of firewall rules
ufw-docker install # Install firewall rules
ufw-docker status
ufw-docker list httpd
ufw-docker allow httpd
ufw-docker allow httpd 80
ufw-docker allow httpd 80/tcp
ufw-docker allow httpd 80/tcp default
ufw-docker delete allow httpd
ufw-docker delete allow httpd 80/tcp
ufw-docker delete allow httpd 80/tcp default
ufw-docker service allow httpd 80/tcp
ufw-docker service delete allow httpd
For example, I can check the rules added by ufw-docker
by command ufw-docker status
the result will appear as below
[ 3] 172.18.0.2 80/tcp ALLOW FWD Anywhere # allow smokeping 80/tcp smokeping_default
It is done. UFW and Docker now work seamlessly together.
If my article brings useful information and knowledge to you, don’t be afraid to invite me a glass of beer to have more motivation to share more. Thank you!