ЁЯПл The SchoolтА║ЁЯЪк NATтА║ЁЯзн рдзрдбрд╛ 07 тАФ NAT рдЪреЗ рдкрд░реНрдпрд╛рдп
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯзн рдзрдбрд╛ 07 тАФ NAT рдЪреЗ рдкрд░реНрдпрд╛рдп

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 8 рдкреИрдХреА рдзрдбрд╛ 07 ┬╖ рдорд╛рдЧреЗ: lesson-06-costs ┬╖ рдкреБрдвреЗ: lesson-08-troubleshooting


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ06, рдЖрдгрд┐ рдмрд╛рдХреАрдЪреА рджрд╛рд░реЗ: gateway endpoints, interface endpoints (PrivateLink), IPv6 рд╕рд╛рдареА egress-only internet gateway, domain allow-lists рд╕рд╛рдареА proxy рдХрд┐рдВрд╡рд╛ AWS Network Firewall, private NAT gateway, рдЖрдгрд┐ internet рдЕрдЬрд┐рдмрд╛рдд рдирд╛рд╣реА. nat/demo.py рдордзреАрд▓ alternatives() рд╣рд╛ рдирдХрд╛рд╢рд╛ рдЫрд╛рдкрддреЗ.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдкреНрд░рддреНрдпреЗрдХ рдлреЗрд░реАрд▓рд╛ рдореБрдЦреНрдп рдлрд╛рдЯрдХ рд▓рд╛рдЧрдд рдирд╛рд╣реА:

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    desks["ЁЯкС private desks"]
    desks -->|"S3 / DynamoDB"| gwe["ЁЯЪЗ gateway endpoint ┬╖ free"]
    desks -->|"ECR, STS, SQSтАж"| ife["ЁЯЪк interface endpoint ┬╖ $/h/AZ + $/GB"]
    desks -->|"IPv6 out only"| eigw["6я╕ПтГг egress-only IGW"]
    desks -->|"listed domains only"| fw["ЁЯУЛ proxy / Network Firewall"] --> nat["ЁЯЪк NAT gateway"]
    desks -->|"other private network"| pnat["ЁЯПл private NAT gateway"]

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/nat/lesson-diagrams.html#l07

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг NAT рд╣реЗ рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдг рдХрд╛рдорд╛рдЪреЗ рдлрд╛рдЯрдХ рдЖрд╣реЗ: рддреНрдпрд╛рд▓рд╛ рдкреНрд░рддрд┐ GB рдЦрд░реНрдЪ рдпреЗрддреЛ, рддреЗ servers рдирд╛ internet рд╡рд░рдЪреНрдпрд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА address рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреВ рджреЗрддреЗ, рдЖрдгрд┐ рддреЗ рдлрдХреНрдд IPv4 рд╕рд╛рдареА рдЖрд╣реЗ. рдЕрдиреЗрдХ рдлреЗрд▒реНрдпрд╛рдВрд╕рд╛рдареА рд╕реНрд╡рд╕реНрдд, рдЕрд░реБрдВрдж рдХрд┐рдВрд╡рд╛ private рджрд╛рд░ рдЬрд╛рд╕реНрдд рдЪрд╛рдВрдЧрд▓реЗ рдЕрд╕рддреЗ. рдпреЛрдЧреНрдп рджрд╛рд░ рдирд┐рд╡рдбрдгреЗ рд╣рд╛ рдЦрд░реНрдЪрд╛рдЪрд╛рд╣реА рдирд┐рд░реНрдгрдп рдЖрд╣реЗ рдЖрдгрд┐ рд╕реБрд░рдХреНрд╖рд┐рддрддреЗрдЪрд╛рд╣реА.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

