Build CoreOrdered learning track

Network ACLs Deep Dive

Learn AWS Networking and Content Delivery - Part 014

Network ACLs secara mendalam sebagai stateless subnet guardrail di Amazon VPC: inbound/outbound rule evaluation, allow/deny semantics, ephemeral ports, subnet association, public/private subnet examples, debugging, anti-patterns, dan governance.

13 min read2476 words
PrevNext
Lesson 1472 lesson track14–39 Build Core
#aws#networking#content-delivery#cloud-architecture+4 more

Part 014 — Network ACLs Deep Dive

Network ACL atau NACL adalah subnet-level stateless filter di Amazon VPC.

Ia terlihat sederhana:

Inbound rules.
Outbound rules.
Allow atau deny.
Rule number.

Tetapi banyak outage VPC terjadi karena engineer lupa satu hal:

NACL tidak menyimpan state koneksi.

Jika inbound request diizinkan, outbound response belum tentu diizinkan.

Jika outbound request diizinkan, inbound response belum tentu diizinkan.

Security Group menyimpan connection state.

NACL tidak.

Karena itu, NACL bukan sekadar “Security Group level subnet”. Ia primitive yang berbeda.

Part ini membahas NACL sebagai coarse subnet guardrail, bukan sebagai tempat utama mendefinisikan semua service dependency.


1. Mental Model: NACL adalah Gate di Boundary Subnet

Security Group menempel ke resource/ENI.

NACL berasosiasi dengan subnet.

Setiap subnet harus punya satu NACL yang aktif.

Satu NACL bisa diasosiasikan ke banyak subnet.

Satu subnet hanya bisa berasosiasi dengan satu NACL pada satu waktu.

Model:

For outbound leaving subnet:

NACL evaluation terjadi saat traffic masuk dan keluar subnet.

Bukan saat traffic bergerak antar host di subnet yang sama dengan cara yang tidak melintasi subnet boundary.

Karena posisinya subnet-level, NACL bagus untuk coarse guardrail:

  • blok CIDR berbahaya;
  • blok port administratif dari internet;
  • enforce subnet class policy;
  • emergency deny saat incident;
  • membatasi subnet tertentu dari destination tertentu;
  • guardrail defense-in-depth di atas Security Group.

NACL buruk untuk service dependency detail:

service-a boleh ke service-b port 8443
service-c tidak boleh ke service-b

Gunakan Security Group untuk dependency graph semacam itu.


2. Stateless: Konsekuensi Paling Penting

Stateless berarti NACL tidak mengingat flow.

Contoh inbound web request:

Client 203.0.113.10:54012 -> Server 10.0.11.25:443
Server 10.0.11.25:443 -> Client 203.0.113.10:54012

NACL public subnet server perlu:

Inbound allow TCP 443 from 203.0.113.10/32 or 0.0.0.0/0
Outbound allow TCP ephemeral range to 203.0.113.10/32 or 0.0.0.0/0

Jika outbound ephemeral response tidak allowed, client timeout.

Diagram:

Ini kebalikan dari Security Group stateful yang otomatis allow return traffic.

Stateless design menghasilkan prinsip:

Every allowed conversation needs two NACL paths:
1. request direction
2. response direction

3. Rule Number: First Match Wins

NACL rule punya nomor 1 sampai 32766.

AWS mengevaluasi rule dari nomor terkecil ke terbesar.

Begitu packet match satu rule, evaluasi berhenti.

Artinya rule ordering adalah policy.

Contoh:

100 DENY  TCP 22 from 0.0.0.0/0
110 ALLOW TCP 22 from 203.0.113.10/32

Hasil:

203.0.113.10 tetap denied untuk TCP 22

Karena rule 100 match lebih dulu.

Urutan benar:

100 ALLOW TCP 22 from 203.0.113.10/32
110 DENY  TCP 22 from 0.0.0.0/0

Tetapi untuk admin access, sebaiknya jangan bergantung pada NACL saja.

Gunakan SSM/Verified Access/VPN/bastion dengan SG ketat.

NACL rule number best practice:

100 baseline allow/deny penting
200 subnet class rules
300 temporary controlled exceptions
400 partner network rules
900 broad allow if required
*   implicit deny

