Nginx

DDoS Protection ใน Nginx บน Cloud VPS

การโจมตี DDoS (Distributed Denial of Service) เป็นหนึ่งในภัยคุกคามที่ร้ายแรงที่สุดสำหรับเว็บแอปพลิเคชัน การโจมตีประเภทนี้มีวัตถุประสงค์เพื่อท้ำให้เซิร์ฟเวอร์ไม่สามารถให้บริการได้โดยการส่งจำนวนคำขอที่มหาศาล หรือการสร้างการเชื่อมต่อที่เยอะเกินไปจากหลายที่อยู่ (IP address) พร้อมกัน การป้องกัน DDoS อย่างมีประสิทธิภาพเป็นสิ่งสำคัญอย่างยิ่งในการรักษาความเสถียรและความพร้อมใช้งานของระบบ

Nginx เป็นเว็บเซิร์ฟเวอร์ที่มีประสิทธิภาพสูงและสามารถทำหน้าที่เป็นเส้นป้องกันแรกต่อต้านการโจมตี DDoS ได้อย่างมีประสิทธิภาพ ด้วยการกำหนดค่าที่เหมาะสม เราสามารถลดผลกระทบของการโจมตีและปกป้องเซิร์ฟเวอร์บนเว็บแอปพลิเคชันของเรา ในบทความนี้ เราจะสำรวจกลยุทธ์ต่างๆ ในการป้องกัน DDoS โดยใช้ Nginx บน Cloud VPS

ทำความเข้าใจเกี่ยวกับการโจมตี DDoS

การโจมตี DDoS เป็นการโจมตีที่มีความเสี่ยงต่อความพร้อมใช้งาน (Availability) ของระบบ ซึ่งแบ่งออกเป็นหลายประเภท:

  • Volume-based DDoS: การส่งจำนวนข้อมูลที่มหาศาล (Megabits per second) เพื่อท้ำให้แบนด์วิดท์เต็ม
  • Protocol-based DDoS: การส่งแพ็คเก็ต (packet) ที่ไม่ถูกต้องตามโปรโตคอลเพื่อให้เซิร์ฟเวอร์สิ้นเปลืองทรัพยากร
  • Application-layer DDoS: การส่งคำขอ HTTP ที่ดูเหมือนถูกต้องจริงแต่มีจำนวนมหาศาล

Nginx สามารถช่วยป้องกันได้โดยเฉพาะการโจมตี Protocol-based และ Application-layer DDoS ผ่านการกำหนดค่าต่างๆ ที่จะอธิบายในส่วนต่อไป

Nginx เป็นเส้นป้องกันแรกต่อต้าน DDoS

Nginx มีข้อดีหลายประการในการป้องกัน DDoS:

  • ประสิทธิภาพสูง: Nginx ใช้สถาปัตยกรรม event-driven ที่สามารถจัดการการเชื่อมต่อหลายพันรายพร้อมกันได้ด้วยการใช้ทรัพยากรน้อย
  • ความยืดหยุ่น: Nginx มีโมดูลมากมายที่สามารถใช้เพื่อปกป้องจากการโจมตี DDoS
  • ปรับแต่งได้: สามารถตั้งค่าการป้องกัน DDoS ตามความต้องการเฉพาะของแอปพลิเคชัน

เมื่อติดตั้ง Nginx บน Cloud VPS ของ DE คุณสามารถกำหนดค่าการป้องกัน DDoS ในตำแหน่งหนึ่งที่เข้าสถานีทั้งหมดของการเชื่อมต่อเข้า ทำให้ลดปริมาณการส่งจากการโจมตีที่ถึงเซิร์ฟเวอร์แอปพลิเคชันด้านหลัง

การจำกัดอัตราด้วย limit_req

โมดูล limit_req ของ Nginx ใช้สำหรับจำกัดอัตราการขอ (request rate) จากไคลเอนต์ เพื่อป้องกันการโจมตี Application-layer DDoS โดยการจำกัดจำนวนคำขอที่สามารถรับได้ในช่วงเวลาที่กำหนด:

http {
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=strict:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location / {
            limit_req zone=general burst=20 nodelay;
            proxy_pass http://backend;
        }

        location /api/ {
            limit_req zone=strict burst=5 nodelay;
            proxy_pass http://backend;
        }
    }
}

ในการตั้งค่าดังกล่าว ลูกค้ากระบวนการ IP จะอนุญาตให้ส่ง 10 คำขอต่อวินาที สำหรับ location ทั่วไป แต่เพียง 1 คำขอต่อวินาที สำหรับ API ช่วยลดความเสี่ยงจากการโจมตี DDoS ที่กำหุม

การจำกัดจำนวนการเชื่อมต่อด้วย limit_conn

โมดูล limit_conn ใช้สำหรับจำกัดจำนวนการเชื่อมต่อพร้อมกันจากไคลเอนต์เดียว:

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            limit_conn addr 10;
            proxy_pass http://backend;
        }
    }
}

