cloud-sre
Why I Closed Port 8545 on a Polygon Erigon Archive Node
A practical security group change that moved a Polygon Erigon archive node from allow-all inbound traffic to a minimal public surface.
Archive nodes are often misconfigured with every port open to the public internet. That is especially risky while the node is still syncing and already under heavy load: scanners continuously probe JSON-RPC, and the logs fill with meaningless calls such as eth_accounts and eth_sendRawTransaction.
This article documents a security group change for a Polygon Erigon archive node: keep the public ports required for P2P networking, and close public JSON-RPC, metrics, private API, and SSH.
Background
The node runs a Polygon Mainnet archive node. Polygon’s official archive-node guide lists a 16-core CPU, 64GB RAM, and about 15TB of storage for a mainnet archive node. For storage, it recommends io1 or above, 20k+ IOPS, RAID-0, and SSD or NVMe media [1].
The Erigon process had HTTP JSON-RPC enabled:
--http
--ws
--http.addr=0.0.0.0
--http.port=8545
--http.api=web3,net,eth,trace
That means the service listens on all addresses inside the container. If the EC2 security group also allows public access to 8545/tcp, JSON-RPC is exposed directly to the internet.
What went wrong
The node logs showed external IPs calling RPC methods, including deprecated calls such as eth_accounts. That traffic was not business traffic. It was public scanning and probing.
The Erigon README gives clear guidance for public RPC: do not add admin to --http.api, avoid overly broad CORS, and reduce batch limits to lower DoS risk [2].
The simpler control is even stronger: if the node is not meant to be a public RPC service, do not expose 8545 at the security group layer.
The security group decision
The final security group keeps only three inbound rules:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
30303 | TCP | 0.0.0.0/0 | Erigon P2P peering |
30303 | UDP | 0.0.0.0/0 | Erigon P2P peering |
42069 | UDP | 0.0.0.0/0 | Erigon torrent / snapshot peer |
These public entry points are closed:
| Port | Reason |
|---|---|
8545/tcp | JSON-RPC. There is no requirement to provide public RPC from this node. |
6060/tcp | Metrics / pprof-style observability. It should be internal or local only. |
9090/tcp | Erigon private API. Erigon examples also bind private.api.addr to 127.0.0.1:9090. |
8546/tcp | WebSocket RPC. No public WebSocket RPC requirement exists. |
8551/tcp | Engine API / JWT auth. This is not an external user entry point. |
22/tcp | SSH. Operational access goes through SSM Session Manager instead. |
This matches Erigon’s default port guidance: 30303 and 30304 are public peering ports, 42069 is snap sync, while 8545 is RPC and metrics/private/Engine API ports should remain private [3].
Why outbound remains open
This change only tightens inbound traffic. Outbound traffic stays open because Polygon Erigon still needs to initiate connections to external dependencies:
- P2P peers
- Remote Heimdall API
- Snapshot and torrent peers
- System maintenance, image pulls, and package repositories over HTTPS
Polygon’s documentation says that if you do not run local Heimdall, you can point Erigon to a remote Heimdall URL with --bor.heimdall=<your heimdall url>. For PoS mainnet, the documented remote endpoint is https://heimdall-api.polygon.technology [1].
So the compromise is deliberate: keep outbound open, but reduce inbound to the minimum public surface.
AWS security groups are stateful virtual firewalls. They control inbound and outbound traffic for associated resources. A new security group has no inbound rules by default, while the default outbound rule allows all outbound traffic [4][5].
Terraform representation
The Terraform change moves the Polygon node from a shared allow-all security group to a dedicated security group:
security_group_ids = [aws_security_group.polygon_node_sg.id]
The dedicated security group keeps only P2P and torrent ingress:
ingress {
description = "Polygon P2P TCP"
from_port = 30303
to_port = 30303
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Polygon P2P UDP"
from_port = 30303
to_port = 30303
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Polygon torrent UDP"
from_port = 42069
to_port = 42069
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
Ports 8545 and 6060 are not hard-coded as public rules. They are controlled by explicit allowlist variables:
variable "polygon_rpc_allowed_cidr_blocks" {
description = "CIDR blocks allowed to access Polygon JSON-RPC on TCP 8545. Empty closes public RPC access."
type = list(string)
default = []
}
variable "polygon_metrics_allowed_cidr_blocks" {
description = "CIDR blocks allowed to access Polygon Erigon metrics on TCP 6060. Empty closes public metrics access."
type = list(string)
default = []
}
The default is closed. If a fixed office IP, monitoring VPC, or reverse proxy really needs access later, it must be added explicitly.
Temporary live change
When Terraform could not be applied immediately because of a local provider issue, the same change was applied online with AWS CLI:
aws ec2 create-security-group \
--region ap-northeast-1 \
--group-name polygon-node-sg \
--description "Polygon Erigon node security group" \
--vpc-id <vpc-id>
Then only the required inbound rules were authorized:
aws ec2 authorize-security-group-ingress \
--region ap-northeast-1 \
--group-id <polygon-node-sg-id> \
--ip-permissions \
'IpProtocol=tcp,FromPort=30303,ToPort=30303,IpRanges=[{CidrIp=0.0.0.0/0,Description="Polygon P2P TCP"}]' \
'IpProtocol=udp,FromPort=30303,ToPort=30303,IpRanges=[{CidrIp=0.0.0.0/0,Description="Polygon P2P UDP"}]' \
'IpProtocol=udp,FromPort=42069,ToPort=42069,IpRanges=[{CidrIp=0.0.0.0/0,Description="Polygon torrent UDP"}]'
Finally, the instance was switched to the new security group:
aws ec2 modify-instance-attribute \
--region ap-northeast-1 \
--instance-id <instance-id> \
--groups <polygon-node-sg-id>
This does not restart EC2 or the container. It only changes the security groups associated with the network interface.
Validation
From outside the instance, 8545 should fail:
curl -sS --connect-timeout 5 -m 8 \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://<public-ip>:8545
The expected result is a timeout or connection failure.
From inside the instance, local RPC should still work:
curl -sS -H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://127.0.0.1:8545 | jq
That confirms the RPC service is still running. It is just no longer reachable from the public internet.
Sync should also continue:
curl -sS -H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' \
http://127.0.0.1:8545 | jq
If currentBlock keeps increasing and the logs show Execution progress, P2P, Heimdall, and local RPC are still functioning.
Follow-up
The manually created security group must be imported back into Terraform state:
terraform import aws_security_group.polygon_node_sg <polygon-node-sg-id>
After that, run the normal terraform plan and terraform apply workflow so Terraform does not try to create a duplicate security group.
The next step is not to reopen RPC. It is to put RPC behind an explicit boundary:
- Internal-only access
- Fixed office egress IPs
- A reverse proxy with authentication, rate limits, and access logs
- A separate read-only RPC layer instead of exposing the archive node itself
The archive node’s primary job is stable sync and internal query service. Unless it is intentionally operated as a public RPC product, 8545 should not be on the public internet.
References
[1] Polygon Labs. “Run an Erigon archive node.” Polygon Docs. https://docs.polygon.technology/pos/how-to/erigon-archive-node
[2] Erigon Contributors. “Public RPC.” Erigon README. https://github.com/erigontech/erigon#public-rpc
[3] Erigon Contributors. “Default Ports and Firewalls.” Erigon README. https://github.com/erigontech/erigon#default-ports-and-firewalls
[4] Amazon Web Services. “Control traffic to AWS resources using security groups.” Amazon VPC User Guide. https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html
[5] Amazon Web Services. “Security group rules.” Amazon VPC User Guide. https://docs.aws.amazon.com/vpc/latest/userguide/security-group-rules.html