Tinggalkan gap angka agar bisa insert rule.

Jangan membuat rule berurutan 100,101,102 tanpa ruang untuk perubahan.


4. Explicit Deny dan Implicit Deny

NACL mendukung ALLOW dan DENY.

Jika packet tidak match rule manapun, rule * implicit deny berlaku.

Contoh custom NACL baru sering tampak “mati” karena belum ada allow rule.

Inbound:
* DENY ALL

Outbound:
* DENY ALL

Default NACL VPC biasanya allow all inbound/outbound.

Custom NACL default deny sampai kamu menambahkan rule.

Ini membuat custom NACL berguna sebagai strict subnet boundary, tetapi juga berbahaya jika diasosiasikan prematur.

Praktik aman:

1. Buat NACL baru.
2. Tambahkan inbound/outbound rules lengkap.
3. Validasi di non-prod.
4. Associate ke subnet kecil dulu.
5. Monitor Flow Logs dan health check.
6. Baru rollout ke subnet lain.

Jangan associate custom NACL kosong ke subnet production.


5. NACL dan Ephemeral Ports

Ephemeral port adalah port sementara yang dipakai client side connection.

Server port biasanya well-known:

HTTPS server: 443
PostgreSQL server: 5432
Redis server: 6379

Client port biasanya ephemeral:

49152
53044
61000

Range ephemeral bisa berbeda tergantung OS dan konfigurasi.

Contoh Linux modern sering memakai range seperti 32768-60999, tetapi jangan mengandalkan satu angka universal tanpa memeriksa OS/workload.

Dalam NACL, kamu sering melihat allow ephemeral broad:

TCP 1024-65535

Itu bukan karena aplikasi listen di semua port.

Itu karena response traffic perlu kembali ke client ephemeral port.

5.1 Public Web Server NACL

Inbound:

ALLOW TCP 443 from 0.0.0.0/0
ALLOW TCP 80  from 0.0.0.0/0 if needed for redirect

Outbound:

ALLOW TCP 1024-65535 to 0.0.0.0/0

Karena server membalas ke ephemeral port client.

5.2 Private App Calling External HTTPS via NAT

Private app subnet outbound:

ALLOW TCP 443 to 0.0.0.0/0 or NAT path destination model

Private app subnet inbound:

ALLOW TCP 1024-65535 from NAT/public path response source

NAT subnet NACL juga perlu allow traffic yang sesuai.

Jika salah satu arah lupa, app timeout.

5.3 App Calling Database

App subnet outbound:

ALLOW TCP 5432 to DB subnet CIDR

App subnet inbound:

ALLOW TCP ephemeral from DB subnet CIDR

DB subnet inbound:

ALLOW TCP 5432 from App subnet CIDR

DB subnet outbound:

ALLOW TCP ephemeral to App subnet CIDR

Dengan Security Group, kita cukup bicara app SG -> db SG TCP/5432.

Dengan NACL, kita harus bicara subnet CIDR dan dua arah.

Itulah kenapa NACL tidak nyaman untuk fine-grained service access.


6. Public Subnet NACL Pattern

Public subnet biasanya menampung:

  • ALB public;
  • NAT Gateway;
  • bastion legacy;
  • public NLB;
  • public-facing reverse proxy;
  • edge appliances.

NACL public subnet harus mendukung:

  • inbound client traffic ke public entrypoint;
  • outbound response ephemeral;
  • health checks jika relevan;
  • NAT traffic jika NAT Gateway berada di subnet tersebut;
  • admin access hanya jika memang ada resource admin.

Contoh untuk public ALB-only subnet:

Inbound:

100 ALLOW TCP 443 from 0.0.0.0/0
110 ALLOW TCP 80  from 0.0.0.0/0    # optional redirect only
120 ALLOW TCP 1024-65535 from app/private CIDR if needed for responses/checks depending path
*   DENY ALL

Outbound:

100 ALLOW TCP 1024-65535 to 0.0.0.0/0  # response to internet clients
110 ALLOW TCP 8080 to app subnet CIDR   # ALB to targets if targets private
*   DENY ALL

Tetapi hati-hati: ALB health checks, client behavior, target port, and response path harus disesuaikan.

