ЁЯПл The SchoolтА║ЁЯПл VPCтА║ЁЯЪк рдзрдбрд╛ 05 тАФ Internet gateway рдЖрдгрд┐ public subnets: рдореБрдЦреНрдп рджрд░рд╡рд╛рдЬрд╛
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯЪк рдзрдбрд╛ 05 тАФ Internet gateway рдЖрдгрд┐ public subnets: рдореБрдЦреНрдп рджрд░рд╡рд╛рдЬрд╛

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-route-tables ┬╖ рдкреБрдвреЗ: lesson-06-sg-vs-nacl


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

рдзрдбреЗ 01тАУ04, рдЖрдгрд┐ рдкрд╣рд┐рд▓рд╛ рдкреВрд░реНрдг campus: vpc/demo.py рдордзреАрд▓ campus() рддреАрди wings рдмрд╛рдВрдзрддреЛ тАФ public-a, app-a, data-a тАФ рдЬреНрдпрд╛рдВрдд web, app рдЖрдгрд┐ db рд╣реЗ desks рдЖрд╣реЗрдд, рдЖрдгрд┐ vpc/network.py рдордзреАрд▓ Campus.walk() рдПрдХрд╛ packet рдЪрд╛ рдмрд╛рд╣реЗрд░рдЪрд╛ рдкреНрд░рд╡рд╛рд╕ рдкрд╛рд╣рддреЛ. igw() web рдЖрдгрд┐ db рдирд╛ internet рдХрдбреЗ рдкрд╛рдард╡рддреЛ.

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

Campus рдЪреНрдпрд╛ рдХреБрдВрдкрдгрд╛рд▓рд╛ рд╢рд╣рд░рд╛рдХрдбреЗ рдЬрд╛рдгрд╛рд░рд╛ рдПрдХрдЪ рдореБрдЦреНрдп рджрд░рд╡рд╛рдЬрд╛ ЁЯЪк рдЖрд╣реЗ: internet gateway.

рджрд░рд╡рд╛рдЬрд╛ рдмрд╛рдВрдзрдгреЗ рдкреБрд░реЗрд╕реЗ рдирд╛рд╣реА. Wing рджрд░рд╡рд╛рдЬрд╛ рд╡рд╛рдкрд░рддреЛ рддреЛ рдлрдХреНрдд рддреНрдпрд╛рдЪреНрдпрд╛ corridor рдЪреНрдпрд╛ рдкрд╛рдЯреАрд╡рд░ "рдмрд╛рдХреА рд╕рдЧрд│реЗ тЖТ рдореБрдЦреНрдп рджрд░рд╡рд╛рдЬрд╛" рдЕрд╕реЗ рд▓рд┐рд╣рд┐рд▓реЗ рдЕрд╕реЗрд▓ рддрд░рдЪ. Public wing рдЪреНрдпрд╛ рдкрд╛рдЯреАрд╡рд░ рддрд╕реЗ рд▓рд┐рд╣рд┐рд▓реЗ рдЖрд╣реЗ. Data wing рдЪреНрдпрд╛ рдкрд╛рдЯреАрд╡рд░ рдирд╛рд╣реА тАФ рдореНрд╣рдгреВрди data wing рдордзреВрди рд╢рд╣рд░рд╛рдХрдбреЗ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдкрддреНрд░рд╛рд▓рд╛ рдПрдХрд╣реА рдУрд│ рд╕рд╛рдкрдбрдд рдирд╛рд╣реА рдЖрдгрд┐ рддреЗ drop рд╣реЛрддреЗ.

рдЖрдгрдЦреА рдПрдХ рдЧреЛрд╖реНрдЯ. рдкрддреНрд░ рджрд░рд╡рд╛рдЬрд╛рддреВрди рдмрд╛рд╣реЗрд░ рдЧреЗрд▓реНрдпрд╛рд╡рд░ рд╢рд╣рд░рд╛рд▓рд╛ рдЙрддреНрддрд░ рд▓рд┐рд╣рд┐рддрд╛ рдЖрд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ. рдлрдХреНрдд campus рдЪрд╛ рдирдВрдмрд░ (10.20.0.10) рдЕрд╕рд▓реЗрд▓реНрдпрд╛ desk рдХрдбреЗ рд╢рд╣рд░ рд╡рд╛рдкрд░реВ рд╢рдХреЗрд▓ рдЕрд╕рд╛ рдкрддреНрддрд╛рдЪ рдирд╛рд╣реА. рдореНрд╣рдгреВрди рд╢рд╣рд░рд╛рд╢реА рдмреЛрд▓рдгрд╛рд▒реНрдпрд╛ desk рд▓рд╛ public рдкрддреНрддрд╛ рдкрдг рд▓рд╛рдЧрддреЛ тАФ рд╕рд╛рдзрд╛ public IP рдХрд┐рдВрд╡рд╛ Elastic IP. рджрд░рд╡рд╛рдЬрд╛ рджреЛрдиреНрд╣реА рджрд┐рд╢рд╛рдВрдиреА рдПрдХрд╛рдЪреНрдпрд╛ рдЬрд╛рдЧреА рджреБрд╕рд░рд╛ рдкрддреНрддрд╛ рдмрджрд▓рддреЛ.

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

