Series MapLesson 17 / 35
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Build CoreOrdered learning track

Security Hardening

Security Hardening for NGINX Edge and Reverse Proxy

Memahami request limits, header limits, method restriction, path protection, Host header risk, SSRF mitigation, security headers, dan secure default server.

9 min read1603 words
PrevNext
Lesson 1735 lesson track07–19 Build Core
#security#hardening#headers#host-header+3 more

Part 017 — Security Hardening for NGINX Edge and Reverse Proxy

1. Tujuan Part Ini

NGINX sering berada di posisi yang sangat sensitif:

client / partner / browser / automation
        ↓
DNS / load balancer
        ↓
NGINX / Ingress
        ↓
Java/JAX-RS service

Artinya, NGINX adalah salah satu layer pertama yang melihat request sebelum request masuk ke aplikasi.

Security hardening di NGINX bukan pengganti secure coding di Java/JAX-RS. Hardening di NGINX adalah defense layer untuk:

membatasi input buruk sebelum masuk aplikasi
menutup default exposure
mengurangi blast radius
menjaga trust boundary
membuat failure lebih cepat dan lebih jelas
memberi observability terhadap traffic abnormal

Part ini membahas NGINX sebagai security control di edge/reverse proxy/ingress layer.

Fokusnya bukan sekadar menambahkan banyak header security. Fokusnya adalah memahami:

apa yang harus ditolak di proxy
apa yang harus tetap divalidasi di aplikasi
apa yang tidak boleh dipercaya dari client
apa yang perlu dilog
apa yang tidak boleh dilog
apa yang harus diverifikasi di platform/internal team

2. Mental Model: NGINX Security Boundary

NGINX bisa melakukan beberapa jenis kontrol:

KontrolContohCocok di NGINX?Tetap perlu di aplikasi?
Request size limitclient_max_body_sizeYaYa, untuk domain limit
Header size limitlarge header protectionYaYa, untuk semantic validation
Method restrictionhanya GET/POST/PUT/PATCH/DELETEYaYa
Path denylistblock /.git, /admin, /actuatorYaYa
Security headersHSTS, CSP, frame optionsYaKadang
Rate limitingper IP / keyYaYa, untuk user/tenant-aware
Auth delegationauth_requestKadangYa
Authorization business rulerole/permission/domain ruleTidak idealYa
Input validationJSON schema, field semanticsTidakYa
Tenant isolationtenant ownership checkTidakYa
Audit decisionwho did whatTidak cukupYa

Prinsip utamanya:

NGINX can reject obviously bad traffic.
Application must still enforce business truth.

Jangan pernah menganggap request aman hanya karena sudah lewat NGINX.


3. Request Hardening Lifecycle

Lifecycle security sederhana:

sequenceDiagram participant C as Client participant LB as Load Balancer participant N as NGINX participant A as Java/JAX-RS App C->>LB: Request LB->>N: Forward request N->>N: Select server/location N->>N: Validate size, method, path, headers N->>N: Apply TLS/security/header/rate policy alt Request rejected at edge N-->>C: 4xx / 429 else Request accepted N->>A: Forward sanitized/proxied request A->>A: AuthZ, domain validation, business rules A-->>N: Response N-->>C: Response with security headers/logging end

Security decision bisa terjadi di beberapa layer. Yang berbahaya adalah ketika tiap layer berasumsi layer lain sudah melakukan validasi.

Contoh anti-pattern:

NGINX assumes app validates Host.
App assumes NGINX validates Host.
Neither validates Host correctly.

Hasilnya bisa berupa host header injection, wrong redirect, poisoned absolute URL, atau exposure environment internal.


4. Secure Default Server

NGINX harus punya default server yang aman.

Masalah umum:

request dengan Host tidak dikenal tetap masuk ke aplikasi default
certificate wildcard membuat hostname salah tetap terlihat valid
crawler menemukan endpoint internal dari IP publik
health/admin endpoint terbuka karena default route terlalu permisif

Contoh pola default server:

server {
    listen 80 default_server;
    server_name _;

    return 444;
}

