Skip to content

Commit c1295bb

Browse files
committed
blog: Strictly Filtering Docker Containers
1 parent ad40dec commit c1295bb

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
layout: post
3+
title: "Strict Filtering of Docker Containers"
4+
section: Blog
5+
date: 2024-04-03T16:00:00
6+
author: Eric Garver
7+
---
8+
9+
## Introduction
10+
11+
Docker supports publishing ports for a container. This allows external
12+
access to the container. When firewalld is running these published ports
13+
are honored and a hole is opened in firewalld. For most users, e.g.
14+
workstations, this a good thing as docker works transparently.
15+
16+
For some users, this is not expected. They want firewalld to be strict.
17+
They want to only allow traffic explicitly via firewalld. Fortunately
18+
this can be achieve with some configuration.
19+
20+
## Docker Configuration
21+
22+
To have full control of docker containers via firewalld one must first
23+
disable iptables in docker.
24+
25+
This can be done by adding `iptables: false` to the daemon
26+
configuration.
27+
28+
```
29+
# cat /etc/docker/daemon.json
30+
{
31+
"iptables": false
32+
}
33+
```
34+
35+
Then the host must be rebooted. Restarting Docker is not enough to clean
36+
up all the pre-existing iptables rules.
37+
38+
```
39+
# reboot
40+
```
41+
42+
Now the containers won't have any iptables firewall rules automatically
43+
created.
44+
45+
## Verify Docker Does Not Install iptables rules
46+
47+
This is optional and just for illustration purposes.
48+
49+
After the reboot starting a docker container will cause containers to
50+
not have internet access. This means that docker is not setting up
51+
iptables rules.
52+
53+
```
54+
# docker run -it --rm debian:stable
55+
56+
# apt update
57+
Ign:1 http://deb.debian.org/debian stable InRelease
58+
Ign:2 http://deb.debian.org/debian stable-updates InRelease
59+
Ign:3 http://deb.debian.org/debian-security stable-security InRelease
60+
0% [Connecting to deb.debian.org]
61+
```
62+
63+
In the next step this will be fixed by doing the networking natively in
64+
firewalld. Restarting the container is not necessary.
65+
66+
## Firewalld Configuration
67+
68+
Now setup firewalld to natively perform all networking for docker with
69+
the following configuration.
70+
71+
```
72+
firewall-cmd --permanent --zone docker --add-source 172.17.0.1/16
73+
74+
firewall-cmd --permanent --new-policy dockerToWorld
75+
firewall-cmd --permanent --policy dockerToWorld --add-ingress-zone docker
76+
firewall-cmd --permanent --policy dockerToWorld --add-egress-zone ANY
77+
firewall-cmd --permanent --policy dockerToWorld --set-target ACCEPT
78+
firewall-cmd --permanent --policy dockerToWorld --add-masquerade
79+
80+
firewall-cmd --reload
81+
```
82+
83+
This creates a policy, `dockerToWorld`, to give the container internet
84+
access. Note that the `--add-source` above assumes the default address
85+
range used by docker.
86+
87+
### Verify Firewalld Rules
88+
89+
After the firewalld rules are created verify the container has internet
90+
access.
91+
92+
```
93+
# apt update
94+
Get:1 http://deb.debian.org/debian stable InRelease [151 kB]
95+
Get:2 http://deb.debian.org/debian stable-updates InRelease [55.4 kB]
96+
Get:3 http://deb.debian.org/debian-security stable-security InRelease [48.0 kB]
97+
Get:4 http://deb.debian.org/debian stable/main amd64 Packages [8786 kB]
98+
Get:5 http://deb.debian.org/debian stable-updates/main amd64 Packages [12.7 kB]
99+
Get:6 http://deb.debian.org/debian-security stable-security/main amd64 Packages [150 kB]
100+
Fetched 9203 kB in 1s (7189 kB/s)
101+
Reading package lists... Done
102+
Building dependency tree... Done
103+
Reading state information... Done
104+
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
105+
```
106+
107+
### Adding Firewalld Native Forward Ports
108+
109+
Since docker is no longer using iptables ports published with
110+
`--publish` will no longer work. It's simply ignored. Ports must be
111+
exposed with firewalld.
112+
113+
The first step is to create another policy, `dockerFwdPort`, to allow
114+
external access to the container.
115+
116+
```
117+
firewall-cmd --permanent --new-policy dockerFwdPort
118+
firewall-cmd --permanent --policy dockerFwdPort --add-ingress-zone ANY
119+
firewall-cmd --permanent --policy dockerFwdPort --add-egress-zone HOST
120+
```
121+
122+
Note: Older firewalld versions (before v2.0.z) require using
123+
`egress-zone=ANY`.
124+
125+
To add port forwarding (equivalent of docker --publish) to a specific
126+
container use `--add-forward-port` in the `dockerFwdPort` policy. This
127+
example forwards port `8080` to to `80`. Note that the containers IP
128+
address must be known.
129+
130+
```
131+
firewall-cmd --permanent --policy dockerFwdPort --add-forward-port port=8080:proto=tcp:toport=80:toaddr=172.17.0.2
132+
```
133+
134+
Lastly reload the firewall.
135+
136+
```
137+
firewall-cmd --reload
138+
```
139+
140+
## Results
141+
142+
This small amount of configuration allows firewalld to strictly filter
143+
docker container network traffic by doing all the networking natively in
144+
firewalld.
145+
146+
## A Note About Podman
147+
148+
A similar configuration can be done with Podman. Podman 4.x can use
149+
environment variable `NETAVARK_FW=none` to disable the network plugin.
150+
Podman 5.x will have a `containers.conf` for it.
151+
152+
The firewalld configuration is the same except that the `podman` zone is
153+
used instead of the `docker` zone.
154+
155+
## Bugs Referencing This Topic
156+
157+
This topic has been discussed and referenced in numerous reports.
158+
159+
- [How to manage docker exposed port by firewall-cmd?](https://github.com/firewalld/firewalld/issues/869)
160+
- [Conflict with CNI DNAT rule and top-level accept of DNAT'd packets](https://github.com/firewalld/firewalld/issues/556)
161+
- [podman-quadlet loads NAT rules that bypass firewall restrictions](https://issues.redhat.com/browse/RHEL-26522)

0 commit comments

Comments
 (0)