flowchart LR
    web["ЁЯЦея╕П web 10.20.0.10<br/>public-a ┬╖ public IP"]
    db["ЁЯЧДя╕П db 10.20.96.15<br/>data-a"]
    rtp["ЁЯкз rt-public<br/>0.0.0.0/0 тЖТ igw-school"]
    rtd["ЁЯкз rt-data<br/>no 0.0.0.0/0"]
    igw["ЁЯЪк igw-school"]
    net["ЁЯМН 93.184.216.34:443"]
    web --> rtp --> igw --> net
    db --> rtd -->|"no route тЖТ dropped"| x["ЁЯЪл"]

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

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

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рдЦрд░реА рд╕реАрдорд╛ route table рдЖрд╣реЗ. рдШрдЯреНрдЯ security group рдЕрд╕рд▓реЗрд▓рд╛, рдкрдг IGW рдХрдбреЗ route рдЖрдгрд┐ public IP рдЕрд╕рд▓реЗрд▓рд╛ database internet рдкрд╛рд╕реВрди рдлрдХреНрдд рдПрдХрд╛ рдирд┐рдпрдо-рдмрджрд▓рд╛рдЪреНрдпрд╛ рдЕрдВрддрд░рд╛рд╡рд░ рдЕрд╕рддреЛ. рдмрд╛рд╣реЗрд░ рдЬрд╛рдгреНрдпрд╛рдЪрд╛ route рдирд╕рд▓реЗрд▓реНрдпрд╛ subnet рдордзреАрд▓ database рдкрд░реНрдпрдВрдд internet рд╡рд░реВрди рдкреЛрд╣реЛрдЪрддрд╛ рдпреЗрдд рдирд╛рд╣реА, рдордЧ рддреНрдпрд╛рдЪрд╛ security group рдХрд╛рд╣реАрд╣реА рдореНрд╣рдгреЛ.

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

Campus.walk(src, dst_ip, proto, port) рдХреНрд░рдорд╛рдиреЗ рддрдкрд╛рд╕рддреЛ: source security group (outbound), source subnet рдЪрд╛ NACL (outbound), рдЖрдгрд┐ рдордЧ route table. Target local рдирд╕реЗрд▓, рддрд░ packet рддреНрдпрд╛ target рдорд╛рд░реНрдЧреЗ "subnet рд╕реЛрдбрддреЛ" рдЖрдгрд┐ walk рд╕рдВрдкрддреЛ. vpc/demo.py рдордзреАрд▓ igw() web рдЖрдгрд┐ db рдирд╛ 93.184.216.34:443 рдкрд░реНрдпрдВрдд рдЪрд╛рд▓рд╡рддреЛ. рд╣реЗ рд╢рд┐рдХрд╡рдгреНрдпрд╛рд╕рд╛рдареАрдЪреЗ model рдЖрд╣реЗ: walk() public IP рддрдкрд╛рд╕рдд рдирд╛рд╣реА тАФ рддреЛ рднрд╛рдЧ рддреБрдореНрд╣рд╛рд▓рд╛ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛рд╡рд╛ рд▓рд╛рдЧреЗрд▓.

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

python3 vpc/demo.py igw
python3 - <<'EOF'
import sys; sys.path.insert(0, "vpc"); from network import RouteTable
from demo import campus, VPC
c = campus()
c.rts["rt-public"] = RouteTable("rt-public", VPC)          # take the gate sign down
print("web without the IGW route:", c.walk("web", "93.184.216.34", "tcp", 443))
c.rts["rt-data"].routes.append(("0.0.0.0/0", "igw-school"))  # a mistake: point data at the gate
print("db with an IGW route:     ", c.walk("db", "93.184.216.34", "tcp", 443)[0])
EOF

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

igw рдЫрд╛рдкрддреЛ:

   web тЖТ internet :443  тЬЕ  ЁЯзН sg-web out тЬУ ┬╖ ЁЯЪж acl-open rule 100 ALLOW ┬╖ ЁЯкз rt-public: 0.0.0.0/0 тЖТ igw-school ┬╖ ЁЯЪк leaves the subnet via igw-school
   db тЖТ internet :443  ЁЯЪл  ЁЯзН sg-db out тЬУ ┬╖ ЁЯЪж acl-data rule 110 ALLOW ┬╖ ЁЯкз no route тЖТ dropped

