Nginx

Proxy Pass และ Proxy Headers ใน Nginx — ส่งต่อ Request อย่างถูกต้อง

Proxy Pass และ Proxy Headers เป็นฟีเจอร์ที่สำคัญในการกำหนดค่า Nginx reverse proxy สำหรับการจัดการและส่งต่อ HTTP requests จากเซิร์ฟเวอร์ Nginx ไปยังเซิร์ฟเวอร์แอปพลิเคชัน (backend servers) การตั้งค่าเหล่านี้ช่วยให้คุณสามารถควบคุมวิธีที่ Nginx จัดการข้อมูลการเชื่อมต่อ ที่อยู่ IP รีโมต และข้อมูลต่างๆ ที่ส่งถูกส่งต่อไปยัง backend ซึ่งมีความสำคัญต่อความปลอดภัย การเข้าถึง และประสิทธิภาพของแอปพลิเคชัน

บทความนี้จะอธิบายรายละเอียดเกี่ยวกับวิธีการใช้งาน proxy_pass, proxy_set_header และ directive ที่เกี่ยวข้องอื่นๆ เพื่อให้คุณสามารถตั้งค่า reverse proxy ของ Nginx ได้อย่างถูกต้องและปลอดภัย

Proxy Pass คืออะไร และการจัดการ URI

proxy_pass เป็น directive ในการกำหนดเซิร์ฟเวอร์ปลายทาง (upstream server) ที่จะรับข้อมูล HTTP requests จากคลายเอนต์ Directive นี้มีบทบาทสำคัญในการทำงาน reverse proxy โดยจะนำเอา requests มาจากเซิร์ฟเวอร์ Nginx ส่งต่อไปยัง backend server ทันที

วิธีการใช้งาน proxy_pass มีหลายรูปแบบ ขึ้นอยู่กับว่าต้องการบริหารจัดการ URI (Uniform Resource Identifier) อย่างไร:

Proxy Pass ที่มี Trailing Slash

เมื่อใช้ proxy_pass กับ trailing slash (/) Nginx จะแทนที่ location path ด้วย proxy URL

location /api/ {
    proxy_pass http://backend.example.com/;
}

# Request: /api/users → /users (on backend)
# Request: /api/posts/123 → /posts/123 (on backend)

Proxy Pass ที่ไม่มี Trailing Slash

ถ้าไม่มี trailing slash Nginx จะเก็บ location path ไว้และต่อท้ายกับ proxy URL:

location /api {
    proxy_pass http://backend.example.com;
}

# Request: /api/users → /api/users (on backend)
# Request: /api/posts/123 → /api/posts/123 (on backend)

Proxy Set Header — การส่งต่อข้อมูล Headers ที่สำคัญ

proxy_set_header ใช้สำหรับการกำหนดหรือแก้ไข HTTP headers ที่จะส่งต่อไปยัง backend server โดยจะต้องระบุชื่อ header และค่าที่ต้องการส่ง Headers เหล่านี้มีความสำคัญต่อการให้ backend server ทราบข้อมูลเกี่ยวกับคลายเอนต์เดิม

Host Header

Host header บอก backend server ว่าคลายเอนต์ขอการเชื่อมต่อ domain ใด ต้องระบุให้ถูกต้องเพื่อป้องกัน virtual host ของ backend ไม่ทำงาน:

location /app {
    proxy_pass http://backend.example.com;
    proxy_set_header Host $host;
}

# $host = Domain ที่คลายเอนต์ขอ (e.g., example.com)

X-Real-IP Header

X-Real-IP ช่วยให้ backend server ทราบที่อยู่ IP จริงของคลายเอนต์ (ไม่ใช่ IP ของ Nginx proxy) ซึ่งสำคัญต่อการ logging และการติดตามผู้ใช้:

location / {
    proxy_pass http://backend.example.com;
    proxy_set_header X-Real-IP $remote_addr;
}

# $remote_addr = IP address ของคลายเอนต์

X-Forwarded-For Header

X-Forwarded-For เป็น standard header ที่เก็บข้อมูล IP addresses ของคลายเอนต์ และทุก proxy ที่ request ผ่าน มีประโยชน์เมื่อมี multiple layer proxies:

location / {
    proxy_pass http://backend.example.com;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# ตัวอย่าง header value: 203.0.113.5, 198.51.100.178

X-Forwarded-Proto Header

X-Forwarded-Proto บอก backend server ว่าคลายเอนต์ใช้ protocol ใด (http หรือ https) ช่วยป้องกันไม่ให้ backend server สั่งการ redirect protocol ผิด:

location / {
    proxy_pass http://backend.example.com;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# $scheme = Protocol ที่ client ใช้ (http หรือ https)

Complete Header Configuration

ตัวอย่างการตั้งค่า headers อย่างสมบูรณ์สำหรับ reverse proxy:

location /api {
    proxy_pass http://backend.example.com;

    # Headers สำคัญ
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # Headers เพิ่มเติม
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header Connection "";
}

Proxy Redirect — การจัดการ Redirect Location

proxy_redirect ใช้สำหรับการแก้ไข Location header ที่ backend server ส่งกลับมา เช่น เมื่อ backend ส่ง redirect ไปยัง URL ใน domain backend แต่ proxy server ต้องแก้ไขให้กลับไปยัง domain ของ proxy แทน:

location /app {
    proxy_pass http://192.168.1.100:8080;
    proxy_redirect http://192.168.1.100:8080/ http://example.com/app/;
}

# Redirect: http://192.168.1.100:8080/login
# → http://example.com/app/login

Proxy Buffering และ Buffer Size

proxy_buffering ควบคุมว่า Nginx จะบัฟเฟอร์ response จาก backend server หรือไม่ การใช้ buffering ช่วยให้ Nginx ได้รับข้อมูลจาก backend อย่างรวดเร็ว จากนั้นจึงส่งต่อไปยังคลายเอนต์ในอัตราของคลายเอนต์

location / {
    proxy_pass http://backend.example.com;

    # เปิด buffering (ค่าเริ่มต้น)
    proxy_buffering on;

    # กำหนดจำนวน buffers
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;

    # ขนาด buffer ที่ใช้สำหรับเขียนไปยังคลายเอนต์
    proxy_busy_buffers_size 8k;
}

Proxy Timeouts — จัดการหมดเวลาการเชื่อมต่อ

การตั้งค่า timeout มีความสำคัญต่อการจัดการการเชื่อมต่อที่ผิดพลาดหรือการตอบสนองที่ช้า:

location / {
    proxy_pass http://backend.example.com;

    # เวลาที่รออยากเชื่อมต่อกับ backend (ค่าเริ่มต้น 60s)
    proxy_connect_timeout 30s;

    # เวลาที่รออยากรับข้อมูลจาก backend (ค่าเริ่มต้น 60s)
    proxy_read_timeout 60s;

    # เวลาที่รออยากส่งข้อมูลไปยัง backend (ค่าเริ่มต้น 60s)
    proxy_send_timeout 60s;
}

Upstream Groups — ส่งต่อไปยังกลุ่มของ Servers

เมื่อมี backend servers หลายตัว สามารถใช้ upstream block เพื่อกำหนดกลุ่มของ servers และ Nginx จะทำการ load balancing

upstream backend_pool {
    server 192.168.1.100:8080;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

location /app {
    proxy_pass http://backend_pool;
    proxy_set_header Host $host;
}

Load Balancing Methods

# Round Robin (ค่าเริ่มต้น)
upstream backend {
    server server1.example.com;
    server server2.example.com;
}

# Least Connections
upstream backend {
    least_conn;
    server server1.example.com;
    server server2.example.com;
}

# IP Hash (เซッชัน sticky)
upstream backend {
    ip_hash;
    server server1.example.com;
    server server2.example.com;
}

HTTPS Backends และ SSL Verification

เมื่อ backend server ใช้ HTTPS ต้องตั้งค่า SSL verification:

location / {
    proxy_pass https://backend.example.com;

    # ตรวจสอบ SSL certificate (ค่าเริ่มต้น on)
    proxy_ssl_verify on;

    # ตั้งไป off หากใช้ self-signed certificate
    proxy_ssl_verify on;
    proxy_ssl_verify_depth 2;
    proxy_ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt;
}

Proxy Cache Integration

การรวม proxy cache ช่วยลดภาระงานของ backend servers โดยเก็บ response ไว้ใน Nginx:

# กำหนด cache zone
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=backend_cache:10m
                 max_size=100m inactive=60m use_temp_path=off;

server {
    location /api {
        proxy_pass http://backend.example.com;

        # ใช้ cache zone
        proxy_cache backend_cache;

        # ระยะเวลา cache ในหน่วยวินาที
        proxy_cache_valid 200 10m;
        proxy_cache_valid 404 1m;

        # ไม่ cache หาก backend ส่ง Set-Cookie header
        proxy_cache_bypass $http_cookie;
    }
}

Proxy Next Upstream — Failover Configuration

proxy_next_upstream ใช้สำหรับการสำรอง (failover) ไปยัง upstream server ถัดไป เมื่อ server ปัจจุบันล้มเหลว:

upstream backend_pool {
    server 192.168.1.100:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
}

location /app {
    proxy_pass http://backend_pool;

    # ลองตัว server ถัดไปหากเกิด error
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

    # จำนวนครั้งสูงสุดที่พยายามลองตัว server ต่างๆ
    proxy_next_upstream_tries 3;

    # ระยะเวลาสูงสุดในการลองหรือ failover
    proxy_next_upstream_timeout 10s;
}

Proxy HTTP Version

proxy_http_version กำหนดเวอร์ชัน HTTP ที่ Nginx ใช้สำหรับการสื่อสารกับ backend server ค่าเริ่มต้นคือ 1.0 แต่มักแนะนำให้ใช้ 1.1 สำหรับการรองรับ Keep-Alive:

location / {
    proxy_pass http://backend.example.com;

    # ใช้ HTTP/1.1 สำหรับ Keep-Alive
    proxy_http_version 1.1;

    # ปิด Connection header เพื่อให้ Keep-Alive ทำงาน
    proxy_set_header Connection "";
}

ตัวอย่าง Real-World Configurations

Node.js Application

upstream nodejs_app {
    least_conn;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://nodejs_app;
        proxy_http_version 1.1;

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

        # สำหรับ WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Django/Python Application

upstream django_app {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://django_app;

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

        # จำกัด method สำหรับ OPTIONS
        proxy_set_header X-Forwarded-Host $server_name;

        # Buffering settings
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
}

Java Application with Load Balancing

upstream java_app {
    ip_hash;
    server 192.168.1.10:8080 weight=5;
    server 192.168.1.11:8080 weight=3;
    server 192.168.1.12:8080 backup;
}

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

    location /app {
        proxy_pass http://java_app;
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
        proxy_next_upstream_timeout 10s;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        # อื่นๆ settings
        proxy_connect_timeout 30s;
        proxy_read_timeout 120s;
    }
}

Troubleshooting Common Proxy Issues

502 Bad Gateway Error

ปัญหานี้เกิดเมื่อ Nginx ไม่สามารถเชื่อมต่อกับ backend server วิธีแก้:

  • ตรวจสอบว่า backend server กำลังทำงาน
  • ตรวจสอบการเชื่อมต่อเครือข่าย (firewall, network rules)
  • ตรวจสอบ proxy_connect_timeout ไม่สั้นเกินไป
  • ตรวจสอบ Nginx error log: /var/log/nginx/error.log

Redirect Loop Problems

เมื่อ client ได้รับ redirect ที่ชี้ไปยัง backend URL แทน proxy URL ให้ตั้งค่า proxy_redirect อย่างถูกต้อง

Missing Headers Issues

หาก backend ไม่ได้รับข้อมูล IP ของ client ให้ตรวจสอบว่าได้ตั้งค่า X-Real-IP และ X-Forwarded-For อย่างถูกต้อง

SSL Certificate Verification Errors

หากเกิดข้อผิดพลาด SSL ให้ตรวจสอบ proxy_ssl_verify และ proxy_ssl_trusted_certificate settings

สรุป

การตั้งค่า proxy_pass และ proxy_set_header ในการใช้งาน Nginx reverse proxy เป็นพื้นฐานที่สำคัญสำหรับการจัดการการขนส่งข้อมูล HTTP requests ไปยัง backend servers ด้วยการทำความเข้าใจเกี่ยวกับ URI handling, headers management, timeouts, buffering, caching, และ failover configurations คุณสามารถสร้าง reverse proxy ที่มีเสถียรภาพ ปลอดภัย และมีประสิทธิภาพ

ประเด็นหลักที่ต้องจำ:

  • proxy_pass ควบคุมวิธีการจัดการ URI
  • proxy_set_header ส่งข้อมูลสำคัญเกี่ยวกับ client ไปยัง backend
  • proxy_redirect แก้ไข Location header จาก backend
  • proxy_buffering เพิ่มประสิทธิภาพของการส่งต่อข้อมูล
  • proxy_next_upstream ช่วยในการจัดการ failover
  • upstream groups ทำให้ load balancing กลายเป็นเรื่องง่าย

แนะนำบริการของ DE

การตั้งค่า Nginx reverse proxy อย่างถูกต้องต้องใช้เซิร์ฟเวอร์ที่มีประสิทธิภาพและเสถียรภาพสูง Dot Enterprise (DE) มีบริการ Cloud VPS และ Cloud Hosting ที่เหมาะสมสำหรับการใช้งาน reverse proxy:

DE Cloud VPS ให้คุณควบคุม Nginx configuration อย่างสมบูรณ์ โดยมี root access และสามารถตั้งค่า proxy_pass, proxy headers, load balancing ได้อย่างอิสระ เหมาะสำหรับแอปพลิเคชันที่ต้องการ custom configuration และประสิทธิภาพสูง

สำหรับผู้ที่ต้องการความสะดวกและการสนับสนุน DE Cloud Hosting นำเสนอโซลูชัน managed hosting ที่มาพร้อมกับการตั้งค่า Nginx proxy ที่เหมาะสมอยู่แล้ว พร้อมทีม support ที่พร้อมช่วยเหลือเรื่องการตั้งค่าและการ optimize performance

ลองทดลองบริการของ DE วันนี้และสัมผัสความแตกต่างของเซิร์ฟเวอร์คลาวด์ที่มีคุณภาพและประสิทธิภาพสูง!