DEV Community

Cover image for ตั้งค่า nginx ให้รับ IP จริง จาก client เมื่อเว็บเราอยู่หลัง Cloudflare
Pattanapong Cherthong
Pattanapong Cherthong

Posted on • Edited on

ตั้งค่า nginx ให้รับ IP จริง จาก client เมื่อเว็บเราอยู่หลัง Cloudflare

เมื่อเราผูกโดเมนกับ dns server ของ cloudflare ซึ่ง cloudflare จะทำหน้าที่เป็นด่านหน้าแทน web server ของเราอีกชั้นนึง ทำหน้าที่เป็น reverse proxy เป็น cdn ช่วยให้เว็บเข้าได้เร็วจากทั่วทุกมุมโลก ทำหน้าที่เป็น web application firewall ป้องกันการโจมตีให้เราได้เบื้องต้น ป้องกันการ ddos ให้เราได้ค่อนข้างดี cloudflare มีให้เรามากขนาดนี้ตั้งแต่แพคเกจฟรี แบบว่าให้ใช้ฟรีซะจนเกรงใจ

เมื่อมี cloudflare มาทำหน้าที่ reverse proxy เป็นด่านหน้าให้ web server ของเรา ข้อจำกัดอย่างหนึ่งก็คือ โดยปกติฝั่ง web server จะไม่ได้รับข้อมูล IP ของ client หรือของผู้เข้าชมเว็บไซต์ที่แท้จริงโดยตรง แต่กลายเป็นว่าได้รับ IP ของ cloudflare ซะเองที่กั้นหน้าอยู่ ทำให้การเก็บ access log หรือ audit log ในฝั่ง web server ได้รับข้อมูลไม่ตรงตามความจริง แต่ cloudflare ก็ยังใจดีแปะ Original IP ของ Client มากับ Header ให้เราด้วย

สรุปให้เข้าใจง่าย

  • คนเข้าเว็บ → วิ่งไปหา Cloudflare ก่อน → Cloudflare ส่งต่อมาที่เซิร์ฟเวอร์คุณ
  • ทำให้ IP ที่เซิร์ฟเวอร์คุณได้ จะเป็น IP ของ Cloudflare ไม่ใช่ IP คนเข้าเว็บจริงๆ
  • Cloudflare ก็เลยต้องแปะ IP จริงของคนเข้าเว็บผ่าน header ชื่อ CF-Connecting-IP และ X-Forwarded-For

หลายๆคนอาจจะมองข้ามเรื่องการเก็บ access logs แต่ถ้าหากเกิดอะไรขึ้นกับเว็บและข้อมูลสำคัญบน server ยังสามารถสืบหา hacker ได้จาก IP Address ซึ่งก็เคยมีประสบการณ์ในการติดตาม hacker จาก IP Address และส่งข้อมูลให้ตำรวจดำเนินคดีกับ hacker มาแล้ว

การตั้งค่าใน nginx

สำหรับ nginx จำเป็นจะต้องใช้โมดูลที่ชื่อว่า ngx_http_realip_module ซึ่งถ้าติดตั้ง nginx ปกติ หรือรัน docker nginx ก็จะมี built in มาให้พร้อมแล้วในตัว เว้นแต่ใครที่เอา source code ของ nginx มา compile เองก็อย่าลืม enable module นี้ด้วย

สิ่งที่เราจะต้องทำก็คือ ต้องเซ็ตค่า set_real_ip_from และ real_ip_header เพิ่ม

ทำไมต้องกำหนด set_real_ip_from

  • set_real_ip_from คือการบอกว่า ถ้า request มาจาก IP ของ Cloudflare เท่านั้น ถึงจะเชื่อถือ CF-Connecting-IP และ X-Forwarded-For
  • ถ้าไม่ตั้งไว้ Nginx จะมองว่า IP ของคนเข้าเว็บ = IP Cloudflare

1.เริ่มจากสร้างไฟล์ config ไว้ที่ /etc/nginx/cloudflare.conf เพิ่มข้อมูลไฟล์ตามด้านล่างนี้

#Cloudflare

# - IPv4
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;

# - IPv6
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;

real_ip_header CF-Connecting-IP;
Enter fullscreen mode Exit fullscreen mode

โดยที่เรากำหนด IP ของ Cloudflare นั้นเพื่อเป็นการ whitelist IP ป้องกันการ spoof หรือปลอมแปลง IP ที่ส่งมากับ header และ Nginx จะกำหนดตัวแปร remote_addr ให้เป็น IP จริงของผู้ใช้ เมื่อ request มาจาก Cloudflare เท่านั้น

อัพเดท list ips ของ cloudflare ได้จาก link นี้ https://www.cloudflare.com/ips/

2.แก้ไขไฟล์ /etc/nginx/nginx.conf และเพิ่ม include ให้อยู่ภายใน http{....} block ตามตัวอย่างด้านล่าง

http {

    include /etc/nginx/cloudflare.conf; 

}
Enter fullscreen mode Exit fullscreen mode

3.แก้ไขเสร็จแล้วก็ให้ restart nginx

sudo systemctl nginx restart
Enter fullscreen mode Exit fullscreen mode

การตั้งค่าสำหรับ Nginx Ingress Controller บน Kubernetes

# ConfigMap for Nginx Ingress Controller
data:
  use-forwarded-headers: "true"
  forwarded-for-header: "CF-Connecting-IP"
  proxy-real-ip-cidr: |
    <Pod CIDRs>,
    <Node CIDRs>,
    <Load Balancer CIDRs>,
    <Cloudflare CIDRs>
Enter fullscreen mode Exit fullscreen mode

example

data:
  use-forwarded-headers: "true"
  forwarded-for-header: "CF-Connecting-IP"
  proxy-real-ip-cidr: |
    <Pod CIDRs>,
    <Node CIDRs>,
    <Load Balancer CIDRs>,
    173.245.48.0/20,
    103.21.244.0/22,
    103.22.200.0/22,
    103.31.4.0/22,
    141.101.64.0/18,
    108.162.192.0/18,
    190.93.240.0/20,
    188.114.96.0/20,
    197.234.240.0/22,
    198.41.128.0/17,
    162.158.0.0/15,
    104.16.0.0/13,
    104.24.0.0/14,
    172.64.0.0/13,
    131.0.72.0/22,
    2400:cb00::/32,
    2606:4700::/32,
    2803:f800::/32,
    2405:b500::/32,
    2405:8100::/32,
    2a06:98c0::/29,
    2c0f:f248::/32
Enter fullscreen mode Exit fullscreen mode

สำหรับ Nginx Ingress Controller ให้กำหนดค่า IPs ใน proxy-real-ip-cidr ใน ConfigMap ซึ่งนอกจากจะใส่ IP ของ Cloudflare แล้ว จะต้องเพิ่ม IP ของ Load balancer, Node , และ Pod เข้าไปด้วย

reference https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/

Top comments (0)