NACL terlalu ketat tanpa observability sering menyebabkan health check failure.

Untuk public subnet dengan NAT Gateway, rule bisa lebih broad karena NAT harus melayani banyak outbound private workloads.

Jika kamu ingin egress filtering detail, jangan berharap NACL public NAT subnet cukup.

Gunakan Network Firewall/egress proxy/DNS Firewall/PrivateLink pattern.


7. Private App Subnet NACL Pattern

Private app subnet biasanya menerima traffic dari ALB/internal service dan keluar ke DB/endpoints/NAT.

Baseline app subnet:

Inbound:

100 ALLOW TCP app-port from ALB subnet CIDR or upstream subnet CIDR
110 ALLOW TCP ephemeral from DB subnet CIDR / NAT response / endpoint response as needed
*   DENY ALL

Outbound:

100 ALLOW TCP db-port to DB subnet CIDR
110 ALLOW TCP 443 to endpoint subnet CIDR or NAT path
120 ALLOW TCP ephemeral to upstream subnet CIDR if app is server responding
*   DENY ALL

NACL berbasis CIDR, bukan SG.

Karena itu, jika app subnet menampung banyak service, NACL tidak bisa membedakan service A dan B di subnet yang sama.

Jika service A dan B butuh policy sangat berbeda, pertimbangkan:

  • pisah subnet;
  • pisah SG;
  • VPC Lattice/service mesh untuk higher-level policy;
  • Network Firewall jika perlu inspection;
  • account/VPC segmentation.

Subnet adalah security grouping kasar.

Jangan isi satu subnet dengan workload yang butuh boundary sangat berbeda lalu berharap NACL menyelesaikannya.


8. Isolated Database Subnet NACL Pattern

Database subnet biasanya tidak butuh inbound dari internet.

DB subnet menerima dari app subnet dan mengirim response.

Contoh PostgreSQL:

Inbound:

100 ALLOW TCP 5432 from app subnet CIDR
*   DENY ALL

Outbound:

100 ALLOW TCP 1024-65535 to app subnet CIDR
110 ALLOW TCP 443 to backup/monitoring endpoint path if required
*   DENY ALL

Namun jangan lupa managed database behavior.

RDS, Aurora, managed backup, monitoring, replication, DNS, control plane integration punya behavior yang tidak selalu identik dengan EC2 manual database.

NACL terlalu ketat di subnet database bisa merusak:

  • DB connectivity;
  • replication;
  • backup/restore path;
  • monitoring;
  • patching operations;
  • managed service health.

Untuk managed services, baca service-specific networking guidance.

Security Group biasanya menjadi primary control untuk DB inbound.

NACL menjadi subnet-level guardrail:

No internet-originated traffic.
Only app subnet CIDR can reach DB port.
Only expected return/management traffic leaves.

9. NACL untuk Deny Guardrail

Karena NACL mendukung explicit deny, ia berguna untuk guardrail yang harus berlaku meskipun SG salah.

Contoh:

Deny TCP 22 from 0.0.0.0/0 on public subnets.
Deny TCP 3389 from 0.0.0.0/0 on public subnets.
Deny known malicious CIDR.
Deny outbound to forbidden partner/network.
Deny all internet-originated traffic to database subnet.

Namun deny harus dipakai hati-hati.

Deny broad yang salah urutan bisa memutus traffic sah.

Contoh incident:

100 DENY TCP 1024-65535 to 0.0.0.0/0
110 ALLOW TCP 443 to partner-api

Jika response dari partner memakai source 443 ke client ephemeral, apakah rule ini memblok arah yang benar? Tergantung inbound/outbound dan packet direction.

NACL deny rule harus ditulis dengan packet direction aktual, bukan bahasa manusia “block partner”.

Untuk deny kompleks, sering lebih tepat memakai Network Firewall atau proxy.


10. NACL dan NAT Gateway

NAT Gateway sering berada di public subnet.

Private subnet route:

0.0.0.0/0 -> NAT Gateway

Public NAT subnet route:

0.0.0.0/0 -> Internet Gateway

NACL yang terlalu ketat di private subnet atau NAT public subnet bisa memutus egress.

Mental model outbound private app ke internet:

