Pembatasan IP

Pembatasan IP #

Kontrol akses berbasis IP adalah cara paling langsung untuk membatasi siapa yang bisa mengakses bagian tertentu dari server. Nginx menyediakan directive allow dan deny yang sederhana tapi fleksibel, serta modul geo untuk logika yang lebih kompleks.

allow dan deny: Dasar #

server {
    location /admin/ {
        # Izinkan IP spesifik
        allow 203.0.113.10;

        # Izinkan subnet
        allow 10.0.0.0/8;
        allow 192.168.1.0/24;

        # Izinkan IPv6
        allow 2001:db8::/32;

        # Tolak semua yang lain
        deny all;

        proxy_pass http://admin_backend;
    }
}

Nginx memproses aturan allow dan deny secara berurutan dan berhenti di aturan pertama yang cocok. Urutan penulisan penting.

# ANTI-PATTERN: deny all dulu, lalu allow
location /api/ {
    deny all;             # ← Semua ditolak di sini
    allow 10.0.0.0/8;    # ← Tidak pernah dieksekusi
}

# BENAR: allow dulu, deny all terakhir
location /api/ {
    allow 10.0.0.0/8;    # ← Cocok untuk 10.x.x.x → izinkan, stop
    deny all;             # ← Untuk semua yang lain → tolak
}

Blokir IP Tertentu, Izinkan Semua yang Lain #

Kebalikan dari pola di atas — berguna untuk memblokir IP yang diketahui berbahaya:

server {
    location / {
        # Blokir IP yang diketahui bermasalah
        deny 198.51.100.0/24;
        deny 203.0.113.5;

        # Izinkan semua yang lain
        allow all;

        proxy_pass http://backend;
    }
}

Modul geo: Logika IP yang Lebih Fleksibel #

geo memungkinkan kamu membuat variabel berdasarkan IP klien. Lebih fleksibel dari allow/deny untuk kasus yang kompleks:

http {
    # Buat variabel $is_internal_ip
    geo $is_internal_ip {
        default     0;      # Default: bukan IP internal
        10.0.0.0/8  1;      # Jaringan internal
        172.16.0.0/12 1;
        192.168.0.0/16 1;
        127.0.0.1   1;
    }

    # Buat variabel $country_allowed berdasarkan negara (jika punya GeoIP)
    # geo $country_allowed {
    #     default        0;
    #     id             1;   # Indonesia
    #     sg             1;   # Singapura
    # }

    server {
        location /internal-api/ {
            # Gunakan variabel dari geo untuk keputusan akses
            if ($is_internal_ip = 0) {
                return 403;
            }
            proxy_pass http://internal_backend;
        }
    }
}

Menangani IP di Balik Proxy: ngx_http_realip_module #

Jika Nginx berada di balik load balancer atau CDN (Cloudflare, AWS ALB, dll.), $remote_addr akan berisi IP proxy, bukan IP klien asli. Modul realip mengatasi ini:

http {
    # Daftar IP proxy yang dipercaya (yang bisa meng-override IP)
    # Nginx akan membaca IP klien asli dari header X-Forwarded-For
    # HANYA dari IP yang ada di daftar ini
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;

    # Untuk Cloudflare, tambahkan semua IP Cloudflare:
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    # (daftar lengkap di https://www.cloudflare.com/ips/)

    # Header yang berisi IP asli klien
    real_ip_header X-Forwarded-For;

    # Ambil IP paling kanan yang belum diverifikasi
    # (lebih aman dari default yang ambil paling kiri)
    real_ip_recursive on;
}

Setelah konfigurasi ini, $remote_addr akan berisi IP klien asli, bukan IP proxy. Semua fitur yang bergantung pada IP (rate limiting, geo, allow/deny) akan bekerja dengan benar.

Jangan menambahkan IP yang tidak kamu kendalikan ke set_real_ip_from. Siapapun bisa mengirim header X-Forwarded-For dengan nilai sembarang. Hanya IP proxy yang benar-benar kamu percaya (load balancer milikmu, Cloudflare) yang boleh di-trust untuk meng-override IP.

Proteksi Endpoint Sensitif #

Pola lengkap untuk mengamankan endpoint internal:

server {
    listen 443 ssl;
    server_name example.com;

    # Site utama — akses terbuka
    location / {
        proxy_pass http://app_backend;
    }

    # Admin panel — hanya IP internal
    location /admin/ {
        allow 10.0.0.0/8;
        allow 192.168.0.0/16;
        deny all;
        proxy_pass http://admin_backend;
    }

    # Nginx status — hanya localhost
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }

    # Metrics Prometheus — hanya monitoring server
    location /metrics {
        allow 10.0.1.50;   # IP monitoring server
        deny all;
        proxy_pass http://localhost:9090;
    }

    # Blokir akses ke file sensitif
    location ~* \.(env|git|sql|bak|log)$ {
        deny all;
        return 404;
    }
}

Ringkasan #

  • Urutan allow/deny penting — Nginx berhenti di aturan pertama yang cocok. allow spesifik selalu sebelum deny all.
  • geo lebih fleksibel dari allow/deny langsung — buat variabel berdasarkan IP untuk digunakan di berbagai kondisi.
  • Jika di balik proxy/CDN, gunakan set_real_ip_from + real_ip_header agar $remote_addr berisi IP klien asli, bukan IP proxy.
  • Hanya trust set_real_ip_from ke IP yang benar-benar kamu kendalikan — mempercayai IP sembarang membuka celah IP spoofing.
  • Selalu proteksi endpoint sensitif (/admin, /metrics, /nginx_status) dengan IP allowlist yang ketat.

← Sebelumnya: Rate Limiting   Berikutnya: Proteksi DoS →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact