A validator that can be found can be attacked. On a proof-of-stake network, your validator's job is to sign blocks on time, every time. An attacker's cheapest path to disrupting that isn't cryptography. It's a volumetric DDoS against the validator's IP address. If your consensus node is directly reachable from the public internet, its address eventually leaks through the peer-exchange gossip layer, and from that moment your liveness depends on how much traffic someone is willing to buy.
The industry answer is sentry node architecture, first formalized in the Tendermint/CometBFT ecosystem. This post walks through the exact topology we run in production at Helios, the configuration that makes it work, and the operational details that most write-ups skip.
The core idea
Instead of connecting the validator to the open peer-to-peer network, you place a ring of disposable full nodes, called sentries, between the validator and everyone else:
┌───────────────────────────── public internet ─────────────────────────────┐
peers ↔ ┌──────────┐ ┌──────────┐ ┌──────────┐ ↔ peers
│ sentry-1 │ │ sentry-2 │ │ sentry-3 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
─────────────────────┼──────────────┼──────────────┼──── private network ─────
└──────────┬───┴──────────────┘
┌─────┴──────┐
│ VALIDATOR │ ← no public IP, no PEX
└─────┬──────┘
┌─────┴──────┐
│ HSM signer │ ← separate host, see our key custody post
└────────────┘
The validator holds exactly one kind of connection: private, persistent peering to its own sentries over a VPN or private VLAN. It has no public IP. It does not participate in peer exchange. As far as the network can observe, the validator does not exist. Blocks are simply signed, and the signatures appear via the sentries.
The configuration that matters
Three settings in the CometBFT config.toml do the heavy lifting. On the validator:
# validator config.toml, [p2p] section
pex = false # never gossip or learn peers
persistent_peers = "[email protected]:26656,[email protected]:26656,[email protected]:26656"
addr_book_strict = false # allow private-range addresses
And on each sentry:
# sentry config.toml, [p2p] section
pex = true
private_peer_ids = "<validator-node-id>" # NEVER gossip the validator
unconditional_peer_ids = "<validator-node-id>" # never evict it under peer pressure
persistent_peers = "<validator>,<other-sentries>"
The two lines people forget are private_peer_ids and unconditional_peer_ids. The first prevents the sentry from ever advertising the validator's address through PEX. Miss it, and your "hidden" validator leaks within hours. The second guarantees the sentry never drops the validator connection when its peer slots fill up during a gossip storm. Miss it, and your validator can be silently partitioned at the worst possible moment.
Field note: after a chain upgrade, always re-verify private_peer_ids. Node IDs change if the node key is regenerated during migration, and a stale ID means the sentry is happily gossiping your validator's address while you sleep.
Why it defeats DDoS economically
Sentries turn a targeted attack into an economics problem that favors the defender:
- Sentries are cattle, not pets. They hold no keys and no state that matters. If one is saturated, we destroy it and provision a replacement with a fresh IP in minutes, fully automated.
- The attack surface rotates. We cycle sentry IPs on a schedule, so reconnaissance data goes stale faster than it can be weaponized.
- Geographic spread raises the price. Our sentries sit in independent facilities in Central Europe and Asia. Saturating all of them simultaneously means renting multi-region attack capacity against targets that keep moving.
- The validator only needs one healthy path. Consensus keeps signing as long as a single sentry connection survives.
Sizing: how many sentries?
Our rule of thumb after running this across ten networks:
| Network profile | Sentries | Placement |
|---|---|---|
| Testnet / low stake | 2 | Same region, different providers |
| Mainnet, standard | 3 | Two regions minimum |
| Mainnet, high stake or high block rate | 4–5 | Three regions, mixed providers |
More is not automatically better: every sentry adds gossip fan-in that the validator must process, and past ~5 the latency variance starts to hurt more than the redundancy helps. Measure your consensus_block_interval_seconds before and after adding sentries. If p99 gets worse, you've overshot.
What we monitor
A sentry layer you don't monitor is a false sense of security. Our Prometheus alerts for this topology, in order of severity:
p2p_peerson the validator dropping below the sentry count. It means a private link is down.- Missed-precommit rate over a 100-block sliding window. This is the earliest liveness signal, long before any downtime penalty window.
- Per-sentry inbound traffic anomaly (baseline ± 3σ). The classic pre-DDoS reconnaissance pattern shows up here first.
- Peer-count spikes on any single sentry. Someone is mapping our edge.
The point of sentry architecture is not that attacks stop happening. It's that attacks stop being interesting: they hit disposable infrastructure, we rotate it, and the validator never misses a block.
Takeaways
- Never give a validator a public IP; connect it only to sentries you control, over a private network.
pex = falseon the validator;private_peer_ids+unconditional_peer_idson every sentry. All four, every time.- Treat sentries as disposable and rotate them; treat the validator as sacred and hide it.
- Alert on missed precommits, not just downtime. By the time "downtime" fires, you're already in the penalty window.
This is layer 3 of the five-layer model we describe on our security page. Layer 2, keeping the signing key off the validator entirely, is covered in Why Your Validator Key Should Never Touch a Disk.