Jika private app NACL outbound allow 443 tetapi inbound tidak allow ephemeral response, app timeout.

Jika NAT subnet NACL outbound allow 443 tetapi inbound response ephemeral tidak allowed, app timeout.

Jika kamu ingin hemat energi debugging, jangan mulai dengan NACL terlalu strict di subnet NAT.

Mulai dari SG/route correctness, lalu tambah NACL guardrail bertahap dengan Flow Logs.


11. NACL dan Load Balancer

11.1 ALB Public Subnet

ALB menerima client traffic dan mengirim ke targets.

Packet directions:

Client -> ALB listener port
ALB -> Client ephemeral response
ALB -> Target target-port
Target -> ALB ephemeral response

NACL public subnet ALB harus mengizinkan:

  • inbound listener ports dari client;
  • outbound ephemeral ke client;
  • outbound target port ke target subnet;
  • inbound ephemeral response dari target subnet.

Jika target health check gagal padahal SG benar, periksa NACL di kedua subnet.

11.2 Target Private Subnet

Target menerima dari ALB dan membalas.

Private target subnet NACL:

Inbound allow target-port from ALB subnet CIDR
Outbound allow ephemeral to ALB subnet CIDR

Namun jika application melakukan outbound dependencies, tambahkan rule sesuai kebutuhan.

11.3 NLB

NLB behavior bisa berbeda terutama source IP preservation.

Jika target melihat client source IP asli, NACL target subnet harus allow dari client CIDR, bukan hanya NLB subnet CIDR.

Jangan asumsikan ALB pattern berlaku untuk NLB.

Selalu validasi:

  • source IP di target;
  • target type;
  • client IP preservation;
  • health check source;
  • internal vs public NLB;
  • SG support/behavior untuk NLB yang digunakan.

12. NACL dan VPC Peering/TGW/Hybrid

NACL mengevaluasi source/destination CIDR.

Untuk traffic dari VPC peering, Transit Gateway, VPN, Direct Connect, atau Cloud WAN, NACL tidak peduli “attachment identity”.

Ia melihat packet address.

Contoh:

On-prem 172.16.20.0/24 -> App subnet 10.20.11.0/24 TCP 443

App subnet NACL inbound:

ALLOW TCP 443 from 172.16.20.0/24

Outbound:

ALLOW TCP 1024-65535 to 172.16.20.0/24

Jika on-prem client ephemeral range terbatas, kamu bisa lebih ketat.

Jika tidak tahu, broad ephemeral range sering diperlukan.

NACL tidak bisa berkata:

allow from this Transit Gateway attachment only

Ia berkata:

allow from this CIDR/protocol/port/direction

Untuk segmentation berbasis attachment/domain, gunakan Transit Gateway route table, AWS Network Firewall, Cloud WAN segment policy, atau service-level controls.


13. NACL Tidak Memfilter Beberapa Reserved Service Path

Ada traffic tertentu di VPC yang tidak difilter oleh NACL seperti traffic normal, misalnya beberapa reserved VPC services seperti AmazonProvidedDNS/Route 53 Resolver, DHCP, instance metadata, time sync, dan reserved VPC router addresses.

Konsekuensi:

NACL bukan alat utama untuk memblok DNS ke Route 53 Resolver.
NACL bukan alat utama untuk mengontrol IMDS.

Gunakan control yang sesuai:

  • Route 53 Resolver DNS Firewall untuk DNS domain control;
  • IMDSv2 dan instance metadata options untuk metadata access;
  • IAM role scoping untuk credential blast radius;
  • host firewall/agent jika butuh host-level enforcement;
  • Network Firewall/proxy untuk traffic inspection.

Jangan membuat compliance claim yang salah:

Kami memblok semua DNS via NACL.

Itu tidak akurat untuk Route 53 Resolver special path.


14. Path MTU Discovery dan ICMP

NACL yang terlalu ketat sering memblok ICMP sepenuhnya.

Ini bisa mengganggu Path MTU Discovery.

Gejala:

  • koneksi kecil berhasil;
  • transfer besar hang;
  • TLS handshake kadang gagal;
  • gRPC stream bermasalah;
  • VPN/hybrid path mengalami fragmentation issue.

Jangan otomatis blok semua ICMP tanpa memahami dampaknya.