server {
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/certs/default.crt;
    ssl_certificate_key /etc/nginx/certs/default.key;

    return 444;
}

Catatan:

444 adalah NGINX-specific behavior untuk menutup koneksi tanpa response.
Tidak semua organisasi menyukai ini.
Beberapa memilih 400 atau 404 agar lebih observable.

Untuk enterprise environment, keputusan ini harus selaras dengan observability dan security policy.

Kubernetes Ingress equivalent

Di Kubernetes, default behavior bisa berasal dari:

default backend ingress controller
Ingress tanpa host
wildcard host rule
catch-all path
cloud load balancer default target

Jangan hanya mengecek Ingress milik service sendiri. Cek controller-level default backend juga.


5. Host Header Hardening

Host header adalah input dari client.

Ia memengaruhi:

virtual host selection
absolute redirect URL
URI generation
CORS origin logic
password reset link
callback URL
OpenAPI/server URL
multi-tenant routing

Risiko Host header injection:

client sends Host: attacker.example.com
backend builds absolute URL from Host
email/reset/callback points to attacker domain

NGINX harus membatasi hostname yang valid.

Contoh:

server {
    listen 443 ssl;
    server_name api.example.com;

    if ($host != "api.example.com") {
        return 400;
    }

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_pass http://jaxrs_upstream;
    }
}

Namun hati-hati dengan if di NGINX. Untuk banyak kasus, lebih aman memakai server block eksplisit dan default server yang menolak unknown host.

Lebih baik:

server {
    listen 443 ssl default_server;
    server_name _;
    return 400;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    location / {
        proxy_set_header Host api.example.com;
        proxy_set_header X-Forwarded-Host api.example.com;
        proxy_pass http://jaxrs_upstream;
    }
}

Dampak ke Java/JAX-RS

Backend Java/JAX-RS sering memakai request context untuk membangun URI:

uriInfo.getBaseUri()
uriInfo.getAbsolutePath()
Response.created(uri).build()

Jika proxy header salah, aplikasi bisa menghasilkan:

http://internal-service:8080/...
https://wrong-host/...
http instead of https
wrong tenant domain
wrong redirect after login

Hardening NGINX harus dipasangkan dengan konfigurasi trusted proxy di aplikasi/framework.


6. Request Size Limit

Request size harus dibatasi di edge.

Tanpa batas, attacker atau client salah konfigurasi bisa mengirim body besar dan menyebabkan:

memory pressure
disk temporary file penuh
worker sibuk membaca upload lambat
upstream Java thread tertahan
413 tidak konsisten antar layer

Directive utama:

client_max_body_size 10m;

Contoh per route:

server {
    listen 443 ssl;
    server_name api.example.com;

    client_max_body_size 1m;

    location /api/v1/documents/upload {
        client_max_body_size 50m;
        proxy_pass http://jaxrs_upstream;
    }

    location / {
        proxy_pass http://jaxrs_upstream;
    }
}

Mental model:

default kecil
exception eksplisit
exception punya justifikasi domain
exception punya observability
exception punya test

Kubernetes Ingress

Di ingress-nginx, body size sering dikontrol via annotation seperti:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"

Nama annotation bergantung controller. Jangan copy annotation tanpa memastikan controller yang digunakan.

Dampak ke Java/JAX-RS

Aplikasi tetap harus punya limit sendiri:

multipart max size
JSON body max size
file type validation
content-type validation
domain-specific attachment policy
virus/malware scanning jika relevan

NGINX limit adalah perimeter limit, bukan domain validation.


7. Header Size Limit

Header besar bisa muncul dari:

JWT terlalu besar
cookie membengkak
trace baggage terlalu panjang
client mengirim header sampah
bot/fuzzer mengirim header ekstrem

NGINX perlu mengatur buffer header agar request abnormal tidak menghabiskan resource.

Contoh directive yang sering terkait:

client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

Risiko limit terlalu kecil:

valid user gagal karena cookie/JWT besar
SSO/OIDC redirect gagal
trace context terpotong/tidak diterima

Risiko limit terlalu besar:

memory overhead naik
attack surface membesar
header bloat tidak terdeteksi

