pelotech-nat
A cost-effective, security-hardened NAT instance AMI built on Amazon Linux 2023 — a drop-in replacement for AWS NAT Gateway.
Why pelotech-nat?
AWS NAT Gateway charges a flat hourly fee plus $0.045 per GB processed. A NAT instance has a fixed monthly cost regardless of data volume. The savings scale with traffic — see Pricing for detailed comparisons.
pelotech-nat is a drop-in replacement for fck-nat — it reads /etc/fck-nat.conf natively, so existing deployments can switch to the hardened AMI with no configuration changes. It builds on fck-nat's configuration model while adding enterprise-grade hardening and operational tooling.
Note: The AMIs are not public. Fork this repository and build the AMIs in your own AWS account — see the Building guide for details.
Features
- Multi-architecture — ARM64 and x86_64 AMIs
- Multi-region — Published to 34 commercial regions + 2 GovCloud regions
- FIPS 140-3 compliant — FIPS crypto policy enabled, FIPS-validated kernel (6.1) for GovCloud
- CIS Level 2 hardened — Full CIS Benchmark Level 2 server profile (auditd, PAM faillock, SSH hardening, sysctl, filesystem restrictions)
- FIPS endpoint auto-detection — Automatically uses AWS FIPS endpoints in supported US/GovCloud regions; configurable via
fips_endpoints - Security-hardened — AL2023 minimal base, IMDSv2 required, Trivy + OpenSCAP (CIS L2 profile) scanned
- Kernel live patching — kpatch enabled for zero-downtime security updates
- CloudWatch integration — Optional CloudWatch agent with SSM-based configuration
- nftables NAT — Modern packet filtering via nftables masquerade rules
- Minimal footprint — 6 GB root volume, oneshot systemd service, no unnecessary packages
- IPv4 + IPv6 — Full dual-stack forwarding support
- fck-nat compatible — Reads
/etc/fck-nat.confnatively; works with theterraform-aws-fck-natmodule out of the box
Architecture
AL2023 Minimal AMI (kernel 6.1, FIPS 140-3 validated)
└─ Packer Build
├─ dnf upgrade + kpatch
├─ pelotech-nat RPM install
│ ├─ /opt/pelotech-nat/pelotech-nat.sh
│ └─ pelotech-nat.service (systemd oneshot)
├─ amazon-cloudwatch-agent
├─ amazon-ssm-agent
├─ nftables + conntrack-tools
├─ FIPS 140-3 enablement + reboot
├─ CIS Level 2 hardening
│ ├─ FIPS crypto policy enforcement
│ ├─ Filesystem module blacklist
│ ├─ /tmp mount (noexec,nodev,nosuid)
│ ├─ /dev/shm mount (nodev,noexec,nosuid)
│ ├─ Kernel/network sysctl hardening
│ ├─ Auditd with immutable rules
│ ├─ PAM faillock (5 attempts, 15 min lockout)
│ ├─ PAM wheel group for su
│ ├─ SSH hardening (no root, no password, banner)
│ ├─ Password policy (365 day max, UMASK 077)
│ └─ User init file permissions (0600)
├─ Security scans (Trivy + OpenSCAP CIS L2)
└─ cleanup + fstrim
CIS Level 2 — Accepted Risks
The following 5 CIS rules are not remediated. All require dedicated partitions (/home, /var, /var/log, /var/log/audit, /var/tmp) which is not practical on a single-purpose NAT appliance with a small ephemeral root volume.
| Rule | Severity | Rationale |
|---|---|---|
partition_for_home |
LOW | No user data stored — instance runs a single systemd service |
partition_for_var |
LOW | Ephemeral instance rebuilt from code on every deploy |
partition_for_var_log |
LOW | Logs ship to CloudWatch; local logs are transient |
partition_for_var_log_audit |
LOW | Audit logs are immutable (-e 2) but disk exhaustion is not a concern on a minimal appliance |
partition_for_var_tmp |
MEDIUM | /tmp is already mounted with noexec,nodev,nosuid; separate /var/tmp partition adds no value here |
These rules assume a general-purpose server where partition isolation prevents disk-fill attacks across mount points. A NAT appliance writes negligible data to disk — it forwards packets, not files — so the risk is accepted.
At boot, the pelotech-nat systemd service runs once:
- Reads
/etc/pelotech-nat.conf(preferred) with fallback to/etc/fck-nat.conffor backward compatibility - Queries IMDS v2 for instance metadata
- Validates IMDS metadata (exits on failure)
- Auto-detects FIPS endpoint support based on region (configurable via
fips_endpoints) - Disables source/destination check on the primary ENI
- Optionally associates an Elastic IP
- Optionally attaches a secondary ENI
- Enables IPv4/IPv6 forwarding and disables reverse path filtering via sysctl
- Applies nftables masquerade rules
- Optionally starts the CloudWatch agent
Supported Regions
Commercial (34 regions)
af-south-1, ap-east-1, ap-east-2, ap-northeast-1, ap-northeast-2, ap-northeast-3, ap-south-1, ap-south-2, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, ap-southeast-5, ap-southeast-6, ap-southeast-7, ca-central-1, ca-west-1, eu-central-1, eu-central-2, eu-north-1, eu-south-1, eu-south-2, eu-west-1, eu-west-2, eu-west-3, il-central-1, me-central-1, me-south-1, mx-central-1, sa-east-1, us-east-1, us-east-2, us-west-1, us-west-2
GovCloud (2 regions)
us-gov-east-1, us-gov-west-1
Supported Architectures
| Architecture | Build Instance | Recommended Instance Types |
|---|---|---|
| ARM64 | t4g.micro |
t4g.nano, t4g.micro, c6gn.medium–c6gn.xlarge, c7gn.medium–c7gn.xlarge, c8gn.medium–c8gn.8xlarge, m7g.medium–m7g.xlarge |
| x86_64 | t3a.micro |
t3a.nano, t3a.micro, c5n.large–c5n.2xlarge, c6in.large–c6in.2xlarge |
Pricing
NAT instances have a flat monthly compute cost regardless of data volume. NAT Gateway charges per-GB on top of its hourly fee. The more data you push, the bigger the savings.
Total Monthly Cost (EC2 Only)
Values shown as Commercial, GovCloud.
| Solution | Arch | 1 TB | 10 TB | 100 TB | 500 TB |
|---|---|---|---|---|---|
| NAT Gateway | — | $78.93, $94.72 | $493.65, $592.38 | $4,640.85, $5,569.02 | $23,072.85, $27,687.42 |
| t4g.nano | ARM64 | $3.07, $3.58 | $3.07, $3.58 | $3.07, $3.58 | $3.07, $3.58 |
| t4g.micro | ARM64 | $6.13, $7.15 | $6.13, $7.15 | $6.13, $7.15 | $6.13, $7.15 |
| c6gn.medium | ARM64 | $31.54, $37.96 | $31.54, $37.96 | $31.54, $37.96 | $31.54, $37.96 |
| c6gn.large | ARM64 | $63.07, $75.92 | $63.07, $75.92 | $63.07, $75.92 | $63.07, $75.92 |
| c6gn.xlarge | ARM64 | $126.14, $151.84 | $126.14, $151.84 | $126.14, $151.84 | $126.14, $151.84 |
| c8gn.medium | ARM64 | $43.25, $52.05 | $43.25, $52.05 | $43.25, $52.05 | $43.25, $52.05 |
| c8gn.large | ARM64 | $86.51, $104.10 | $86.51, $104.10 | $86.51, $104.10 | $86.51, $104.10 |
| c7gn.medium | ARM64 | $42.05, $42.05 | $42.05, $42.05 | $42.05, $42.05 | $42.05, $42.05 |
| c7gn.large | ARM64 | $84.10, $84.10 | $84.10, $84.10 | $84.10, $84.10 | $84.10, $84.10 |
| c7gn.xlarge | ARM64 | $168.19, $168.19 | $168.19, $168.19 | $168.19, $168.19 | $168.19, $168.19 |
| c8gn.8xlarge | ARM64 | $1,384.08, $1,666.15 | $1,384.08, $1,666.15 | $1,384.08, $1,666.15 | $1,384.08, $1,666.15 |
| m7g.medium | ARM64 | $29.78, $29.78 | $29.78, $29.78 | $29.78, $29.78 | $29.78, $29.78 |
| m7g.large | ARM64 | $59.57, $59.57 | $59.57, $59.57 | $59.57, $59.57 | $59.57, $59.57 |
| m7g.xlarge | ARM64 | $119.14, $119.14 | $119.14, $119.14 | $119.14, $119.14 | $119.14, $119.14 |
| t3a.nano | x86_64 | $3.43, $4.02 | $3.43, $4.02 | $3.43, $4.02 | $3.43, $4.02 |
| t3a.micro | x86_64 | $6.86, $8.03 | $6.86, $8.03 | $6.86, $8.03 | $6.86, $8.03 |
| c5n.large | x86_64 | $78.84, $78.84 | $78.84, $78.84 | $78.84, $78.84 | $78.84, $78.84 |
| c5n.xlarge | x86_64 | $157.68, $157.68 | $157.68, $157.68 | $157.68, $157.68 | $157.68, $157.68 |
| c5n.2xlarge | x86_64 | $315.36, $315.36 | $315.36, $315.36 | $315.36, $315.36 | $315.36, $315.36 |
| c6in.large | x86_64 | $82.78, $99.65 | $82.78, $99.65 | $82.78, $99.65 | $82.78, $99.65 |
| c6in.xlarge | x86_64 | $165.56, $199.29 | $165.56, $199.29 | $165.56, $199.29 | $165.56, $199.29 |
| c6in.2xlarge | x86_64 | $331.13, $398.58 | $331.13, $398.58 | $331.13, $398.58 | $331.13, $398.58 |
Commercial NAT Gateway: $0.045/hr ($32.85/mo) + $0.045/GB processed. GovCloud NAT Gateway: $0.054/hr ($39.42/mo) + $0.054/GB processed (~20% premium). At 500 TB a single NAT Gateway would need ~67 Gbps sustained throughput — approaching its 100 Gbps limit.
NAT Instance Sizing & Network Performance
When sizing a NAT instance, it is critical to understand that AWS enforces Internet Gateway (IGW) Egress Limits that differ from the instance's internal VPC network bandwidth.
⚠️ The AWS Internet Egress Rule
Regardless of how much network bandwidth an instance has internally, traffic leaving the VPC to the internet (which is the primary job of a NAT instance) is heavily throttled based on the number of vCPUs:
- Under 32 vCPUs: Capped at 5 Gbps for internet egress.
- 32 vCPUs and above: Capped at 50% of the instance's total network bandwidth.
Note: Single-flow traffic (a single TCP/UDP connection) is always hard-capped at 5 Gbps to the internet, regardless of instance size.
ARM64 Instances (Graviton)
Graviton instances offer the best price-to-performance ratio for packet processing and are the recommended choice for NAT instances.
| Instance Type | vCPUs | Sustained VPC Bandwidth | Max Internet Egress | EC2 Com Hourly | EC2 Com Monthly | EC2 Gov Hourly | EC2 Gov Monthly | Target Use Case |
|---|---|---|---|---|---|---|---|---|
t4g.nano |
2 | ~0.03 Gbps | 5 Gbps | $0.0042 | ~$3.07 | $0.0049 | ~$3.58 | Dev/Test, low-cost |
t4g.micro |
2 | ~0.06 Gbps | 5 Gbps | $0.0084 | ~$6.13 | $0.0098 | ~$7.15 | Dev/Test, low-cost |
t4g.small |
2 | ~0.12 Gbps | 5 Gbps | $0.0168 | ~$12.26 | $0.0196 | ~$14.31 | Dev/Test, low-cost |
t4g.medium |
2 | ~0.25 Gbps | 5 Gbps | $0.0336 | ~$24.53 | $0.0392 | ~$28.62 | Small prod web apps |
c6gn.medium |
1 | 1.6 Gbps | 5 Gbps | $0.0432 | ~$31.54 | $0.0520 | ~$37.96 | Standard Prod |
c6gn.large |
2 | 3.1 Gbps | 5 Gbps | $0.0864 | ~$63.07 | $0.1040 | ~$75.92 | Standard Prod |
c6gn.xlarge |
4 | 6.2 Gbps | 5 Gbps | $0.1728 | ~$126.14 | $0.2080 | ~$151.84 | High Traffic |
c6gn.2xlarge |
8 | 12.5 Gbps | 5 Gbps | $0.3456 | ~$252.29 | $0.4160 | ~$303.68 | High Traffic |
c6gn.4xlarge |
16 | 25 Gbps | 5 Gbps | $0.6912 | ~$504.58 | $0.8320 | ~$607.36 | Heavy internal, cap at IGW |
c6gn.8xlarge |
32 | 50 Gbps | 25 Gbps | $1.3824 | ~$1,009.15 | $1.6640 | ~$1,214.72 | Enterprise Backbone |
c6gn.16xlarge |
64 | 100 Gbps | 50 Gbps | $2.7648 | ~$2,018.30 | $3.3280 | ~$2,429.44 | Extreme Scale |
c8gn.medium |
1 | ~2 Gbps | 5 Gbps | $0.0593 | ~$43.25 | $0.0713 | ~$52.05 | Standard Prod |
c8gn.large |
2 | ~4 Gbps | 5 Gbps | $0.1185 | ~$86.51 | $0.1426 | ~$104.10 | High Traffic |
c8gn.xlarge |
4 | ~8 Gbps | 5 Gbps | $0.2370 | ~$173.01 | $0.2853 | ~$208.27 | High Traffic |
c8gn.2xlarge |
8 | 16 Gbps | 5 Gbps | $0.4740 | ~$346.02 | $0.5706 | ~$416.54 | Heavy burst |
c8gn.4xlarge |
16 | 25 Gbps | 5 Gbps | $0.9480 | ~$692.04 | $1.1412 | ~$833.08 | Heavy internal, cap at IGW |
c8gn.8xlarge |
32 | 50 Gbps | 25 Gbps | $1.8960 | ~$1,384.08 | $2.2824 | ~$1,666.15 | Enterprise Backbone |
c8gn.16xlarge |
64 | 100 Gbps | 50 Gbps | $3.7920 | ~$2,768.16 | $4.5648 | ~$3,332.30 | Extreme Scale |
x86_64 Instances (Intel / AMD)
x86_64 instances are provided for regions where Graviton is unavailable or for environments with specific architecture compliance requirements.
| Instance Type | vCPUs | Sustained VPC Bandwidth | Max Internet Egress | EC2 Com Hourly | EC2 Com Monthly | EC2 Gov Hourly | EC2 Gov Monthly | Target Use Case |
|---|---|---|---|---|---|---|---|---|
t3a.nano |
2 | ~0.03 Gbps | 5 Gbps | $0.0047 | ~$3.43 | $0.0055 | ~$4.02 | Dev/Test, low-cost |
t3a.micro |
2 | ~0.06 Gbps | 5 Gbps | $0.0094 | ~$6.86 | $0.0110 | ~$8.03 | Dev/Test, low-cost |
t3a.small |
2 | ~0.12 Gbps | 5 Gbps | $0.0188 | ~$13.72 | $0.0220 | ~$16.06 | Dev/Test, low-cost |
t3a.medium |
2 | ~0.25 Gbps | 5 Gbps | $0.0376 | ~$27.45 | $0.0439 | ~$32.05 | Small prod web apps |
c6in.large |
2 | 3.1 Gbps | 5 Gbps | $0.1134 | ~$82.78 | $0.1365 | ~$99.65 | Standard Prod |
c6in.xlarge |
4 | 6.2 Gbps | 5 Gbps | $0.2268 | ~$165.56 | $0.2730 | ~$199.29 | High Traffic |
c6in.2xlarge |
8 | 12.5 Gbps | 5 Gbps | $0.4536 | ~$331.13 | $0.5460 | ~$398.58 | High Traffic |
c6in.4xlarge |
16 | 25 Gbps | 5 Gbps | $0.9072 | ~$662.26 | $1.0920 | ~$797.16 | Heavy internal, cap at IGW |
c6in.8xlarge |
32 | 50 Gbps | 25 Gbps | $1.8144 | ~$1,324.51 | $2.1840 | ~$1,594.32 | Enterprise Backbone |
c6in.16xlarge |
64 | 100 Gbps | 50 Gbps | $3.6288 | ~$2,649.02 | $4.3680 | ~$3,188.64 | Extreme Scale |
c6in.32xlarge |
128 | 200 Gbps | 100 Gbps | $7.2576 | ~$5,298.05 | $8.7360 | ~$6,377.28 | Absolute Max Egress |
Recommendations
- t4g.nano (ARM64) / t3a.nano (x86_64) — Best for small but growing environments. At $3–4/mo these are the cheapest option. 32 Mbps sustained is enough for light workloads and the 5 Gbps burst handles traffic spikes. Start here and upgrade when you consistently saturate the baseline.
- t4g.micro (ARM64) / t3a.micro (x86_64) — Same burst ceiling but 64 Mbps sustained baseline. Good middle ground if t4g.nano's baseline feels tight.
- c6gn.medium — Budget option for sustained bandwidth. 1.6 Gbps at ~$32/mo — roughly the same as a NAT Gateway's hourly fee but no per-GB charge.
- c8gn.medium — Graviton4 network-optimized. ~2 Gbps at ~$43/mo. Better per-packet compute performance than the older c6gn generation.
- c6gn.xlarge / c8gn.xlarge — The "Sweet Spot". At ~6-8 Gbps sustained bandwidth, these are the largest instances you can use before hitting the AWS 5 Gbps IGW hard cap for instances under 32 vCPUs.
- c6gn.8xlarge / c8gn.8xlarge — Enterprise Backbone. 32 vCPUs bypass the 5 Gbps cap, unlocking up to 25 Gbps of internet egress (half of their 50 Gbps VPC limit).
- c6in.large–2xlarge (x86_64) — Network-optimized x86_64. 3.1–12.5 Gbps sustained. Use when ARM64 isn't an option.
- c6in.32xlarge (x86_64) — Absolute Maximum Scale. For workloads pushing over 50 Gbps, this instance provides 200 Gbps VPC bandwidth and hits the NAT Gateway's 100 Gbps absolute maximum egress limit.
Notes
- Pricing may be out of date — verify against the AWS EC2 pricing page for current rates.
- Prices are
us-east-1(Commercial) andus-gov-east-1(GovCloud) on-demand; spot instances (HA mode) reduce cost further. - Standard AWS data transfer charges ($0.09/GB to internet) apply equally to both NAT Gateway and NAT instances — they cancel out in comparison.
t4g/t3aburst bandwidth (5 Gbps) uses a network I/O credit system similar to CPU credits.c8gninstances use AWS Graviton4 processors.c6inare x86_64 network-optimized families for environments that require Intel-compatible AMIs.