рддреБрдордЪрд╛ snippet рдЫрд╛рдкрддреЛ web without the IGW route: (False, ['ЁЯзН sg-web out тЬУ', 'ЁЯЪж acl-open rule 100 ALLOW', 'ЁЯкз no route тЖТ dropped']) тАФ рддреЛрдЪ desk, рддреЗрдЪ рд░рдХреНрд╖рдХ, рдкрд╛рдЯреА рдирд╛рд╣реА, internet рдирд╛рд╣реА. рдордЧ db with an IGW route: True: рдПрдХрд╛ рдЪреБрдХреАрдЪреНрдпрд╛ route рдиреЗ data wing "public" рдХреЗрд▓рд╛. (AWS рдордзреНрдпреЗ db рд▓рд╛ рдкреНрд░рддреНрдпрдХреНрд╖ internet рд╢реА рдмреЛрд▓рдгреНрдпрд╛рд╕рд╛рдареА рддрд░реАрд╣реА public IP рд▓рд╛рдЧрд▓рд╛ рдЕрд╕рддрд╛ тАФ model рддреА рддрдкрд╛рд╕рдгреА рд╡рдЧрд│рддреЗ.)

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

"Public" рдореНрд╣рдгрдЬреЗ route table рд╡рд░рдЪреА рдПрдХ рдУрд│. рддреА рдХрд╛рдврд╛ рдЖрдгрд┐ public wing рдмрдВрдж рд╣реЛрддреЛ; рддреА рдЬреЛрдбрд╛ рдЖрдгрд┐ data wing рд╕реБрджреНрдзрд╛ public рд╣реЛрддреЛ.

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

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

Public subnets рдордзреНрдпреЗ рдлрдХреНрдд load balancers рдЖрдгрд┐ NAT gateways рдЕрд╕рддрд╛рдд. Servers рдЖрдгрд┐ databases рдирд╛ public IP рдЕрдЬрд┐рдмрд╛рдд рдирд╕рддреЛ. Public IPs рдЖрдкреЛрдЖрдк рджреЗрдгрд╛рд▒реНрдпрд╛ subnets рд╡рд░ Security Hub рдмреЛрдЯ рдареЗрд╡рддреЛ.

рдЦрд▒реНрдпрд╛ account рд╡рд░ (AWS CLI рдЖрдгрд┐ credentials рд▓рд╛рдЧрддрд╛рдд; IDs рдЙрджрд╛рд╣рд░рдгрд╛рджрд╛рдЦрд▓ рдЖрд╣реЗрдд):

aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway --internet-gateway-id igw-0123456789abcdef0 --vpc-id vpc-0123456789abcdef0
aws ec2 create-route --route-table-id rtb-0aaaaaaaaaaaaaaaa \
    --destination-cidr-block 0.0.0.0/0 --gateway-id igw-0123456789abcdef0
aws ec2 modify-subnet-attribute --subnet-id subnet-0123456789abcdef0 --map-public-ip-on-launch
aws ec2 allocate-address --domain vpc

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

рдкрд╛рдЯреНрдпрд╛ рд╕рд╛рдВрдЧрддрд╛рдд рдХреА packet рдХреБрдареЗ рдЬрд╛рдК рд╢рдХрддреЛ. рдЖрддрд╛: рдХреЛрдг рджрд╛рд░ рдареЛрдард╛рд╡реВ рд╢рдХрддреЛ. Security groups рд╡рд┐рд░реБрджреНрдз NACLs тАФ рдкрд╛рд╣реБрдгреНрдпрд╛рдВрдЪреА рдпрд╛рджреА рдЖрдгрд┐ wing рдЪреЗ рджрд╛рд░.

git checkout lesson-06-sg-vs-nacl

ЁЯЪк Lesson 05 тАФ Internet gateway & public subnets: the front gate

ЁЯУН You are here: Lesson 05 of 12 ┬╖ Previous: lesson-04-route-tables ┬╖ Next: lesson-06-sg-vs-nacl


ЁЯУж What's in this branch

Lessons 01тАУ04, plus the first full campus: campus() in vpc/demo.py builds three wings тАФ public-a, app-a, data-a тАФ with desks web, app and db, and Campus.walk() in vpc/network.py follows one packet out. igw() sends web and db to the internet.

ЁЯзТ Explain like I'm 5

