Cloud / SRE
Closing Public Port 8545 on a Polygon Erigon Archive Node
How a dedicated AWS security group kept Polygon P2P ports public while closing JSON-RPC, metrics, private API, and SSH ingress.
On this page
A Polygon archive node’s logs showed unsolicited JSON-RPC calls while the node was syncing. The intended public service was peer networking; application queries and metrics did not need unrestricted internet access. The change therefore separated public P2P ports from private operational endpoints.
The change was simple: keep the public ports required for P2P networking, and close public JSON-RPC, metrics, private API, and SSH.
Terms used here
| Term | Meaning |
|---|---|
| Security group | AWS firewall attached to an instance or network interface. It decides which inbound and outbound traffic is allowed. |
| JSON-RPC | HTTP API used by clients to query blockchain data or submit transactions. On Erigon it commonly listens on 8545. |
| P2P | Peer-to-peer node traffic. Erigon needs it to exchange blocks and network data with other nodes. |
| Metrics port | HTTP endpoint for operational metrics. It is useful for monitoring but should not be public by default. |
| Private API | Erigon’s internal API for local components. It is not an external user interface. |
| CIDR | IP range notation such as 203.0.113.0/24, used to allow only specific networks. |
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
With that setting, the service listens on all addresses inside the container. If Docker also publishes that listener on a reachable host address and the network rules allow public 8545/tcp traffic, the endpoint can be reached from the internet.
What went wrong
The node logs showed unexpected external callers invoking methods such as eth_accounts. Those callers were outside the intended access pattern and were consistent with scanning; the method name alone does not establish the caller’s intent.
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. The --groups argument replaces its associated group list, so include any other groups that are still required and confirm SSM access before applying this change:
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.
[2] Erigon Contributors. “Public RPC.” Erigon README.
[3] Erigon Contributors. “Default Ports and Firewalls.” Erigon README.
[5] Amazon Web Services. “Security group rules.” Amazon VPC User Guide.