การตั้งค่านี้จะอนุญาตให้ไคลเอนต์เดียวมีการเชื่อมต่อพร้อมกันได้ไม่เกิน 10 การเชื่อมต่อ การเชื่อมต่อพิเศษจะถูกปฏิเสธ ช่วยป้องกันการโจมตี Protocol-based DDoS ที่พยายามสร้างการเชื่อมต่อมากมายจากไคลเอนต์เดียว

การปรับแต่ง Timeout เพื่อป้องกัน DDoS

การตั้งค่า timeout ที่เหมาะสมสามารถช่วยป้องกันการโจมตี Slowloris ที่ปล่อยการเชื่อมต่อช้าๆ และรักษาการเชื่อมต่อไว้นาน:

http {
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 5s 5s;
    send_timeout 10s;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_connect_timeout 10s;
            proxy_send_timeout 10s;
            proxy_read_timeout 10s;
            proxy_pass http://backend;
        }
    }
}

การตั้งค่า timeout ที่สั้นจะลดความเสี่ยงในการเสียทรัพยากร (resource exhaustion) เนื่องจากการเชื่อมต่อที่นิ่งหรือปล่อยช้า

การบล็อก User-Agent ที่ไม่ดี

หลายการโจมตี DDoS ใช้ Bot หรือ Crawler ที่มี User-Agent ที่สม่ำเสมอ การบล็อก User-Agent ที่รู้จักว่าถูกใช้ในการโจมตีช่วยลดปริมาณการโจมตี:

http {
    map $http_user_agent $block_bad_bot {
        default 0;
        ~*(bot|crawler|spider|scraper) 1;
        ~*(nmap|nikto|masscan) 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_bad_bot) {
            return 403;
        }

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

การบล็อกนี้จะปฏิเสธคำขอจาก Bot และ Crawler ที่ไม่ต้องการ ช่วยลดปริมาณการโจมตีที่เข้ามา

การกรองคำขอ (Request Filtering)

การกรองคำขอที่ผิดปกติช่วยให้เราสามารถปฏิเสธคำขอที่เห็นได้ว่าเป็นส่วนของการโจมตี:

http {
    server {
        listen 80;
        server_name example.com;

        # บล็อกคำขอ POST ขนาดใหญ่
        client_max_body_size 1m;

        # บล็อกคำขอที่มี parameter มากเกินไป
        location / {
            if ($args ~* (.){100,}) {
                return 403;
            }
            proxy_pass http://backend;
        }

        # บล็อก SQL Injection patterns
        location / {
            if ($request_uri ~* "union.*select|select.*from|insert.*into") {
                return 403;
            }
            proxy_pass http://backend;
        }
    }
}

การกรองนี้ช่วยปฏิเสธคำขอที่ไม่ถูกต้องหรือคำขอที่เป็นอันตราย ทำให้เซิร์ฟเวอร์แอปพลิเคชันไม่ต้องประมวลผลคำขอเหล่านั้น

การใช้ Geo Module เพื่อบล็อกประเทศ

หากวิธีการโจมตี DDoS มาจากประเทศที่ไม่มีผู้ใช้ที่เหมาะสม การบล็อกการเชื่อมต่อจากประเทศเหล่านั้นเป็นวิธีการป้องกันที่มีประสิทธิภาพ:

http {
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_country_code country iso_code;
    }

    map $geoip2_country_code $block_country {
        default 0;
        "CN" 1;  # บล็อกจีน
        "RU" 1;  # บล็อกรัสเซีย
        "KP" 1;  # บล็อกเกาหลีเหนือ
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_country) {
            return 403;
        }

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

โปรดใช้เพียงตัวเลือกนี้หากคุณมั่นใจว่าผู้ใช้ที่ถูกต้องไม่มาจากประเทศที่บล็อก

การป้องกัน SYN Flood ด้วยการปรับแต่ง Kernel

SYN Flood เป็นการโจมตี Protocol-based ที่พยายามใช้ SYN queue ให้เต็ม การปรับแต่ง Kernel Linux สามารถช่วยลดผลกระทบได้:

# เพิ่มขนาด SYN backlog
sysctl -w net.ipv4.tcp_max_syn_backlog=4096

# เปิด SYN cookies
sysctl -w net.ipv4.tcp_syncookies=1

# ลดเวลา SYN timeout
sysctl -w net.ipv4.tcp_synack_retries=2

# เพิ่มการเชื่อมต่อที่อนุญาต
sysctl -w net.core.somaxconn=65535

# เพิ่ม TCP backlog
sysctl -w net.ipv4.tcp_max_tw_buckets=2000000

การตั้งค่า kernel นี้ช่วยให้ระบบสามารถทนต่อการโจมตี SYN Flood ได้ดีขึ้น

การรวมกับ Cloudflare สำหรับการป้องกัน DDoS ที่สูงขึ้น

Cloudflare เป็นบริการ CDN และ DDoS protection ที่ทรงพลัง การรวม Cloudflare กับ Nginx ช่วยให้การป้องกัน DDoS มีประสิทธิภาพสูงยิ่งขึ้น:

  • Cloudflare ตัวกลางแรก: Cloudflare จะกรองการโจมตี Volume-based DDoS ก่อนที่จะเข้า Nginx
  • Rate Limiting ที่ดีขึ้น: Cloudflare สามารถใช้ข้อมูลทั่วโลกเพื่อตรวจหาและบล็อกการโจมตี
  • Geographic Filtering: Cloudflare สามารถบล็อกการเชื่อมต่อจากภูมิภาคที่กำหนด
  • Bot Management: Cloudflare มีเครื่องมือจัดการ Bot ที่ขั้นสูง

เมื่อใช้ Cloudflare ร่วมกับ Nginx บน Cloud VPS ของ DE คุณได้รับการป้องกัน DDoS ที่มีประสิทธิภาพมากขึ้น

การตรวจสอบและตรวจจับการโจมตี

การตรวจสอบและตรวจจับการโจมตี DDoS เป็นสิ่งสำคัญในการตอบสนองต่อการโจมตี:

  • ตรวจสอบบันทึก Nginx: ตรวจสอบบันทึก access.log และ error.log เพื่อหา IP ที่ส่งคำขอจำนวนมหาศาล
  • ใช้เครื่องมือ Monitoring: ใช้เครื่องมือเช่น Prometheus และ Grafana เพื่อตรวจสอบการใช้ทรัพยากร
  • ตั้งค่า Alert: ตั้งค่า Alert เพื่อแจ้งเตือนเมื่อมีการโจมตี DDoS อาจเกิดขึ้น

ตัวอย่างการตรวจสอบบันทึก:

# นับคำขอจาก IP แต่ละตัว
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# ค้นหา IP ที่ส่งคำขอมากกว่า 100 ครั้ง
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | awk '$1 > 100 {print}'

ตัวอย่างการตั้งค่า DDoS Protection แบบสมบูรณ์

นี่คือตัวอย่างการตั้งค่า Nginx ที่สมบูรณ์เพื่อป้องกัน DDoS:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 4096;
    use epoll;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Limit request rate
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=strict:10m rate=1r/s;

    # Limit connections
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    # Block bad bots
    map $http_user_agent $block_bad_bot {
        default 0;
        ~*(bot|crawler|spider|scraper|nmap|nikto) 1;
    }

    # Timeouts
    client_body_timeout 10s;
    client_header_timeout 10s;
    send_timeout 10s;

    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        listen 80;
        server_name example.com;

        client_max_body_size 1m;

        # Block bad bots
        if ($block_bad_bot) {
            return 403;
        }

        # Block large query strings
        location / {
            if ($args ~* (.){100,}) {
                return 403;
            }

            limit_req zone=general burst=20 nodelay;
            limit_conn addr 10;

            proxy_pass http://backend;
            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;

            proxy_connect_timeout 10s;
            proxy_send_timeout 10s;
            proxy_read_timeout 10s;
        }

        # API location with stricter limits
        location /api/ {
            limit_req zone=strict burst=5 nodelay;
            limit_conn addr 5;

            proxy_pass http://backend;
            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_connect_timeout 10s;
            proxy_send_timeout 10s;
            proxy_read_timeout 10s;
        }
    }
}