Untuk IPv6, ICMPv6 jauh lebih fundamental untuk neighbor discovery dan path behavior.

Security posture yang matang bukan berarti “deny semua ICMP”.

Ia berarti allow ICMP type/code yang diperlukan dan monitor abuse.


15. NACL vs Host Firewall

NACL bekerja di subnet boundary.

Host firewall bekerja di OS.

Security Group bekerja di ENI/resource boundary.

Ketiganya bisa overlap.

Jika connection gagal:

NACL allow
SG allow
OS firewall deny

Hasil tetap gagal.

Jika:

NACL deny
SG allow
OS firewall allow

Hasil tetap gagal.

Debugging harus mengevaluasi semua layer.

Host firewall berguna untuk:

  • defense-in-depth pada instance;
  • process-level/local policy;
  • eBPF/agent-based enforcement;
  • non-AWS portability;
  • emergency block inside host.

Tetapi jangan menjadikan host firewall satu-satunya kontrol di AWS ketika SG/NACL/IAM bisa dikelola secara cloud-native dan terpusat.


16. NACL sebagai Emergency Brake

Karena NACL punya explicit deny dan bisa berlaku di seluruh subnet, ia bisa menjadi emergency brake saat incident.

Contoh:

Block outbound from compromised subnet to 198.51.100.0/24
Block inbound from malicious CIDR to public subnet
Block database subnet access except from known app CIDR

Tetapi emergency brake punya risiko:

  • salah subnet berdampak luas;
  • rule ordering salah;
  • response traffic ikut terblok;
  • health checks gagal;
  • rollback manual lambat;
  • rule temporary menjadi permanen.

Incident playbook harus punya:

1. Pre-approved emergency NACL templates.
2. Break-glass IAM role.
3. Change log/ticket linkage.
4. Fast rollback command.
5. Flow Logs dashboard.
6. Owner notification.
7. Post-incident cleanup.

NACL emergency deny harus seperti circuit breaker: cepat, jelas, reversible.

Bukan patch permanen tanpa desain.


17. Common Anti-Patterns

17.1 Menggunakan NACL untuk Semua Microservice Policy

service-a subnet allow service-b subnet port 8443
service-c subnet deny service-b subnet

Jika banyak service berbagi subnet, NACL tidak bisa membedakan per service.

Gunakan SG reference.

17.2 Lupa Ephemeral Return

Inbound allow 443, outbound deny ephemeral.

Hasil: client timeout.

17.3 Custom NACL Kosong di Production

Custom NACL default deny all.

Associate tanpa rules = subnet outage.

17.4 Rule Order Salah

Deny broad sebelum allow specific.

Hasil: traffic sah terblok.

17.5 Public Subnet NACL Terlalu Broad Tanpa Alasan

ALLOW ALL inbound 0.0.0.0/0
ALLOW ALL outbound 0.0.0.0/0

Jika hanya ingin default behavior, mungkin default NACL sudah cukup.

Jika ingin guardrail, tulis guardrail yang bermakna.

17.6 Mengira NACL Bisa Reference SG

NACL rule memakai CIDR/protocol/port, bukan SG identity.

Jika workload autoscaling berubah IP dalam subnet, NACL tetap subnet-level.

17.7 Mengabaikan IPv6

Menambahkan IPv6 route tetapi NACL hanya diaudit IPv4.

IPv6 rules harus direview separately.


18. Debugging NACL Issue

Gejala NACL issue biasanya timeout/drop.

Runbook:

1. Tentukan source IP dan port.
2. Tentukan destination IP dan port.
3. Tentukan arah request.
4. Tentukan arah response.
5. Identifikasi subnet source dan subnet destination.
6. Check outbound NACL source subnet untuk request.
7. Check inbound NACL destination subnet untuk request.
8. Check outbound NACL destination subnet untuk response.
9. Check inbound NACL source subnet untuk response.
10. Check SG source outbound dan destination inbound.
11. Check route table dua arah.
12. Check Flow Logs REJECT.

Format worksheet:

Conversation: client 10.0.21.10:53044 -> db 10.0.31.20:5432