nat/demo.py рдордзреАрд▓ alternatives() рдкреНрд░рддреНрдпреЗрдХ рдЧрд░рдЬ рдЖрдгрд┐ рддрд┐рдЪреЗ рджрд╛рд░ рдЫрд╛рдкрддреЗ. nat/gateway.py рдордзреАрд▓ monthly_cost() рд▓рд╛ рддреБрдореНрд╣реА рд╕реНрд╡рддрдГрдЪреЗ hourly рдЖрдгрд┐ per_gb рджрд┐рд▓реЗ рддрд░ рддреЗ рдХреЛрдгрддреНрдпрд╛рд╣реА "рддрд╛рд╕ + GB" рджрд╛рд░рд╛рдЪреА рдХрд┐рдВрдордд рдХрд╛рдврддреЗ. рдЦрд╛рд▓реА, 3 AZs рдордзреАрд▓ interface endpoint hourly=0.01, per_gb=0.01 рд╡рд╛рдкрд░рддреЛ тАФ us-east-1 рдЪреНрдпрд╛ рдЙрджрд╛рд╣рд░рдг рдХрд┐рдорддреА.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 nat/demo.py alternatives
python3 - <<'EOF'
import sys; sys.path.insert(0, "nat"); from gateway import monthly_cost
gb_s3, gb_ecr, gb_web = 3000, 1500, 500
print("1 all through 3 NATs              $", monthly_cost(3, gb_s3 + gb_ecr + gb_web))
print("2 S3 тЖТ free gateway endpoint      $", monthly_cost(3, gb_ecr + gb_web))
ecr = monthly_cost(3, gb_ecr, hourly=0.01, per_gb=0.01)   # example: interface endpoint in 3 AZs
print("3 + ECR тЖТ interface endpoint      $", round(monthly_cost(3, gb_web) + ecr, 2), f"(endpoint part ${ecr})")
print("4 no internet needed, no NAT      $", monthly_cost(0, 0))
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

alternatives рд╕рд╣рд╛ рдУрд│реА рдЫрд╛рдкрддреЗ, S3 / DynamoDB тЖТ gateway endpoint тАФ free, just a route рдкрд╛рд╕реВрди nothing on the internet at all тЖТ no NAT тАФ the cheapest and safest gate is none рдкрд░реНрдпрдВрдд. рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:

1 all through 3 NATs              $ 323.55
2 S3 тЖТ free gateway endpoint      $ 188.55
3 + ECR тЖТ interface endpoint      $ 157.95 (endpoint part $36.9)
4 no internet needed, no NAT      $ 0.0

рдкреНрд░рддреНрдпреЗрдХ рджрд╛рд░рд╛рдиреЗ bill рдЪрд╛ рдХрд╛рд╣реА рднрд╛рдЧ рдХрд╛рдвреВрди рдЯрд╛рдХрд▓рд╛. (ECR image layers S3 рдордзреНрдпреЗ рд╕рд╛рдард╡рд▓реЗрд▓реЗ рдЕрд╕рддрд╛рдд, рдореНрд╣рдгреВрди рдкреНрд░рддреНрдпрдХреНрд╖рд╛рдд image pull рдЪрд╛ рдмрд░рд╛рдЪрд╕рд╛ рднрд╛рдЧ S3 gateway endpoint рдордзреВрдирдЪ рдЬрд╛рддреЛ; рдЙрд░рд▓реЗрд▓реНрдпрд╛рд╕рд╛рдареА ECR API endpoints рддрд░реАрд╣реА рд▓рд╛рдЧрддрд╛рдд.)

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

NAT рд╣реЗ рдЕрдиреЗрдХ рджрд╛рд░рд╛рдВрдкреИрдХреА рдПрдХ рджрд╛рд░ рдЖрд╣реЗ; рдкреНрд░рддреНрдпреЗрдХ destination рд╕рд╛рдареА рдпреЛрдЧреНрдп рджрд╛рд░ рдирд┐рд╡рдбрд▓реНрдпрд╛рдиреЗ рдЙрджрд╛рд╣рд░рдгрд╛рддрд▓реЗ bill $323.55 рд╡рд░реВрди $157.95 рд╡рд░ рдЖрд▓реЗ, рдЖрдгрд┐ internet рдЪреА рдЧрд░рдЬ рдирд╕рд▓реЗрд▓реНрдпрд╛ workload рд╕рд╛рдареА рд╢реВрдиреНрдпрд╛рд╡рд░.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд

рдЦрд▒реНрдпрд╛ account рд╡рд░:

aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Gateway --service-name com.amazonaws.us-east-1.dynamodb --route-table-ids rtb-private-a rtb-private-b rtb-private-c
aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Interface --service-name com.amazonaws.us-east-1.ecr.dkr --subnet-ids subnet-private-a subnet-private-b subnet-private-c --security-group-ids sg-0endpoints --private-dns-enabled
aws ec2 create-egress-only-internet-gateway --vpc-id vpc-0abc
aws ec2 create-route --route-table-id rtb-private-a --destination-ipv6-cidr-block ::/0 --egress-only-internet-gateway-id eigw-0abc
aws ec2 create-nat-gateway --subnet-id subnet-transit-a --connectivity-type private
resource "aws_egress_only_internet_gateway" "v6" {
  vpc_id = aws_vpc.main.id
}

resource "aws_route" "private_v6_out" {
  route_table_id              = aws_route_table.private["a"].id
  destination_ipv6_cidr_block = "::/0"
  egress_only_gateway_id      = aws_egress_only_internet_gateway.v6.id
}

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдЪрд╛рдВрдЧрд▓реА egress рд░рдЪрдирд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рдЪреЗ destination рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ рджрд╛рд░ рдпрд╛рджреАрдд рдорд╛рдВрдбрддреЗ: AWS services endpoints рдордзреВрди, partners NAT рдордзреВрди (рд╕реНрдерд┐рд░ IPs рд╕рд╣), рдмрд╛рдХреА рд╕рдЧрд│реЗ domain allow-list рдордзреВрди тАФ рдХрд┐рдВрд╡рд╛ рдХрд╛рд╣реАрдЪ рдирд╛рд╣реА.

тПня╕П рдкреБрдвреЗ

рдлрд╛рдЯрдХ рдЪрд╛рд▓рддреЗ. рдПрдХ рджрд┐рд╡рд╕ рддреЗ рдЪрд╛рд▓рдд рдирд╛рд╣реА рддреЛрдкрд░реНрдпрдВрдд: "connection reset", "cannot allocate port". рдлрд╛рдЯрдХрд╛рдЪреЗ troubleshooting тАФ рднрд░рд▓реЗрд▓реНрдпрд╛ рдиреЛрдВрджрд╡рд╣реНрдпрд╛ рдЖрдгрд┐ рд╡рд┐рд╕рд░рд▓реЗрд▓реНрдпрд╛ рдУрд│реА.

git checkout lesson-08-troubleshooting

ЁЯзн Lesson 07 тАФ Alternatives to NAT

ЁЯУН You are here: Lesson 07 of 8 ┬╖ Previous: lesson-06-costs ┬╖ Next: lesson-08-troubleshooting


ЁЯУж What's in this branch

Lessons 01тАУ06, plus the other doors: gateway endpoints, interface endpoints (PrivateLink), the egress-only internet gateway for IPv6, a proxy or AWS Network Firewall for domain allow-lists, the private NAT gateway, and no internet at all. alternatives() in nat/demo.py prints the map.

ЁЯзТ Explain like I'm 5

Not every trip needs the main gate:

ЁЯЧ║я╕П Diagram

flowchart LR
    desks["ЁЯкС private desks"]
    desks -->|"S3 / DynamoDB"| gwe["ЁЯЪЗ gateway endpoint ┬╖ free"]
    desks -->|"ECR, STS, SQSтАж"| ife["ЁЯЪк interface endpoint ┬╖ $/h/AZ + $/GB"]
    desks -->|"IPv6 out only"| eigw["6я╕ПтГг egress-only IGW"]
    desks -->|"listed domains only"| fw["ЁЯУЛ proxy / Network Firewall"] --> nat["ЁЯЪк NAT gateway"]
    desks -->|"other private network"| pnat["ЁЯПл private NAT gateway"]

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/nat/lesson-diagrams.html#l07

тЭУ What