Senior engineer harus membaca header size bukan hanya sebagai tuning teknis, tetapi sebagai sinyal desain:

Kenapa JWT sebesar itu?
Kenapa cookie menyimpan terlalu banyak data?
Kenapa baggage telemetry terlalu panjang?
Apakah ada header internal yang bocor ke client?

8. Method Restriction

Tidak semua endpoint harus menerima semua method.

Risiko method terlalu terbuka:

TRACE enabled unintentionally
unexpected PUT/DELETE reaches app
CORS preflight behavior kacau
crawler/fuzzer mendapat response terlalu informatif

Contoh pembatasan:

location /api/ {
    limit_except GET POST PUT PATCH DELETE OPTIONS {
        deny all;
    }

    proxy_pass http://jaxrs_upstream;
}

Atau dengan map:

map $request_method $method_allowed {
    default 0;
    GET     1;
    POST    1;
    PUT     1;
    PATCH   1;
    DELETE  1;
    OPTIONS 1;
}

server {
    location /api/ {
        if ($method_allowed = 0) {
            return 405;
        }

        proxy_pass http://jaxrs_upstream;
    }
}

Namun jangan membuat method policy di NGINX yang bertentangan dengan aplikasi.

Contoh failure:

JAX-RS endpoint mendukung PATCH
NGINX hanya allow GET/POST/PUT/DELETE
Client menerima 405 dari NGINX
Application log tidak menunjukkan request

Untuk API enterprise, method policy harus masuk PR checklist.


9. Dangerous Path Blocking

NGINX sebaiknya menolak path yang jelas tidak boleh diakses dari luar.

Contoh:

location ~* /(\.git|\.svn|\.hg|\.env|Dockerfile|docker-compose\.ya?ml)$ {
    return 404;
}

location ~* /(?:actuator|metrics|debug|admin|internal)(?:/|$) {
    return 404;
}

Tetapi hati-hati: block list bukan primary security.

Lebih baik:

hanya expose path yang memang public
admin/internal endpoint berada di network berbeda
authZ tetap di aplikasi
service management endpoint tidak diroute via public ingress

Java/JAX-RS context

JAX-RS service mungkin punya endpoint:

/api/v1/quotes
/api/v1/orders
/internal/reindex
/admin/retry
/health
/metrics
/openapi

Tidak semua endpoint boleh keluar melalui public edge.

Internal endpoint exposure adalah salah satu kesalahan paling mahal di enterprise platform.


10. Path Traversal and Path Normalization Awareness

NGINX dan upstream bisa berbeda dalam melihat path.

Contoh input berbahaya:

/..%2fadmin
/%2e%2e/%2e%2e/etc/passwd
/api//v1///quotes
/api/v1/%2e%2e/internal

Risiko muncul jika:

NGINX melakukan normalization berbeda dari aplikasi
rewrite mengubah path sebelum validasi
backend framework decode path lagi
upstream menerima path yang sudah terlihat aman di proxy

Prinsip:

Do not rely only on proxy path normalization for application security.

NGINX dapat membantu menolak pola yang jelas buruk, tetapi aplikasi tetap harus melakukan authorization berdasarkan resource, bukan hanya path string.


11. Header Spoofing and Trusted Forwarded Headers

Header seperti ini sering dipakai untuk menentukan identitas request:

X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Proto
X-Real-IP
Forwarded
X-Request-ID
X-Correlation-ID
X-User-ID
X-Tenant-ID
X-Client-Cert

Masalahnya: client juga bisa mengirim header tersebut.

NGINX harus membedakan:

header dari client tidak trusted
header dari trusted proxy bisa trusted
header identity internal harus dihapus sebelum di-set ulang

Contoh pola aman:

location / {
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP         $remote_addr;

    proxy_set_header X-User-ID "";
    proxy_set_header X-Tenant-ID "";

    proxy_pass http://jaxrs_upstream;
}

Jika NGINX menerima identity dari external auth service, header harus di-set hanya setelah auth berhasil dan harus tidak bisa dikirim langsung oleh client.

