DEV Community

Cover image for Announcing udwall: A New Tool for Making UFW and Docker Play Nice With Each Other
Ganesh Kumar
Ganesh Kumar

Posted on

Announcing udwall: A New Tool for Making UFW and Docker Play Nice With Each Other

Many of us believe that the combination of UFW and Docker is the standard stack for deploying applications securely without exposing docker container ports.

Configuring UFW via provisioning tools like Ansible is usually seamless, giving us confidence that our servers are secure.

However, there is a massive, often overlooked security gap in this setup that meanse using UFW with Docker can be dangerous.

Basically, even though your UFW status says "Active" and is set to block all incoming traffic, Docker container ports often remain wide open to the public internet.

At Hexmos, we are dedicated to enhancing the developer experience, having built tools like Livereview and FreeDevtools.

We investigated this critical security flaw and built udwall to finally make UFW and Docker compatible by default.

Understanding Docker Security Flaw

The problem is straightforward but alarming. You set up a server, enable UFW, and set a default deny policy. You feel secure.

Then, you spin up a Docker container and publish a port:

docker run -d -p 8080:80 nginx
Enter fullscreen mode Exit fullscreen mode

You might assume that because you haven't explicitly allowed port 8080 in UFW, it is blocked from the outside world. But it is totaly wrong in actual scenario.

Curl the port 8080 with ip address of your server.

curl http://<server_ip>:8080
Enter fullscreen mode Exit fullscreen mode

You will get response from nginx server.

Docker interacts directly with iptables. When it starts a container, it inserts rules into the PREROUTING chain of the nat table. These rules take precedence over UFW’s standard rules.

Essentially, Docker punches a hole right through your firewall, exposing your internal services to the public internet regardless of your UFW configuration.

image

A Decade of Unsolved Docker Security Flaw

We are not the only ones facing this. This behavior isn't a bug in the traditional sense; it's an architectural conflict that has plagued the DevOps community for years.

It has been almost 10 years since this issue was reported, and it remains a major pain point. A quick look at the community discussions reveals the scale of the confusion:

  • GitHub Issues: The original thread moby/moby#4737 is legendary in the Docker community for its longevity.
  • Docker Forums: Users frequently ask why UFW is seemingly ignored.
  • Stack Overflow: Countless threads, like this one, show developers scrambling to figure out why their ports are exposed.

While there are many suggested workarounds, most involve fragile manual scripts that break the moment a container restarts or Docker updates its iptables rules.

The Existing Solution (and its Drawbacks)

When we first encountered issues, we looked for established solutions. The "gold standard" for years has been a project called ufw-docker by chaifeng.

It is a fantastic utility that solves the underlying routing issue by modifying the iptables configuration to add a custom DOCKER-USER chain. This ensures traffic destined for Docker containers is actually checked by UFW before being allowed through.

However, as we adopted it in production, we ran into significant friction that made automation difficult:

  1. Manual Rule Management: It requires manual steps to manage rules for specific containers. If you are automating infrastructure, these manual interventions are a bottleneck.
  2. Persistence & State Issues: We found that if UFW was disabled or reloaded, the protection for Docker ports could become inconsistent.
  3. Complex Uninstall: Historically, removing the tool was risky. It required manually stripping iptables rules, and doing it wrong could lock you out of your server. > Note: ufw-docker recently added an uninstall command.

Why We Built udwall?

At Hexmos, our internal infrastructure relies heavily on Docker. We needed a solution that was:

  1. Secure by default (fixing the Docker hole).
  2. Native to UFW (no weird hacks).
  3. Easy to automate (for tools like Ansible).

We realized that the existing solutions, while brilliant, were too manual for a modern, fast-paced CI/CD environment.

We started building udwall originally as an internal tool to secure our own servers without the headache of manual rule management.

However, seeing that thousands of developers have been struggling with this exact issue for a decade, we decided to open source it.

udwall is our attempt to make UFW and Docker play nicely together, automatically, so you can trust your firewall again.

udwall builds upon the solid logic of ufw-docker but wraps it in a declarative management system. It is designed to make UFW Docker-compatible with a single command.

What makes udwall different?

  1. Declarative: You define your rules in a Python-based config file (udwall.conf).
  2. Atomic Updates: When you apply changes, udwall handles the logic. It removes old rules that are no longer in your config and applies the new ones.
  3. Safety: It automatically backs up your /etc/ufw and iptables rules before every change, so you can always revert if something goes wrong.
  4. Simplicity: It handles both standard host rules (like SSH) and Docker routing rules in one place.

Getting Started with udwall

The goal of this tool is to minimize friction. Here is how you can secure your Docker host in just a few minutes.

Installation

You can install it via a single command which sets up the tool and dependencies:

curl -fsSL https://raw.githubusercontent.com/HexmosTech/udwall/main/install.sh | sudo bash
Enter fullscreen mode Exit fullscreen mode

The Configuration

Once installed, you manage everything via /etc/udwall/udwall.conf. If you already have UFW rules running, you can generate a config file based on your current state:

sudo udwall --create
Enter fullscreen mode Exit fullscreen mode

Or, you can write one from scratch. Here is what the configuration looks like. It is clean, readable, and Python-based:

# udwall.conf
rules = [
    # Standard Host Rule: Allow SSH from anywhere
    {'from': 'any', 'connectionType': 'tcp', 'to': 'OpenSSH', 'isDockerServed': False, 'isEnabled': True},

    # Standard Host Rule: Allow HTTP/HTTPS to the host
    {'from': 'any', 'connectionType': 'tcp', 'to': 80, 'isDockerServed': False, 'isEnabled': True},
    {'from': 'any', 'connectionType': 'tcp', 'to': 443, 'isDockerServed': False, 'isEnabled': True},

    # Docker Rule: Allow traffic to a container on port 8080 ONLY from a specific IP
    {'from': '192.168.1.100', 'connectionType': 'tcp', 'to': 8080, 'isDockerServed': True, 'isEnabled': True},
]
Enter fullscreen mode Exit fullscreen mode

Applying Changes

Once your file is ready, you apply the configuration. This step backs up your current state and synchronizes the firewall with your file:

sudo udwall --apply
Enter fullscreen mode Exit fullscreen mode

Finally, if this is your first time running it, you enable the Docker-UFW integration (this sets up the iptables magic):

sudo udwall --enable
Enter fullscreen mode Exit fullscreen mode

Conclusion

Running Docker and UFW on the same server shouldn't mean sacrificing security for convenience. While Docker's networking is powerful, its ability to bypass UFW is a serious risk that many users don't discover until it is too late.

udwall attempts to bridge that gap by combining the security fixes of ufw-docker with the ease of declarative configuration management.

It is open source, and We would love for you to try it out and let us know what you think.

Check out the repository here:
https://github.com/HexmosTech/udwall


FreeDevTools

We’ve been building for FreeDevTools.

A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction when searching for tools and materials.

Any feedback or contributions are welcome!

It’s online, open-source, and ready for anyone to use.

👉 Check it out: FreeDevTools

⭐ Star it on GitHub: freedevtools

Top comments (0)