Request path:
- source subnet outbound: allow TCP 5432 to 10.0.31.20/32 or DB subnet CIDR?
- destination subnet inbound: allow TCP 5432 from 10.0.21.10/32 or app subnet CIDR?

Response path:
- destination subnet outbound: allow TCP 53044 to app subnet CIDR?
- source subnet inbound: allow TCP 53044 from DB subnet CIDR?

If unknown client ephemeral:

Use ephemeral range required by source OS/client population.

Do not debug NACL with vague language like:

DB allows app.

Translate into packet tuple:

src IP, src port, dst IP, dst port, protocol, direction, subnet boundary.

19. Flow Logs untuk NACL

VPC Flow Logs bisa membantu melihat ACCEPT dan REJECT.

Contoh:

REJECT TCP 10.0.21.10 10.0.31.20 53044 5432

Interpretasi awal:

  • request dari app ke DB ditolak;
  • cek source outbound NACL;
  • cek destination inbound NACL;
  • cek SG outbound/inbound;
  • cek route.

Contoh response drop:

REJECT TCP 10.0.31.20 10.0.21.10 5432 53044

Interpretasi:

  • DB mencoba membalas ke ephemeral port app;
  • cek DB subnet outbound NACL;
  • cek app subnet inbound NACL.

Flow Logs tidak selalu langsung memberi “NACL rule 120 yang salah”.

Ia memberi evidence packet tuple.

Kamu tetap harus memetakan tuple ke rule.


20. Production NACL Governance

NACL harus dikelola seperti policy artifact.

Minimal:

[ ] NACL didefinisikan di IaC.
[ ] Rule number punya convention.
[ ] Description/tag menjelaskan intent.
[ ] No manual console change kecuali break-glass.
[ ] Pre-prod validation untuk subnet class baru.
[ ] Flow Logs enabled pada subnet kritikal.
[ ] Rule review berkala.
[ ] IPv4 dan IPv6 rules diaudit.
[ ] Emergency deny punya TTL dan rollback.

NACL naming:

prod-public-edge-nacl
prod-private-app-nacl
prod-private-data-nacl
prod-inspection-nacl
prod-shared-endpoint-nacl

Jangan:

nacl-1
custom-nacl
test-new
prod-allow

NACL adalah bagian dari network contract.

Namanya harus mencerminkan subnet class.


21. Design Decision: Kapan NACL Dibuat Ketat?

Tidak semua environment butuh NACL super ketat dari hari pertama.

Strategi bertahap:

Level 0 — Default NACL

Default allow all, rely on SG.

Cocok untuk:

  • learning environment;
  • early dev;
  • fast prototyping.

Risiko:

  • tidak ada subnet-level guardrail.

Level 1 — Guardrail Deny

Allow broad, deny known dangerous ports/sources.

Cocok untuk:

  • general production awal;
  • tim kecil;
  • SG sudah disiplin.

Level 2 — Subnet-Class Policy

Public subnet, app subnet, data subnet punya NACL berbeda.

Cocok untuk:

  • mature production;
  • regulated systems;
  • multi-team platform.

Level 3 — Strict Egress/Ingress Matrix

Explicit allow per subnet class and known dependency path.

Cocok untuk:

  • high assurance;
  • strict compliance;
  • limited, stable dependencies.

Risiko:

  • high operational overhead;
  • false outages saat dependency berubah;
  • sulit untuk dynamic workload.

Top-tier engineer tidak otomatis memilih paling strict.

Mereka memilih level yang sesuai risiko, kemampuan operasi, dan perubahan sistem.


22. NACL dengan Terraform/IaC: Prinsip Praktis

NACL manual rentan drift.

Di Terraform/CloudFormation/CDK, prinsipnya:

1. Define NACL per subnet class.
2. Keep rule numbers deterministic.
3. Keep comments/descriptions close to rule definitions.
4. Avoid generated random rule order.
5. Separate emergency overlay carefully.
6. Test plan diff before apply.

Pseudo Terraform style:

resource "aws_network_acl" "private_app" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name        = "prod-private-app-nacl"
    Environment = "prod"
    ManagedBy   = "terraform"
  }
}

