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.

Jun 16, 2026
AWSPolygonErigonsecurity-grouparchive-node

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:

PortProtocolSourcePurpose
30303TCP0.0.0.0/0Erigon P2P peering
30303UDP0.0.0.0/0Erigon P2P peering
42069UDP0.0.0.0/0Erigon torrent / snapshot peer

These public entry points are closed:

PortReason
8545/tcpJSON-RPC. There is no requirement to provide public RPC from this node.
6060/tcpMetrics / pprof-style observability. It should be internal or local only.
9090/tcpErigon private API. Erigon examples also bind private.api.addr to 127.0.0.1:9090.
8546/tcpWebSocket RPC. No public WebSocket RPC requirement exists.
8551/tcpEngine API / JWT auth. This is not an external user entry point.
22/tcpSSH. 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