Logo

Personal Ops Runbook

Personal runbook covering infrastructure operations for Cloud, Kubernetes, OpenStack, and Ceph environments. Includes deployment and teardown procedures, node management, cluster monitoring setup, and incident response workflows compiled from day-to-day operational work. Intended strictly for personal reference — configurations and scripts are environment-specific and not guaranteed to work as-is elsewhere.

Làm thế nào để Backend thấy được IP thật của Client khi dùng Firewall, Router + Nginx Proxy?


🧭 Tổng quan

Trong các hệ thống hạ tầng web có sử dụng firewall Fortigate kết hợp với proxy Nginx, một vấn đề rất phổ biến là:

Backend không nhìn thấy IP thật của client ngoài Internet, mà chỉ thấy IP nội bộ (ví dụ như IP LAN của firewall hoặc IP proxy).

image

Đây không chỉ là vấn đề nhỏ – nó ảnh hưởng đến:

  • Việc ghi log chính xác
  • Giới hạn truy cập theo IP
  • Bảo mật (chặn IP, phát hiện tấn công,…)
  • Phân tích hành vi người dùng

Trong bài viết này, mình sẽ phân tích:

  • Nguyên nhân vì sao mất IP thật
  • Cách khắc phục để backend có thể thấy IP 1.2.3.4 của client
  • Ưu và nhược điểm từng cách
  • Ví dụ cụ thể
  • Sơ đồ hoạt động
  • Và lời khuyên cho các hệ thống thực tế

🧱 Mô hình hệ thống ví dụ

Client (1.2.3.4)
     |
     v
Internet
     |
     v
WAN IP: 113.161.201.128
Fortigate Firewall (DNAT + SNAT)
LAN IP: 192.168.123.1
     |
     v
Nginx Proxy: 192.168.100.101
     |
     v
Backend App: 192.168.100.111

🎯 Mục tiêu:

Làm sao để backend thấy được IP 1.2.3.4, chứ không phải IP LAN như 192.168.123.1 hay 192.168.100.101.

🧨 Nguyên nhân backend không thấy IP thật

❗ Khi Fortigate bật Enable NAT (SNAT):

Fortigate sẽ thay đổi Source IP của gói tin để đảm bảo có thể trả về đúng. Tuy nhiên điều này khiến IP thật bị mất hoàn toàn.

Trạng thái Source IP Destination IP
Trước Fortigate 1.2.3.4 113.161.201.128:80
Sau Fortigate (NAT) 192.168.123.1 192.168.100.101:80

Nginx proxy sẽ thấy IP là 192.168.123.1. Backend khi đọc X-Forwarded-For hoặc REMOTE_ADDR cũng sẽ thấy IP này – không đúng IP thật.

✅ Giải pháp: Tắt NAT (Disable SNAT) và đảm bảo định tuyến đúng

Khi Fortigate chỉ thực hiện DNAT mà không SNAT:

IP thật 1.2.3.4 được giữ nguyên và truyền thẳng đến Nginx.

Trạng thái Source IP Destination IP
Trước Fortigate 1.2.3.4 113.161.201.128
Sau DNAT 1.2.3.4 192.168.100.101

Nginx sẽ thấy IP là 1.2.3.4 và backend khi đọc X-Forwarded-For sẽ thấy chính xác IP client thật.

🖼️ Sơ đồ hoạt động khi tắt NAT

Client (1.2.3.4)
     |
     v
Internet
     |
     v
Fortigate (DNAT)
 - WAN: 113.161.201.128
 - LAN: 192.168.123.1
     |
     v
Nginx Proxy (192.168.100.101)
     |
     v
Backend (192.168.100.111)

Nginx -> thêm header: X-Forwarded-For: 1.2.3.4
Backend -> đọc IP thật từ header

🛠️ Cấu hình chi tiết

Trên Fortigate:

  • Tạo Virtual IP (VIP) DNAT:
    • External IP: 113.161.201.128
    • Mapped IP: 192.168.100.101
    • Port: 80
  • Tạo Policy WAN → LAN:
    • Source: all
    • Destination: VIP
    • Action: Accept
    • Tắt NAT (Disable Enable NAT)
  • Tạo Policy LAN → WAN (để trả phản hồi):
    • Source: 192.168.100.0/24
    • Destination: all
    • Action: Accept
    • NAT: tuỳ chọn

Trên Proxy Nginx (192.168.100.101):

location / {
    proxy_pass http://192.168.100.111;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Trên Backend (PHP):

function getClientIP() {
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        return trim($ipList[0]);
    }
    return $_SERVER['REMOTE_ADDR'];
}

⚠️ Điều kiện bắt buộc để hệ thống hoạt động đúng khi tắt NAT

Yêu cầu Giải thích
Default gateway của Nginx proxy phải là Fortigate Để gói phản hồi đi ngược qua firewall
Fortigate có route quay về mạng 192.168.100.0/24 Đảm bảo đường trả phản hồi đúng
Không có thiết bị nào khác làm NAT giữa proxy và backend Tránh mất IP gốc giữa đường

🔍 So sánh các cách

Phương pháp Có thấy IP thật? Dễ triển khai Ưu điểm Nhược điểm
Giữ NAT (Enable NAT) ❌ Không ✅ Dễ cấu hình Đơn giản, ít lỗi định tuyến Mất IP thật
Tắt NAT + định tuyến đúng ✅ Có ⚠️ Phức tạp hơn Thấy IP thật, chuẩn Cần hiểu rõ routing
Dùng Proxy Protocol ✅ Có ❌ Phức tạp Chuẩn kỹ thuật, chính xác Yêu cầu phần mềm backend hỗ trợ
FortiWeb / WAF thêm IP header ✅ Có ⚠️ Tuỳ thiết bị Thấy IP thật Phụ thuộc thiết bị, bản quyền

💡 Lời khuyên

  • Nếu bạn kiểm soát được hệ thống mạng (default gateway, routing), hãy tắt NAT và cấu hình đúng tuyến.
  • Nếu không thể tắt NAT, hãy dùng X-Forwarded-For, nhưng chấp nhận IP sẽ là IP của firewall, không phải IP client thật.
  • Đừng quên kiểm tra định tuyếngateway ở proxy/nginx để đảm bảo gói tin đi và về đều qua Fortigate.
  • Trong môi trường lớn, nên cân nhắc sử dụng Proxy Protocol hoặc các WAF chuyên dụng (như FortiWeb, Cloudflare…).

📌 Kết luận

Việc giữ lại IP thật của client là rất quan trọng cho hệ thống backend. Nếu bạn đang dùng Fortigate và Nginx, cách hiệu quả và đơn giản nhất là:

  • Tắt NAT (Enable NAT) trên Fortigate
  • Đảm bảo định tuyến đúng
  • Đọc IP từ header X-Forwarded-For

Đây là cách phổ biến và an toàn được nhiều hệ thống sử dụng.

Hy vọng bài viết này giúp bạn hiểu rõ cách hoạt động của NAT, proxy và cách giữ lại IP thật của người dùng. Nếu có câu hỏi, đừng ngại để lại bình luận!