---
title: Packet filtering and firewalls
weight: 10
description: How Docker works with packet filtering, iptables, and firewalls
keywords: network, iptables, firewall
aliases:
- /network/iptables/
- /network/packet-filtering-firewalls/
---
On Linux, Docker creates `iptables` and `ip6tables` rules to implement network
isolation, port publishing and filtering.
Because these rules are required for the correct functioning of Docker bridge
networks, you should not modify the rules created by Docker.
But, if you are running Docker on a host exposed to the internet, you will
probably want to add iptables policies that prevent unauthorized access to
containers or other services running on your host. This page describes how
to achieve that, and the caveats you need to be aware of.
> [!NOTE]
>
> Docker creates `iptables` rules for bridge networks.
>
> No `iptables` rules are created for `ipvlan`, `macvlan` or `host` networking.
## Docker and iptables chains
In the `filter` table, Docker sets the default policy to `DROP`, and creates the
following custom `iptables` chains:
* `DOCKER-USER`
* A placeholder for user-defined rules that will be processed before rules
in the `DOCKER-FORWARD` and `DOCKER` chains.
* `DOCKER-FORWARD`
* The first stage of processing for Docker's networks. Rules that pass packets
that are not related to established connections to the other Docker chains,
as well as rules to accept packets that are part of established connections.
* `DOCKER`
* Rules that determine whether a packet that is not part of an established
connection should be accepted, based on the port forwarding configuration
of running containers.
* `DOCKER-ISOLATION-STAGE-1` and `DOCKER-ISOLATION-STAGE-2`
* Rules to isolate Docker networks from each other.
* `DOCKER-INGRESS`
* Rules related to Swarm networking.
In the `FORWARD` chain, Docker adds rules that unconditionally jump to the
`DOCKER-USER`, `DOCKER-FORWARD` and `DOCKER-INGRESS` chains.
In the `nat` table, Docker creates chain `DOCKER` and adds rules to implement
masquerading and port-mapping.
### Add iptables policies before Docker's rules
Packets that get accepted or rejected by rules in these custom chains will not
be seen by user-defined rules appended to the `FORWARD` chain. So, to add
additional rules to filter these packets, use the `DOCKER-USER` chain.
Rules appended to the `FORWARD` chain will be processed after Docker's rules.
### Match the original IP and ports for requests
When packets arrive to the `DOCKER-USER` chain, they have already passed through
a Destination Network Address Translation (DNAT) filter. That means that the
`iptables` flags you use can only match internal IP addresses and ports of
containers.
If you want to match traffic based on the original IP and port in the network
request, you must use the
[`conntrack` iptables extension](https://ipset.netfilter.org/iptables-extensions.man.html#lbAO).
For example:
```console
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdst 198.51.100.2 --ctorigdstport 80 -j ACCEPT
```
> [!IMPORTANT]
>
> Using the `conntrack` extension may result in degraded performance.
## Port publishing and mapping
By default, for both IPv4 and IPv6, the daemon blocks access to ports that have not
been published. Published container ports are mapped to host IP addresses.
To do this, it uses iptables to perform Network Address Translation (NAT),
Port Address Translation (PAT), and masquerading.
For example, `docker run -p 8080:80 [...]` creates a mapping
between port 8080 on any address on the Docker host, and the container's
port 80. Outgoing connections from the container will masquerade, using
the Docker host's IP address.
### Restrict external connections to containers
By default, all external source IPs are allowed to connect to ports that have
been published to the Docker host's addresses.
To allow only a specific IP or network to access the containers, insert a