resource "aws_network_acl_rule" "private_app_inbound_from_alb" {
  network_acl_id = aws_network_acl.private_app.id
  rule_number    = 100
  egress         = false
  protocol       = "tcp"
  rule_action    = "allow"
  cidr_block     = var.public_alb_subnet_cidr
  from_port      = 8080
  to_port        = 8080
}

Tetapi jangan percaya IaC saja.

IaC bisa membuat policy salah dengan sangat konsisten.

Butuh review packet tuple.


23. Worked Example: ALB to App to DB

Subnets:

public-alb-a: 10.0.1.0/24
private-app-a: 10.0.11.0/24
private-db-a: 10.0.21.0/24

Traffic:

Internet client -> ALB TCP 443
ALB -> App TCP 8080
App -> DB TCP 5432

23.1 Public ALB NACL

Inbound:

100 ALLOW TCP 443 from 0.0.0.0/0
110 ALLOW TCP 1024-65535 from 10.0.11.0/24  # app response to ALB-originated target calls if applicable
*   DENY ALL

Outbound:

100 ALLOW TCP 1024-65535 to 0.0.0.0/0       # response to internet clients
110 ALLOW TCP 8080 to 10.0.11.0/24          # ALB to app target
*   DENY ALL

23.2 Private App NACL

Inbound:

100 ALLOW TCP 8080 from 10.0.1.0/24         # ALB to app
110 ALLOW TCP 1024-65535 from 10.0.21.0/24  # DB response to app
*   DENY ALL

Outbound:

100 ALLOW TCP 1024-65535 to 10.0.1.0/24     # app response to ALB
110 ALLOW TCP 5432 to 10.0.21.0/24          # app to DB
*   DENY ALL

23.3 Private DB NACL

Inbound:

100 ALLOW TCP 5432 from 10.0.11.0/24        # app to DB
*   DENY ALL

Outbound:

100 ALLOW TCP 1024-65535 to 10.0.11.0/24    # DB response to app
*   DENY ALL

This example is intentionally simplified.

Real systems may need:

  • health check source handling;
  • monitoring/logging egress;
  • backup paths;
  • SSM endpoints;
  • OS package update paths;
  • DNS behavior;
  • IPv6 rules;
  • multi-AZ CIDR duplicates;
  • managed service-specific requirements.

Do not copy blindly.

Use it as packet reasoning template.


24. Small Lab: Break and Fix NACL Ephemeral Response

Tujuan: melihat stateless behavior secara nyata.

Setup:

client EC2 in subnet A
server EC2 in subnet B
server listens on TCP 8080
SG allows client -> server TCP 8080
routes are correct

NACL subnet B inbound:

ALLOW TCP 8080 from subnet A CIDR

NACL subnet B outbound:

DENY ALL

Test:

curl http://server-private-ip:8080

Expected:

timeout

Because request reaches server, but response cannot leave subnet B.

Fix:

NACL subnet B outbound:
ALLOW TCP 1024-65535 to subnet A CIDR

Retest.

Then check Flow Logs to see rejected response before fix.

Lesson:

NACL requires request and response paths.

25. Final Mental Model

NACL adalah stateless subnet-level allow/deny guardrail.

Ia bagus untuk:

  • coarse subnet boundary;
  • explicit deny;
  • emergency block;
  • defense-in-depth;
  • public/private/data subnet class policy;
  • reducing blast radius when SG is misconfigured.

Ia tidak bagus untuk:

  • service-level dependency graph;
  • dynamic autoscaling identity;
  • fine-grained workload policy in same subnet;
  • layer-7 filtering;
  • DNS domain control;
  • replacing Security Groups;
  • replacing Network Firewall/WAF/IAM.

Kalimat pegangan:

Security Group asks: may this resource talk?
NACL asks: may this packet enter or leave this subnet?
Route table asks: where should this packet go?

Jika kamu debug NACL, jangan mulai dari service name.

Mulai dari packet tuple:

protocol, source IP, source port, destination IP, destination port, direction, subnet boundary.

Setelah itu baru cocokkan ke rule number.

Engineer yang matang tidak membuat NACL ketat hanya agar terlihat secure.

Mereka membuat NACL yang sesuai risiko, bisa dijelaskan, bisa dioperasikan, dan bisa dibuktikan dengan observability.


Referensi Resmi

Lesson Recap

You just completed lesson 14 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.