InfraFenceInfraFence

Live Security Operations

Get started

Docker host security

Last updated:

A Docker host is easy to leave open by mistake. A port published by a container is not filtered by your INPUT rules, so ufw or firewalld can say a port is closed while the internet still reaches the container behind it. And the web traffic of your sites often lives in container output, not in a log file on the host.

This page explains what Docker does to the firewall, and how the InfraFence agent protects the host and its containers. The Docker facts come from Docker's documentation, as of November 2026.

Published ports skip your INPUT rules

Traffic to a published container port is forwarded to the container, not delivered to the host, so it goes through the FORWARD path. Docker's documentation says it plainly for ufw: packets are routed before the firewall rules can be applied. Docker leaves one chain for your own rules, DOCKER-USER, which it evaluates before its own.

So a firewall that only writes INPUT rules protects the host's own services, not the containers. A database container started with -p 3306:3306 is open to the world even if ufw denies 3306.

How the agent handles Docker's firewall

  • Bans reach the containers. When Docker is present, the agent jumps to its own INFRAFENCE chain from DOCKER-USER as well as from INPUT, and keeps that jump first. Bans, threat lists and country blocks therefore apply to published container ports too. If a Docker restart or a firewall reload removes the jump, the agent puts it back.
  • Exposed database ports can be closed, containers included. A database, cache or admin port open to the internet (MySQL, PostgreSQL, Redis, MongoDB, Elasticsearch, the Docker API and the others the agent knows) can be closed from the dashboard. The rule matches the port the client asked for (--ctorigdstport), which is still right after Docker's address translation, on IPv4 and IPv6. Connections opened before the port closed are dropped too, with the conntrack tool when it is installed.
  • Containers and your network keep access. Loopback and private addresses, the Docker networks among them, are never affected by a closed port, nor is anything on your allow list.
  • It does not cut off regular clients. The agent counts who connects to these ports, from the socket table and, for published container ports, the conntrack table. While an address seen on 3 of the last 7 days is not on the allow list, the port is not closed (Regular clients).
  • Every change is checked. The agent never closes SSH, 80, 443 or a port a web server listens on, and undoes a change if SSH or a site stops answering.

Its rules live in its own chains, and it never edits Docker's chains or yours. If the system's iptables switched to the nf_tables backend while Docker still runs on the legacy one, the agent keeps its jump where Docker's chain is until Docker restarts.

Two setups have no DOCKER-USER chain, so the agent cannot reach published ports there: Docker started with "iptables": false, and Docker's nftables backend, experimental since Docker 29. Bans still apply to the host's own services through INPUT.

Web traffic in containers

From agent 1.0.42 the web firewall reads, through the Docker or Podman socket and read only:

  • the access logs of reverse proxies: Traefik (JSON or its default format, from its log file or its output), Caddy (JSON) and HAProxy;
  • the output of web servers in containers (nginx, OpenResty, Apache httpd, WordPress, php:*-apache and LiteSpeed images), when they publish port 80 or 443 or sit behind a proxy whose log is not read.

Behind a proxy container, the visitor's address is taken from X-Forwarded-For only for requests that come from the proxy itself. Behind Cloudflare, the visitor is taken from CF-Connecting-IP only for requests from Cloudflare's ranges, and a Cloudflare address is never banned. The server page shows each log read under Network › Web attack detection, or why none is read. Details: Access logs of reverse proxies and containers.

Three labels let you steer it per container: infrafence.monitor (true or false), infrafence.log-path (host paths of its logs) and infrafence.domain (its domains). From agent 1.0.35 the agent also lists the domains behind Traefik and Caddy from their labels, so each site can get the trust badge, verified with a DNS TXT record.

Install: on the host, or as a container

On the host (recommended): the install command at the end of this page, as root. The agent then finds web containers and reads their labels with the docker command-line tool. Run the read-only check first if you like:

curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --dry-run

As a container: the image ghcr.io/infrafence/infrafence-agent (also on Docker Hub as infrafence/infrafence-agent) is multi-architecture and signed with cosign. It needs the host's network and process namespace, privileges to manage the host firewall, and /var/log and the Docker socket read only:

docker run -d --name infrafence-agent --restart unless-stopped \
  --privileged --network host --pid host \
  -v /var/log:/var/log:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v infrafence-config:/etc/infrafence \
  -e INFRAFENCE_TOKEN=<TOKEN> \
  ghcr.io/infrafence/infrafence-agent:latest

The image has no docker command-line tool, so inside the container point the agent to file logs with WEB_LOG_PATH; proxy logs and container output are still read through the socket. Docker Compose works the same way, and a Swarm stack file runs one agent per node. Every variable and mount is in Docker.

What it does not cover

  • Traffic between containers on the same host: it never leaves the Docker networks, and private addresses are never banned.
  • Container images: the vulnerability check covers the host's installed packages, not what is inside your images.
  • Bans, the whitelist and country blocks apply to IPv4; closed ports apply to IPv4 and IPv6.

For a cluster rather than one host, see Kubernetes node intrusion detection. For a Coolify server, see Securing a Coolify server.

Try it free on 1 server

Starter gives one server full protection, free and with no credit card.

  1. 01

    Create a free account, then open Servers › Add server to get your install token. It is valid for one hour.

    Create the token
  2. 02

    Then run this as root on the server:

    curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>