ЁЯдФ Why

Because the NAT is a general-purpose gate: it costs per GB, it lets servers reach any address on the internet, and it is only for IPv4. Many trips are better served by a door that is cheaper, narrower or private. Choosing the right door is both a cost decision and a security decision.

ЁЯФз How (in this repo)

alternatives() in nat/demo.py prints each need and its door. monthly_cost() in nat/gateway.py prices any "hours + GB" door when you pass its own hourly and per_gb. Below, an interface endpoint in 3 AZs uses hourly=0.01, per_gb=0.01 тАФ example us-east-1 prices.

ЁЯзк Try it

python3 nat/demo.py alternatives
python3 - <<'EOF'
import sys; sys.path.insert(0, "nat"); from gateway import monthly_cost
gb_s3, gb_ecr, gb_web = 3000, 1500, 500
print("1 all through 3 NATs              $", monthly_cost(3, gb_s3 + gb_ecr + gb_web))
print("2 S3 тЖТ free gateway endpoint      $", monthly_cost(3, gb_ecr + gb_web))
ecr = monthly_cost(3, gb_ecr, hourly=0.01, per_gb=0.01)   # example: interface endpoint in 3 AZs
print("3 + ECR тЖТ interface endpoint      $", round(monthly_cost(3, gb_web) + ecr, 2), f"(endpoint part ${ecr})")
print("4 no internet needed, no NAT      $", monthly_cost(0, 0))
EOF

тЬЕ Verify тАФ what you should see

alternatives prints six lines, from S3 / DynamoDB тЖТ gateway endpoint тАФ free, just a route to nothing on the internet at all тЖТ no NAT тАФ the cheapest and safest gate is none. Your snippet prints:

1 all through 3 NATs              $ 323.55
2 S3 тЖТ free gateway endpoint      $ 188.55
3 + ECR тЖТ interface endpoint      $ 157.95 (endpoint part $36.9)
4 no internet needed, no NAT      $ 0.0

Each door removed part of the bill. (ECR image layers are stored in S3, so in real life the S3 gateway endpoint also carries much of an image pull; the ECR API endpoints are still needed for the rest.)

ЁЯПБ What you just proved

The NAT is one door among several; picking the right door per destination cut the example bill from $323.55 to $157.95, and for a workload with no internet needs, to zero.

тЪая╕П Common mistakes

ЁЯПн In production

On a real account:

aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Gateway --service-name com.amazonaws.us-east-1.dynamodb --route-table-ids rtb-private-a rtb-private-b rtb-private-c
aws ec2 create-vpc-endpoint --vpc-id vpc-0abc --vpc-endpoint-type Interface --service-name com.amazonaws.us-east-1.ecr.dkr --subnet-ids subnet-private-a subnet-private-b subnet-private-c --security-group-ids sg-0endpoints --private-dns-enabled
aws ec2 create-egress-only-internet-gateway --vpc-id vpc-0abc
aws ec2 create-route --route-table-id rtb-private-a --destination-ipv6-cidr-block ::/0 --egress-only-internet-gateway-id eigw-0abc
aws ec2 create-nat-gateway --subnet-id subnet-transit-a --connectivity-type private
resource "aws_egress_only_internet_gateway" "v6" {
  vpc_id = aws_vpc.main.id
}

resource "aws_route" "private_v6_out" {
  route_table_id              = aws_route_table.private["a"].id
  destination_ipv6_cidr_block = "::/0"
  egress_only_gateway_id      = aws_egress_only_internet_gateway.v6.id
}

ЁЯПн Why this matters in production: a good egress design lists every destination class and its door: AWS services through endpoints, partners through the NAT (with fixed IPs), everything else through a domain allow-list тАФ or nothing.

тПня╕П Next

The gate works. Until one day it does not: "connection reset", "cannot allocate port". Troubleshooting the gate тАФ full registers and forgotten rows.

git checkout lesson-08-troubleshooting
тЖР PreviouscostsNext тЖТtroubleshooting

This page is the lesson's README from the lesson-07-alternatives branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.