Skip to content

Commit 2b18134

Browse files
committed
blog: new post
1 parent ad8e5d2 commit 2b18134

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
layout: post
3+
title: "Strict Forward Ports"
4+
section: Blog
5+
date: 2024-11-06T12:00:00
6+
author: Eric Garver
7+
---
8+
9+
## Introduction
10+
11+
When Docker (or Podman) publishes container ports, the published ports
12+
are honored by firewalld. In some cases, users want firewalld to be
13+
strict and block those ports. This has been outlined in a [previous post]({% post_url /blog/2024-03-22-strictly-filtering-docker-containers %}).
14+
15+
Firewalld now supports `StrictForwardPorts` which allows users to block
16+
published container ports.
17+
18+
## Configuration
19+
20+
The behavior is configurable by changing `StrictForwardPorts` in
21+
`/etc/firewalld/firewalld.conf`.
22+
23+
`/etc/firewalld/firewalld.conf`:
24+
```
25+
# StrictForwardPorts
26+
# If set to yes, the generated destination NAT (DNAT) rules will NOT accept
27+
# traffic that was DNAT'd by other entities, e.g. docker. Firewalld will be
28+
# strict and not allow published container ports until they're explicitly
29+
# allowed via firewalld.
30+
# If set to no, then docker (and podman) integrates seamlessly with firewalld.
31+
# Published container ports are implicitly allowed.
32+
# Defaults to "no".
33+
StrictForwardPorts=no
34+
```
35+
36+
## Forwarding Ports with StrictForwardPorts=yes
37+
38+
When `StrictForwardPorts=yes`, the user must explicitly forward ports to
39+
containers using firewalld. All `--published` ports will be blocked.
40+
41+
Since the containers IP address will change every time the container is
42+
started, a forward port should be added at runtime. Luckily docker
43+
provides a way to get the container's address programmatically.
44+
45+
Example to forward `8080` to a container's port `80`.
46+
47+
```
48+
# CONTAINER_IP=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}} <container_name>)
49+
# firewall-cmd --zone public --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=${CONTAINER_IP}
50+
```
51+
52+
## What it Looks Like
53+
54+
This feature works by altering the underlying firewall rules that accept
55+
DNAT'd connections.
56+
57+
With `StrictForwardPorts=no`, there is a top-level and generic accept of
58+
all DNAT'd connections. This is the rule that would allow `--published`
59+
ports.
60+
61+
```
62+
table inet firewalld {
63+
chain filter_FORWARD {
64+
ct state established,related accept
65+
ct status dnat accept <--- THIS RULE
66+
[..]
67+
}
68+
}
69+
```
70+
71+
With `StrictForwardPorts=yes`, the generic is replaced by a rule per
72+
forward-port that accepts _only_ those ports for which firewalld has
73+
explicit configuration. It block all other DNAT'd traffic.
74+
75+
```
76+
table inet firewalld {
77+
chain filter_FORWARD {
78+
ct state established,related accept
79+
ct status dnat jump filter_FORWARD_dnat <--- CHANGED RULE
80+
[..]
81+
}
82+
}
83+
84+
table inet firewalld {
85+
chain filter_FORWARD_dnat {
86+
ct original proto-dst 8080 accept <--- ONE PER forward-port
87+
reject with icmpx admin-prohibited
88+
}
89+
}
90+
```
91+
92+
## Conclusion
93+
94+
This new configuration knob gives users more control over container
95+
traffic. The default behavior has not changed. That is, firewalld and
96+
docker (podman) integration is still seamless by default. Users that
97+
want strict control now have a configuration option to get the behavior
98+
they desire.
99+
100+
## Bugs Referencing This Topic
101+
102+
This topic has been discussed and referenced in numerous reports.
103+
104+
- [How to manage docker exposed port by firewall-cmd?](https://github.com/firewalld/firewalld/issues/869)
105+
- [Podman and Firewalld: Port Forwarding through the Firewall](https://github.com/firewalld/firewalld/issues/1380)

0 commit comments

Comments
 (0)