Docker gateway address blocked for https

Your question

I am running the stalwart container image, v0.16.8. My setup is:

  • docker-ce on Debian 13
  • Server sits behind NAT, which all required ports forwarded to it

TCP 443 is already used by something else, so I resorted to TCP 10443. The TLS cert is manually configured and that part is fine.
I am managing the container using a systemd service unit file which looks like this:

[Unit]
Description=Stalwart Mail Server Container
After=docker.service network-online.target
Requires=docker.service

[Service]
Restart=always
ExecStartPre=-/usr/bin/docker stop stalwart
ExecStartPre=-/usr/bin/docker rm stalwart

ExecStart=/usr/bin/docker run --name stalwart \
    --log-driver "journald" \
    --log-opt tag="{{.Name}}" \
    -e STALWART_PUBLIC_URL="https://foobarz.cajones.org:10443" \
    -p 192.168.178.3:25:25 \
    -p 2a10:3781:442a:1::3:25:25 \
    -p 993:993 \
    -p 465:465 \
    -p 9090:8080 \
    -p 10443:443 \
    -v /opt/stalwart/config:/etc/stalwart \
    -v /opt/stalwart/data:/var/lib/stalwart \
    stalwartlabs/stalwart:v0.16.8

ExecStop=/usr/bin/docker stop stalwart

[Install]
WantedBy=multi-user.target

This worked OK but recently all HTTPS traffic get blocked:

2026-06-13T08:47:40Z INFO Blocked IP address (security.ip-blocked)
>-listenerId = "https"
>-localPort = 443
>-remoteIp = 172.17.0.1
>-remotePort = 44718

The remoteIp address is the docker’s gateway. Which is weird, because for other
listenerIds the real IP address is listed at that place. For example:

2026-06-13T08:47:00Z INFO Authentication not allowed (smtp.auth-not-allowed)
>-listenerId = "smtp"
>-localPort = 25
>-remoteIp = 158.94.208.66
>-remotePort = 21397

Looking through the docs, the first thing that comes to mind is some Proxy Protocol setting.
But, I’m not using any proxy. All ports are publicly exposed.

I’m guessing something needs to be configured either on docker, or on stalwart?

PS, in case you wonder why port 25 isn’t just mapped with -p 25:25: the server still runs postfix which listens on localhost.

The root cause is exactly what the FAQ describes: when Docker port-maps 10443:443, all HTTPS connections reach Stalwart with the Docker bridge gateway IP (172.17.0.1) as the source, not the real client IP. Stalwart’s auto-ban eventually blocks that gateway address, which then blocks every HTTPS user at once. The SMTP listener works correctly because you mapped it to a specific host IP (-p 192.168.178.3:25:25), which routes traffic differently.

You have two options to fix this:


Option A (recommended) – Add 172.17.0.1 to the AllowedIPs list

In the WebUI go to Settings › Security › Allowed IPs and add 172.17.0.1 (or 172.17.0.0/16 if your bridge subnet ever changes). This stops auto-ban from ever blocking the gateway. Real IP visibility will still be missing from logs, but connections won’t be dropped.

First, also remove the existing block on 172.17.0.1 from Settings › Security › Blocked IPs.


Option B (better for logging/security) – Use Docker --network host or --ip-forward tricks to preserve real IPs

Because Docker’s userland proxy is in the path for 10443:443, the source IP is NAT’d to the gateway. The clean Docker-native fix is to publish the port with the host’s IP directly, or switch to host networking. If you want to keep bridge networking, you can enable Docker’s --userland-proxy=false in the Docker daemon config (/etc/docker/daemon.json):

{ "userland-proxy": false }

With userland-proxy=false, Docker uses iptables rules directly and the real client IP is preserved in the socket – so Stalwart sees the actual remote address for the HTTPS listener, just like it does for SMTP.


The FAQ entry that describes this exact scenario is at: FAQ | Stalwart

And the AllowedIPs docs are at: General | Stalwart

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.