The campus fence has one front gate ЁЯЪк to the city: the internet gateway.

Building a gate is not enough. A wing only uses the gate if its corridor sign says "everything else тЖТ the front gate". The public wing's sign says that. The data wing's sign does not тАФ so a letter from the data wing to the city finds no line and is dropped.

One more thing. When a letter goes out through the gate, the city must be able to write back. A desk with only a campus number (10.20.0.10) has no address the city can use. So a desk that talks to the city also needs a public address тАФ an ordinary public IP or an Elastic IP. The gate swaps one for the other, both ways.

ЁЯЧ║я╕П Diagram

flowchart LR
    web["ЁЯЦея╕П web 10.20.0.10<br/>public-a ┬╖ public IP"]
    db["ЁЯЧДя╕П db 10.20.96.15<br/>data-a"]
    rtp["ЁЯкз rt-public<br/>0.0.0.0/0 тЖТ igw-school"]
    rtd["ЁЯкз rt-data<br/>no 0.0.0.0/0"]
    igw["ЁЯЪк igw-school"]
    net["ЁЯМН 93.184.216.34:443"]
    web --> rtp --> igw --> net
    db --> rtd -->|"no route тЖТ dropped"| x["ЁЯЪл"]

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

тЭУ What

ЁЯдФ Why

Because the route table is the real boundary. A database with a tight security group but a route to the IGW and a public IP is one rule change away from the internet. A database in a subnet with no route out cannot be reached from the internet, whatever its security group says.

ЁЯФз How (in this repo)

Campus.walk(src, dst_ip, proto, port) checks, in order: the source security group (outbound), the source subnet's NACL (outbound), then the route table. If the target is not local, the packet "leaves the subnet via" that target and the walk ends. igw() in vpc/demo.py walks web and db to 93.184.216.34:443. It is a teaching model: walk() does not check for a public IP тАФ that part you must remember.

ЁЯзк Try it

python3 vpc/demo.py igw
python3 - <<'EOF'
import sys; sys.path.insert(0, "vpc"); from network import RouteTable
from demo import campus, VPC
c = campus()
c.rts["rt-public"] = RouteTable("rt-public", VPC)          # take the gate sign down
print("web without the IGW route:", c.walk("web", "93.184.216.34", "tcp", 443))
c.rts["rt-data"].routes.append(("0.0.0.0/0", "igw-school"))  # a mistake: point data at the gate
print("db with an IGW route:     ", c.walk("db", "93.184.216.34", "tcp", 443)[0])
EOF

тЬЕ Verify тАФ what you should see

igw prints:

   web тЖТ internet :443  тЬЕ  ЁЯзН sg-web out тЬУ ┬╖ ЁЯЪж acl-open rule 100 ALLOW ┬╖ ЁЯкз rt-public: 0.0.0.0/0 тЖТ igw-school ┬╖ ЁЯЪк leaves the subnet via igw-school
   db тЖТ internet :443  ЁЯЪл  ЁЯзН sg-db out тЬУ ┬╖ ЁЯЪж acl-data rule 110 ALLOW ┬╖ ЁЯкз no route тЖТ dropped

Your snippet prints web without the IGW route: (False, ['ЁЯзН sg-web out тЬУ', 'ЁЯЪж acl-open rule 100 ALLOW', 'ЁЯкз no route тЖТ dropped']) тАФ same desk, same guards, no sign, no internet. Then db with an IGW route: True: one wrong route made the data wing "public". (In AWS, db would still need a public IP to actually talk to the internet тАФ the model skips that check.)

ЁЯПБ What you just proved

"Public" is one line on a route table. Remove it and the public wing is closed; add it and even the data wing becomes public.

тЪая╕П Common mistakes

ЁЯПн In production

Only load balancers and NAT gateways live in public subnets. Servers and databases have no public IP at all. Security Hub flags subnets that auto-assign public IPs.

On a real account (needs the AWS CLI and credentials; IDs are examples):

aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway --internet-gateway-id igw-0123456789abcdef0 --vpc-id vpc-0123456789abcdef0
aws ec2 create-route --route-table-id rtb-0aaaaaaaaaaaaaaaa \
    --destination-cidr-block 0.0.0.0/0 --gateway-id igw-0123456789abcdef0
aws ec2 modify-subnet-attribute --subnet-id subnet-0123456789abcdef0 --map-public-ip-on-launch
aws ec2 allocate-address --domain vpc

тПня╕П Next

The signs say where a packet may go. Now: who may knock. Security groups vs NACLs тАФ the guest list and the wing door.

git checkout lesson-06-sg-vs-nacl
тЖР Previousroute tablesNext тЖТsg vs nacl

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