Java/JAX-RS risk

Jika aplikasi percaya X-User-ID dari request publik, attacker bisa melakukan:

curl -H 'X-User-ID: admin' https://api.example.com/...

Aplikasi tidak boleh mempercayai identity header kecuali ingress/proxy chain sudah dikunci dan terdokumentasi.


12. Real Client IP and Allow/Deny Rules

IP allowlist sering digunakan untuk:

partner integration
internal admin route
management endpoint
B2B API
migration tool
temporary operational access

Masalahnya, source IP di NGINX bisa berupa:

client IP asli
cloud load balancer IP
node IP
proxy IP sebelumnya
NAT gateway IP
corporate proxy IP

Jika salah membaca IP, allowlist bisa menjadi tidak berguna.

Contoh konfigurasi real IP:

set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Hati-hati:

set_real_ip_from harus hanya berisi trusted proxy/load balancer
jangan trust X-Forwarded-For dari internet langsung

Allowlist contoh:

location /partner/ {
    allow 203.0.113.10;
    allow 203.0.113.11;
    deny all;

    proxy_pass http://jaxrs_upstream;
}

Kubernetes/AWS/Azure nuance

Source IP preservation sangat bergantung pada:

LoadBalancer type
externalTrafficPolicy
proxy protocol
ALB/NLB behavior
Azure Load Balancer/Application Gateway behavior
Ingress controller config

Jangan mereview allow/deny tanpa memahami source IP chain.


13. Security Headers

Security headers membantu browser mengambil keputusan aman.

Header umum:

Strict-Transport-Security
Content-Security-Policy
X-Frame-Options
X-Content-Type-Options
Referrer-Policy
Permissions-Policy

Contoh:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "no-referrer" always;

CSP contoh minimal:

add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'none'" always;

Namun CSP tidak boleh asal ditambahkan untuk semua response.

Untuk API JSON murni, beberapa security header berguna tetapi CSP biasanya lebih relevan untuk browser-rendered content.

Untuk SPA/frontend static assets, CSP harus diuji terhadap:

script source
style source
font source
image source
API endpoint
analytics/telemetry endpoint
iframe policy

HSTS caution

HSTS berbahaya jika domain/subdomain belum siap HTTPS penuh.

Sebelum includeSubDomains atau preload:

pastikan semua subdomain valid HTTPS
pastikan certificate rotation matang
pastikan rollback strategy jelas
pastikan tidak ada legacy HTTP-only integration

14. Sensitive Header Removal

NGINX dapat menyembunyikan header upstream yang tidak boleh keluar.

Contoh:

proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_hide_header X-Internal-Trace;
proxy_hide_header X-Debug-Token;

Header internal yang harus hati-hati:

internal service name
pod/node identifier
stack/framework version
debug token
upstream address
internal correlation metadata
user/tenant raw identifiers

Namun jangan sembunyikan header observability yang memang dibutuhkan client/support tanpa pengganti.

Contoh aman:

Expose: X-Request-ID
Hide: X-Internal-Request-Route

15. Server Token and Version Disclosure

NGINX bisa mengurangi version disclosure:

server_tokens off;

Ini bukan security control utama, tetapi mengurangi informasi mudah untuk fingerprinting.

Jangan menganggap server_tokens off cukup untuk hardening. Ini hanya hygiene.


16. SSRF Mitigation Awareness

SSRF biasanya terjadi di aplikasi, bukan di NGINX.

Namun NGINX bisa memperburuk SSRF jika:

proxy_pass memakai variable dari request tanpa allowlist
resolver mengarah ke DNS yang bisa dimanipulasi
internal hostname bisa dicapai dari route publik
rewrite membangun upstream target dari user input

Contoh berbahaya:

location /proxy/ {
    proxy_pass http://$arg_target;
}

Ini membuka peluang request publik memaksa NGINX mengakses internal target.

Pola aman:

jangan membangun upstream dari user input
pakai allowlist upstream eksplisit
pisahkan public route dan internal route
batasi resolver dan network egress

Untuk Java/JAX-RS service, SSRF prevention utama tetap di aplikasi dan outbound network policy.


