Skip to content

Commit f7e847c

Browse files
committed
Split packet filtering / port publishing / iptables
With nftables on the way - refer to "firewall" instead of "iptables" in the top-level description of packet-filtering-firewalls, move out the iptables specifics, and port-publishing (which applies to both iptables and nftables). Signed-off-by: Rob Murray <[email protected]>
1 parent 555675e commit f7e847c

File tree

4 files changed

+459
-404
lines changed

4 files changed

+459
-404
lines changed

content/manuals/engine/network/_index.md

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -141,45 +141,10 @@ networks.
141141

142142
Use the `--publish` or `-p` flag to make a port available outside the host,
143143
and to containers in other bridge networks.
144-
This creates a firewall rule in the host,
145-
mapping a container port to a port on the Docker host to the outside world.
146-
Here are some examples:
147-
148-
| Flag value | Description |
149-
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
150-
| `-p 8080:80` | Map port `8080` on the Docker host to TCP port `80` in the container. |
151-
| `-p 192.168.1.100:8080:80` | Map port `8080` on the Docker host IP `192.168.1.100` to TCP port `80` in the container. |
152-
| `-p 8080:80/udp` | Map port `8080` on the Docker host to UDP port `80` in the container. |
153-
| `-p 8080:80/tcp -p 8080:80/udp` | Map TCP port `8080` on the Docker host to TCP port `80` in the container, and map UDP port `8080` on the Docker host to UDP port `80` in the container. |
154-
155-
> [!IMPORTANT]
156-
>
157-
> Publishing container ports is insecure by default. Meaning, when you publish
158-
> a container's ports it becomes available not only to the Docker host, but to
159-
> the outside world as well.
160-
>
161-
> If you include the localhost IP address (`127.0.0.1`, or `::1`) with the
162-
> publish flag, only the Docker host and its containers can access the
163-
> published container port.
164-
>
165-
> ```console
166-
> $ docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' nginx
167-
> ```
168-
>
169-
> > [!WARNING]
170-
> >
171-
> > In releases older than 28.0.0, hosts within the same L2 segment (for example,
172-
> > hosts connected to the same network switch) can reach ports published to localhost.
173-
> > For more information, see
174-
> > [moby/moby#45610](https://github.com/moby/moby/issues/45610)
175-
176-
Ports on the host's IPv6 addresses will map to the container's IPv4 address
177-
if no host IP is given in a port mapping, the bridge network is IPv4-only,
178-
and `--userland-proxy=true` (default).
179144

180145
For more information about port mapping, including how to disable it and use
181146
direct routing to containers, see
182-
[packet filtering and firewalls](./packet-filtering-firewalls.md).
147+
[port publishing](./port-publishing.md).
183148

184149
## IP address and hostname
185150

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
title: Docker with iptables
3+
weight: 10
4+
description: How Docker works with iptables
5+
keywords: network, iptables, firewall
6+
---
7+
8+
Docker creates iptables rules in the host's network namespace for bridge
9+
networks. For bridge and other network types, iptables rules for DNS are
10+
also created in the container's network namespace.
11+
12+
Creation of iptables rules can be disabled using daemon options `iptables`
13+
and `ip6tables`, see [Prevent Docker from manipulating firewall rules](packet-filtering-firewalls.md#prevent-docker-from-manipulating-firewall-rules).
14+
However, this is not recommended for most users as it will likely break
15+
container networking.
16+
17+
### Docker and iptables chains
18+
19+
To support bridge and overlay networks, Docker creates the following custom
20+
`iptables` chains:
21+
22+
* `DOCKER-USER`
23+
* A placeholder for user-defined rules that will be processed before rules
24+
in the `DOCKER-FORWARD` and `DOCKER` chains.
25+
* `DOCKER-FORWARD`
26+
* The first stage of processing for Docker's networks. Rules that pass packets
27+
that are not related to established connections to the other Docker chains,
28+
as well as rules to accept packets that are part of established connections.
29+
* `DOCKER`, `DOCKER-BRIDGE`, `DOCKER-INTERNAL`
30+
* Rules that determine whether a packet that is not part of an established
31+
connection should be accepted, based on the port forwarding configuration
32+
of running containers.
33+
* `DOCKER-CT`
34+
* Per-bridge connection tracking rules.
35+
* `DOCKER-INGRESS`
36+
* Rules related to Swarm networking.
37+
38+
In the `FORWARD` chain, Docker adds rules that unconditionally jump to the
39+
`DOCKER-USER`, `DOCKER-FORWARD` and `DOCKER-INGRESS` chains.
40+
41+
In the `nat` table, Docker creates chain `DOCKER` and adds rules to implement
42+
masquerading and port-mapping.
43+
44+
Docker requires IP Forwarding to be enabled on the host for its default
45+
bridge network configuration. If it enables IP Forwarding, it also sets the
46+
default policy of the iptables `FORWARD` chain in the `filter` table to `DROP`.
47+
48+
### Add iptables policies before Docker's rules
49+
50+
Packets that get accepted or rejected by rules in these custom chains will not
51+
be seen by user-defined rules appended to the `FORWARD` chain. So, to add
52+
additional rules to filter these packets, use the `DOCKER-USER` chain.
53+
54+
Rules appended to the `FORWARD` chain will be processed after Docker's rules.
55+
56+
### Match the original IP and ports for requests
57+
58+
When packets arrive to the `DOCKER-USER` chain, they have already passed through
59+
a Destination Network Address Translation (DNAT) filter. That means that the
60+
`iptables` flags you use can only match internal IP addresses and ports of
61+
containers.
62+
63+
If you want to match traffic based on the original IP and port in the network
64+
request, you must use the
65+
[`conntrack` iptables extension](https://ipset.netfilter.org/iptables-extensions.man.html#lbAO).
66+
For example:
67+
68+
```console
69+
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
70+
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdst 198.51.100.2 --ctorigdstport 80 -j ACCEPT
71+
```
72+
73+
> [!IMPORTANT]
74+
>
75+
> Using the `conntrack` extension may result in degraded performance.
76+
77+
### Allow forwarding between host interfaces
78+
79+
If Docker has set the default policy of the `FORWARD` chain in the `filter`
80+
table to `DROP`, a rule in `DOCKER-USER` can be used to allow forwarding
81+
between host interfaces. For example:
82+
83+
```console
84+
$ iptables -I DOCKER-USER -i src_if -o dst_if -j ACCEPT
85+
```
86+
87+
### Restrict external connections to containers
88+
89+
By default, all external source IPs are allowed to connect to ports that have
90+
been published to the Docker host's addresses.
91+
92+
To allow only a specific IP or network to access the containers, insert a
93+
negated rule at the top of the `DOCKER-USER` filter chain. For example, the
94+
following rule drops packets from all IP addresses except `192.0.2.2`:
95+
96+
```console
97+
$ iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.2 -j DROP
98+
```
99+
100+
You will need to change `ext_if` to correspond with your
101+
host's actual external interface. You could instead allow connections from a
102+
source subnet. The following rule only allows access from the subnet `192.0.2.0/24`:
103+
104+
```console
105+
$ iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.0/24 -j DROP
106+
```
107+
108+
Finally, you can specify a range of IP addresses to accept using `--src-range`
109+
(Remember to also add `-m iprange` when using `--src-range` or `--dst-range`):
110+
111+
```console
112+
$ iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.0.2.1-192.0.2.3 -j DROP
113+
```
114+
115+
You can combine `-s` or `--src-range` with `-d` or `--dst-range` to control both
116+
the source and destination. For instance, if the Docker host has addresses
117+
`2001:db8:1111::2` and `2001:db8:2222::2`, you can make rules specific to
118+
`2001:db8:1111::2` and leave `2001:db8:2222::2` open.
119+
120+
You may need to allow responses from servers outside the permitted external address
121+
ranges. For example, containers may send DNS or HTTP requests to hosts that are
122+
not allowed to access the container's services. The following rule accepts any
123+
incoming or outgoing packet belonging to a flow that has already been accepted
124+
by other rules. It must be placed before `DROP` rules that restrict access from
125+
external address ranges.
126+
127+
```console
128+
$ iptables -I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT
129+
```
130+
131+
For more detailed information about iptables configuration and advanced usage,
132+
refer to the [Netfilter.org HOWTO](https://www.netfilter.org/documentation/HOWTO/NAT-HOWTO.html).

0 commit comments

Comments
 (0)