สรุป

การป้องกัน DDoS ใน Nginx บน Cloud VPS เป็นกระบวนการที่หลายชั้น ซึ่งรวมถึงการจำกัดอัตรา การจำกัดการเชื่อมต่อ การปรับแต่ง timeout การบล็อก User-Agent ที่ไม่ดี การกรองคำขอ และการปรับแต่ง kernel ด้วยการรวมกลยุทธ์เหล่านี้ คุณสามารถลดความเสี่ยงจากการโจมตี DDoS อย่างมีนัยสำคัญ

การตรวจสอบและตรวจจับการโจมตีเป็นสิ่งสำคัญเช่นเดียวกัน เพื่อให้คุณสามารถตอบสนองต่อการโจมตีอย่างรวดเร็ว การรวม Cloudflare เข้ากับระบบของคุณจะให้ชั้นการป้องกัน DDoS เพิ่มเติม และการตั้งค่าให้ถูกต้องจะช่วยให้เว็บแอปพลิเคชันของคุณปลอดภัยจากการโจมตี DDoS

แนะนำบริการ DE

หากคุณกำลังมองหาโซลูชัน Cloud VPS ที่เชื่อถือได้และปลอดภัยเพื่อโฮสต์แอปพลิเคชันของคุณ Cloud VPS ของ DE เป็นทางเลือกที่ดี ด้วยเซิร์ฟเวอร์ที่มีประสิทธิภาพสูง และการจัดการด้วยบริหารที่ยืดหยุ่น คุณสามารถกำหนดค่า Nginx เพื่อป้องกัน DDoS ได้อย่างง่ายดาย

นอกจากนี้ หากคุณต้องการบริการโฮสติ้งที่มีการจัดการแบบเต็มรูปแบบ Cloud Hosting ของ DE อาจเป็นตัวเลือกที่เหมาะสมสำหรับคุณ ด้วยทีมผู้เชี่ยวชาญที่ช่วยดูแลเซิร์ฟเวอร์ของคุณ รวมถึงการป้องกัน DDoS และความปลอดภัยอื่นๆ