17. Request Smuggling Awareness

Request smuggling muncul saat proxy dan backend berbeda memahami boundary request, terutama terkait:

Content-Length
Transfer-Encoding
chunked encoding
connection reuse
HTTP/1.1 parsing differences

NGINX modern cukup ketat, tetapi risiko tetap muncul dalam chain kompleks:

cloud LB -> WAF -> NGINX -> API gateway -> Java app server

Checklist awareness:

hindari proxy chain yang tidak jelas
upgrade komponen proxy secara disiplin
jangan meneruskan hop-by-hop header sembarangan
uji behavior Content-Length vs Transfer-Encoding
pastikan backend app server di-patch

Di Java ecosystem, perhatikan app server/container:

Tomcat
Jetty
Undertow
Netty
Quarkus/Vert.x
Spring embedded server

Masing-masing punya parser HTTP dan patch lifecycle sendiri.


18. WAF and ModSecurity Integration

NGINX bisa diintegrasikan dengan WAF, tergantung distribusi/platform:

ModSecurity connector
NGINX App Protect WAF
cloud WAF di ALB/Application Gateway/Front Door
API gateway WAF
third-party security appliance

WAF berguna untuk:

known attack pattern
SQLi/XSS generic detection
bot/fuzzer noise
protocol anomaly
virtual patching sementara

Tetapi WAF bukan pengganti:

input validation
parameterized query
authorization
tenant isolation
secure domain workflow

Risiko WAF:

false positive memblokir legitimate request
false negative memberi rasa aman palsu
latency overhead
rule update menyebabkan incident
observability kurang jelas

Untuk enterprise system, WAF harus punya:

detection mode sebelum blocking
exception management
rule ownership
alert triage
business impact review
rollback mechanism

19. Bot Mitigation and Abuse Protection

NGINX bisa membantu melindungi backend dari traffic otomatis:

rate limiting
connection limiting
User-Agent filtering kasar
deny path scanner umum
basic geo/IP policy jika relevan
WAF integration

Tetapi bot mitigation serius biasanya membutuhkan layer tambahan:

cloud WAF
bot management product
API gateway policy
risk scoring
captcha untuk browser flow
behavioral detection

Jangan membuat rule User-Agent terlalu agresif untuk API enterprise, karena banyak partner/client memakai automation, SDK, atau integration runtime yang User-Agent-nya tidak standar.


20. Log Redaction and Privacy

Security hardening tidak hanya menolak request. Ia juga mencegah data sensitif bocor melalui log.

Risiko log:

token di query string
Authorization header tercatat
cookie tercatat
PII di URI path
PII di request body
client certificate subject terlalu detail
tenant/user ID tanpa masking

Access log default biasanya tidak mencatat body, tetapi bisa mencatat URI lengkap termasuk query string.

Contoh masalah:

GET /api/v1/reset-password?token=secret
GET /api/v1/customer/1234567890/quote

Prinsip:

Do not put secrets in URL.
Do not log sensitive headers.
Do not add body logging at NGINX unless explicitly approved.
Use request ID for correlation, not raw payload logging.

Jika perlu debugging payload, lakukan dengan controlled sampling dan approval yang jelas.


21. Error Response Hygiene

NGINX bisa menghasilkan error response sendiri:

400 bad request
403 forbidden
404 not found
413 payload too large
414 URI too long
429 too many requests
494 request header too large
502 bad gateway
503 service unavailable
504 gateway timeout

Pastikan error response tidak membocorkan:

NGINX version
internal upstream name
pod IP
internal hostname
stack trace
config path

Contoh custom error:

error_page 403 /errors/403.json;
error_page 413 /errors/413.json;
error_page 429 /errors/429.json;
error_page 502 503 504 /errors/5xx.json;

location /errors/ {
    internal;
    default_type application/json;
    return 503 '{"error":"service_unavailable","requestId":"$request_id"}';
}

Hati-hati: return di static location seperti ini butuh desain yang konsisten per status. Jangan sampai semua error menjadi 503.

