MONERO.LOVE / GUIDES / POST MORTEM

Why P2Pool kept banning our miners

Our P2Pool post mortem explains how rootless Docker gave miners one shared IP, why a first fix failed, and how slirp4netns restored client addresses.

Published · 5 min read

On October 19, 2026, our miners were reporting “Banned,” several at the same time. P2Pool was still running, and its container looked healthy.

The problem was in the network path. Rootless Docker was presenting unrelated clients to P2Pool under one gateway address. When P2Pool banned that address, every miner behind it was affected.

We fixed the shared-address problem by changing Docker’s port driver to preserve incoming client IPs.

Three mining computers share one gateway and are blocked together before reaching the pool server.

Eight P2Pool bans against one address

The investigation found eight bans against 172.28.1.1 during the reviewed 24 hours. Each lasted 600 seconds. Those timestamps matched eight periods of rejected shares across the miners.

Sampled XMRig logs explicitly reported “Banned.” Even the miner running on the pool host was affected.

Meanwhile, P2Pool had continued running without a container restart. That explained why service health and mining health disagreed. The process was available, but it was refusing clients.

The repeated address was the clue. 172.28.1.1 was the Docker bridge gateway, which had become the apparent source of connections from different machines.

Rejected-share percentages across six monitored miners, with eight recorded gateway ban intervals shaded orange.

Rejected-share percentages rose together across six monitored miners during the eight gateway bans. Orange bands mark the 600-second bans recorded in P2Pool logs. The lines use 15-minute rolling rates, so peaks extend beyond the ban intervals. All times are UTC. This chart was plotted from historical metrics retrieved through Grafana.

How rootless Docker spread one ban across the miners

Stratum is the connection miners use to receive jobs and submit work to the pool. P2Pool’s Stratum server includes client-banning logic. When the network presents several clients under one address, an address-based ban can affect all of them. P2Pool Stratum source

Our rootless Docker configuration used the builtin port driver with a forwarding setup that lost the original client addresses. Docker documents this source-IP limitation and supported ways to preserve those addresses. Docker rootless networking documentation

The logs established why the bans spread across the fleet. They did not establish what triggered the first ban. At the available logging level, we could see the resulting ban without enough detail to identify the client behavior behind it.

There was no evidence to call it an attack or blame a particular miner or monitoring probe.

The first fix hit a host problem

We first tried disabling Docker’s userland-proxy, a documented option for source-IP propagation with newer RootlessKit versions. That approach can require the br_netfilter kernel module. Docker configuration requirements

The running kernel and installed module tree did not match. The module could not load, and Docker failed to restart.

Rolling back the configuration did not immediately restore the stack. Docker listed existing Compose networks, but attempts to attach containers failed because their network IDs could not be found.

We backed up the network definitions, recreated the affected networks from the existing Compose configuration, and recreated containers that referenced stale network IDs. The original volumes were retained. Monero resumed from its existing blockchain database without a resync.

Mining was interrupted during that recovery. The kernel/module mismatch still required planned maintenance after the repair.

The slirp4netns configuration that worked

The successful change selected the slirp4netns port driver through a persistent override for the rootless Docker user service:

[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns"

We saved it under:

~/.config/systemd/user/docker.service.d/foo-source-ip.conf

Then reloaded the user service configuration and restarted Docker:

systemctl --user daemon-reload
systemctl --user restart docker

These commands run as the account that owns the rootless Docker service. Restarting that daemon affects its entire container stack.

This was the override used on our existing setup. Other installations should check their network-driver configuration too. Docker documents the slirp4netns network and port-driver combination for source-IP propagation. Docker driver configuration

The original userland-proxy behavior was restored. P2Pool’s ban protections and rejection thresholds stayed enabled.

Checking that mining recovered

A running container was not enough to verify this repair. We checked the addresses visible to the services and whether miners were submitting accepted work.

After recovery:

  • Real external source IPs were visible on both Stratum and Monero RPC connections.
  • All eleven previously running containers were back.
  • Monero was synchronized, and P2Pool reported synchronized status.
  • P2Pool was delivering jobs to nine clients.
  • All six monitored miners showed increasing accepted-share counters during the final two-minute observation window.

Accepted shares per minute for six monitored miners around the repair, with the documented recovery time marked by a dashed line.

Accepted-share rates around the October 19 repair. The dashed line marks the approximately 21:28 UTC recovery time recorded in the repair log. These five-minute rolling rates smooth the restart interruption and show short-term accepted work after recovery. All times are UTC. This chart was plotted from historical metrics retrieved through Grafana.

Local miner logs and an XMRig API check supplied additional confirmation. One miner could not be reached directly over SSH, so its recovery was confirmed through central telemetry.

Accepted shares resumed at approximately 21:28 UTC on October 19.

What the repair established and what remains unknown

Preserving client addresses removed the Docker gateway as a shared ban identity. Machines behind the same upstream NAT can still share a public IP, and the original ban trigger remained unidentified.

The immediate checks confirmed recovery. They did not establish a full day without recurrence.

The useful diagnostic was comparing the address P2Pool banned with the addresses it saw. Several independent miners had been reduced to one apparent client. Fixing that network behavior allowed P2Pool to apply its protections without taking unrelated miners down together.

Yet another reason not to Docker.

Support Monero Love

Help keep the public nodes and packages running. Send any amount of XMR.

89hGTKxRVA3AUeKAbCRBt5TMSzq3MQZooNNsezCpNFjp2oeJPRx8AJeGKA8ziHZNqab78f4Vr1ntxhPDxX5298nnGZjHkhm