Untuk API enterprise, error contract sebaiknya diselaraskan antara NGINX/API gateway dan Java/JAX-RS application.


22. Security Hardening in Kubernetes Ingress

Di Kubernetes, hardening sering tersebar di:

Ingress annotation
IngressClass
controller ConfigMap
controller command args
Helm values
admission policy
NetworkPolicy
PodSecurity
Secret management
cloud LB/WAF configuration

Contoh annotation yang mungkin relevan, tergantung controller:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/whitelist-source-range: "203.0.113.0/24"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"

Risiko besar:

annotation memberi tim aplikasi kemampuan override policy global
configuration-snippet/server-snippet membuka arbitrary NGINX config
per-Ingress exception tidak terlihat oleh platform governance

Security hardening di Kubernetes harus didukung policy:

allowed annotation list
blocked annotation list
admission control
Helm linting
GitOps review rule
central platform standard

23. AWS/Azure/On-Prem Considerations

AWS/EKS

Perlu cek:

WAF berada di CloudFront/ALB/API Gateway atau tidak
ALB/NLB meneruskan source IP bagaimana
security group membatasi ingress port apa
ACM certificate termination di ALB atau NGINX
proxy protocol aktif atau tidak

Jika TLS terminate di ALB, NGINX mungkin menerima HTTP internal. Maka X-Forwarded-Proto harus benar.

Azure/AKS

Perlu cek:

Azure Front Door / Application Gateway / Azure WAF
TLS termination location
NSG rule
Private Link/Private Endpoint
source IP preservation
AGIC vs NGINX Ingress boundary

On-prem/hybrid

Perlu cek:

corporate firewall
DMZ reverse proxy
internal L4/L7 load balancer
internal CA
proxy chaining
TLS inspection
split-horizon DNS

Dalam hybrid environment, jangan asumsikan NGINX adalah layer pertama. Kadang request sudah melewati beberapa proxy sebelum sampai ke NGINX.


24. Failure Modes

SymptomKemungkinan penyebab
400 dari NGINXHost/header invalid, malformed request, header terlalu besar
403 dari NGINXallow/deny, method restriction, WAF, auth_request
404 dari NGINXpath blocked, wrong location, default backend
413body melebihi client_max_body_size / ingress body size
414URI terlalu panjang
429rate limit/connection limit
502upstream error, TLS upstream issue, bad proxy config
legitimate client blockedWAF false positive, IP allowlist salah, header limit terlalu kecil
app tidak melihat requestrequest ditolak di NGINX sebelum upstream
app melihat wrong scheme/hostforwarded header salah
internal endpoint exposedrouting/default server/Ingress terlalu permisif

25. Detection and Debugging

Pertanyaan debugging pertama:

Apakah request sampai ke Java/JAX-RS app?

Jika tidak ada application log, cek NGINX:

kubectl logs deploy/ingress-nginx-controller -n ingress-nginx
kubectl describe ingress <name> -n <namespace>
kubectl get events -n <namespace>

Cek request dengan curl:

curl -v https://api.example.com/api/v1/quotes
curl -v -H 'Host: unexpected.example.com' https://api.example.com/
curl -v -X TRACE https://api.example.com/api/v1/quotes
curl -v --data-binary @large.json https://api.example.com/api/v1/quotes

Cek TLS/header/security response:

curl -I https://api.example.com/
openssl s_client -connect api.example.com:443 -servername api.example.com

Cek log fields penting:

request_id
remote_addr
realip_remote_addr
host
request_method
request_uri
status
body_bytes_sent
request_time
upstream_addr
upstream_status
upstream_response_time
http_user_agent

26. PR Review Checklist

Gunakan checklist ini saat mereview perubahan NGINX/Ingress/security config.

Boundary

Apakah route ini public, partner-only, internal, atau admin?
Apakah route ini seharusnya lewat NGINX yang sama?
Apakah ada API Gateway/WAF sebelum NGINX?

Host and path

Apakah host eksplisit?
Apakah default server aman?
Apakah path internal/admin tidak terekspos?
Apakah rewrite mengubah security assumption?

Headers

Apakah forwarded headers diset ulang oleh trusted proxy?
Apakah identity headers dari client dihapus?
Apakah Host header tervalidasi?
Apakah security headers sesuai jenis response?

Size and method

Apakah body size limit masuk akal?
Apakah header size limit masuk akal?
Apakah method policy sesuai API contract?
Apakah upload route punya exception eksplisit?

Auth and trust

Apakah auth dilakukan di layer yang tepat?
Apakah authorization tetap ada di aplikasi?
Apakah IP allowlist membaca real client IP yang benar?

Observability

Apakah 403/413/429/5xx bisa diamati?
Apakah request ID tersedia?
Apakah false positive bisa ditriage?
Apakah log tidak membocorkan PII/token?

Rollback

Apakah perubahan bisa dirollback cepat?
Apakah ada smoke test?
Apakah ada canary jika perubahan berisiko tinggi?

27. Internal Verification Checklist

Cek hal-hal berikut di internal CSG/team sebelum menyimpulkan arsitektur:

Jenis NGINX yang digunakan: OSS, Plus, ingress-nginx, NGINX Inc controller, atau managed gateway.
Lokasi TLS termination sebenarnya.
Apakah WAF berada sebelum atau di dalam NGINX.
Default backend/default server behavior.
Daftar annotation Ingress yang diizinkan.
Apakah snippets diaktifkan atau diblokir.
Policy body size/header size global.
Policy source IP preservation.
Trusted proxy/load balancer CIDR.
Auth boundary: NGINX, API gateway, app, atau kombinasi.
Daftar header internal/identity yang boleh diteruskan.
Security header standard.
Admin/internal endpoint exposure policy.
Log redaction policy.
Dashboard untuk 4xx/5xx/security events.
Runbook untuk blocked traffic dan WAF false positive.
Incident notes terkait 403/413/429/Host/TLS/security header issue.

28. Anti-Patterns

Menganggap NGINX hardening menggantikan application authorization.
Meneruskan X-User-ID dari client ke backend.
Default server meroute unknown host ke aplikasi.
Wildcard host rule tanpa boundary.
client_max_body_size dinaikkan global karena satu endpoint upload.
Allowlist IP tanpa memahami real client IP chain.
Mengaktifkan server-snippet/configuration-snippet tanpa governance.
Menambahkan HSTS includeSubDomains tanpa inventory subdomain.
Menulis token atau PII di access log.
Memakai proxy_pass dynamic dari user input.
Memblokir method di NGINX tanpa sinkron dengan API contract.
Mengaktifkan WAF blocking tanpa detection phase dan rollback.

29. Practical Senior Engineer Heuristics

Gunakan heuristik ini:

Reject early, validate deeply.
Trust only the previous known proxy, not arbitrary headers.
Default route should be safe, boring, and non-informative.
Global limits should be conservative; exceptions should be explicit.
Security headers are not a substitute for authZ.
IP allowlist without source IP proof is theater.
WAF without observability becomes random production failure.
Log enough to debug; never log enough to leak.
Every edge rejection must be observable.
Every security exception must have owner and expiry.

30. Ringkasan

NGINX security hardening adalah tentang membuat edge layer lebih defensif, predictable, dan observable.

Yang harus dipahami:

NGINX bisa menolak request buruk lebih awal.
NGINX bisa memperbaiki atau merusak trust boundary.
NGINX bisa menyembunyikan bug aplikasi atau justru membuka celah baru.
NGINX policy harus selaras dengan Java/JAX-RS application contract.
NGINX Ingress policy harus governed, bukan bebas via annotation.

Sebagai senior backend engineer, target Anda bukan menghafal semua directive security. Targetnya adalah mampu bertanya:

Apa yang dipercaya?
Siapa yang menyet header ini?
Route ini seharusnya public atau internal?
Limit ini global atau exception?
Apakah rejection ini terlihat di dashboard?
Apakah aplikasi tetap enforce authorization?

Kalau jawaban pertanyaan-pertanyaan itu jelas, hardening NGINX sudah bergerak dari checklist kosmetik menjadi production security control.

Lesson Recap

You just completed lesson 17 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.