Nginx

User-Agent Blocking ใน Nginx บน Cloud VPS — วิธีป้องกันบอทไม่พึงประสงค์

ในยุคดิจิทัลปัจจุบัน เซิร์ฟเวอร์เว็บไซต์ของเรามักถูกรบกวนจากบอทที่ไม่พึงประสงค์ เช่น บอทที่ใช้สำหรับการจำหน่ายข้อมูล (scraping) หรือบอทที่มีจุดประสงค์เพื่อค้นหาช่องโหว่ด้านความปลอดภัย (security scanning) User-Agent Blocking เป็นเทคนิคที่สำคัญในการป้องกันการเข้าถึงที่ไม่ต้องการและลดความเสี่ยงด้านความปลอดภัยของเว็บไซต์ได้อย่างมีประสิทธิภาพ

Nginx เป็นเว็บเซิร์ฟเวอร์ที่มีความสามารถในการจัดการและกรองข้อมูลจากลูกค้า (client) ได้อย่างดีเยี่ยม ด้วยความสามารถในการระบุและปิดกั้น User-Agent ที่ไม่ต้องการ เราสามารถปกป้องเว็บไซต์และลดความเสี่ยงจากการโจมตี (attack) ได้อย่างมีประสิทธิภาพ บทความนี้จะอธิบายวิธีการป้องกันและตั้งค่า User-Agent Blocking ใน Nginx แบบครบถ้วน

User-Agent คืออะไร และเหตุใดจึงต้องปิดกั้น

User-Agent เป็นข้อมูลส่วนหัว (HTTP header) ที่บ่งบอกข้อมูลเกี่ยวกับเบราว์เซอร์หรือแอปพลิเคชันที่กำลังส่งคำขอ (request) ไปยังเซิร์ฟเวอร์ User-Agent จะประกอบไปด้วยข้อมูล เช่น ชื่อเบราว์เซอร์ เวอร์ชัน ระบบปฏิบัติการ และอื่น ๆ ตัวอย่างเช่น:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36

เหตุผลสำคัญในการปิดกั้น User-Agent ที่ไม่พึงประสงค์มีดังนี้:

  • ป้องกันการ Scraping: บอทที่ใช้เพื่อดึงข้อมูลจากเว็บไซต์ของเรามักจะเปิดเผย User-Agent เฉพาะตัว
  • ลดภาระงาน (Load): บอทที่ไม่พึงประสงค์อาจสร้างความเสี่ยงต่อประสิทธิภาพของเซิร์ฟเวอร์
  • เพิ่มความปลอดภัย: บอทที่สแกนช่องโหว่ (vulnerability scanning) มักใช้ User-Agent เฉพาะตัว
  • ป้องกันการโจมตี DDoS: บางการโจมตี DDoS อาจใช้ User-Agent เพื่อซ่อนตัวตัวเอง

การระบุบอทที่ไม่พึงประสงค์ผ่าน User-Agent

วิธีการระบุบอทที่ไม่พึงประสงค์นั้นสามารถทำได้โดยการบันทึกข้อมูล User-Agent และวิเคราะห์ลวดลายของมัน บอทส่วนใหญ่มักเปิดเผย User-Agent ของพวกเขาอย่างชัดเจน ดังเช่น:

  • curl/7.x.x — เครื่องมือ curl ที่ใช้เพื่อส่งคำขอ HTTP
  • wget/1.x — เครื่องมือ wget สำหรับดาวน์โหลดไฟล์
  • python-requests — ไลบรารี Python ที่ใช้ทำบอท
  • MJ12bot, AhrefsBot — บอทที่ใช้เพื่อ SEO scanning
  • SqlMap, Nikto — เครื่องมือที่ใช้ในการทดสอบช่องโหว่
  • Empty User-Agent — การร้องขอที่ไม่มี User-Agent มักเป็นสัญญาณที่น่าสงสัย

สามารถดูบันทึก (log) เซิร์ฟเวอร์ Nginx และตรวจสอบ User-Agent ที่ส่งคำขอมาหา:

tail -f /var/log/nginx/access.log | grep -oP '(?<="[^"]*" )[^"]*'

ปิดกั้น User-Agent เฉพาะตัวด้วย if Directive

วิธีพื้นฐานในการปิดกั้น User-Agent คือการใช้ if directive ใน Nginx configuration ตัวอย่างด้านล่างจะแสดงวิธีปิดกั้น User-Agent บางตัว:

server {
    listen 80;
    server_name example.com;

    # ปิดกั้น curl
    if ($http_user_agent ~* curl) {
        return 403;
    }

    # ปิดกั้น wget
    if ($http_user_agent ~* wget) {
        return 403;
    }

    # ปิดกั้น python-requests
    if ($http_user_agent ~* python-requests) {
        return 403;
    }

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

ในตัวอย่างข้างต้น:

  • $http_user_agent — ตัวแปร Nginx ที่เก็บค่า User-Agent จากการร้องขอ
  • ~* — ตัวดำเนินการเปรียบเทียบที่ไม่คำนึงถึงขนาดตัวอักษร (case-insensitive)
  • return 403 — ส่งการตอบสนอง HTTP 403 (Forbidden)

การใช้ map เพื่อปิดกั้น User-Agent ที่มีประสิทธิภาพ

การใช้ if directive หลายครั้งนั้นอาจทำให้ประสิทธิภาพลดลง วิธีที่ดีกว่าคือการใช้ map block เพื่อจัดการ User-Agent หลายตัวพร้อมกัน:

http {
    map $http_user_agent $block_user_agent {
        default 0;
        ~*curl 1;
        ~*wget 1;
        ~*python-requests 1;
        ~*MJ12bot 1;
        ~*AhrefsBot 1;
        ~*SqlMap 1;
        ~*Nikto 1;
        ~*nmap 1;
        ~*masscan 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_user_agent) {
            return 403;
        }

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

วิธีนี้มีข้อดี:

  • ประสิทธิภาพดีกว่า: ใช้การเปรียบเทียบแบบเดียวแทนที่จะใช้หลาย if statement
  • ง่ายต่อการจัดการ: สามารถเพิ่มหรือลบ User-Agent ได้อย่างง่ายดาย
  • อ่านรหัสได้ชัดเจน: ทำให้ configuration ดูเป็นระเบียบเรียบร้อย

ปิดกั้น User-Agent ที่ว่างเปล่า

User-Agent ที่ว่างเปล่า (empty User-Agent) มักเป็นสัญญาณที่น่าสงสัย และอาจบ่งชี้ถึงการโจมตี เราสามารถปิดกั้นได้ดังนี้:

http {
    map $http_user_agent $block_empty_ua {
        default 0;
        "" 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_empty_ua) {
            return 403;
        }

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

อีกวิธีหนึ่งคือการตรวจจับ User-Agent ว่างเปล่าอย่างชัดเจน:

server {
    listen 80;
    server_name example.com;

    if ($http_user_agent = "") {
        return 403;
    }

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

อนุญาตเฉพาะบอทที่เชื่อถือได้ เช่น Googlebot และ Bingbot

บางครั้งเราต้องการอนุญาตเฉพาะบอทที่เชื่อถือได้เท่านั้น เช่น Googlebot และ Bingbot ซึ่งมีประโยชน์สำหรับการทำให้เว็บไซต์ปรากฏในผลลัพธ์การค้นหา (SEO):

http {
    map $http_user_agent $allow_user_agent {
        default 0;
        ~*Googlebot 1;
        ~*Bingbot 1;
        ~*Slurp 1;
        ~*DuckDuckBot 1;
        ~*Baidu 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($allow_user_agent = 0) {
            return 403;
        }

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

วิธีการข้างต้นนั้นเข้มงวดมาก และอาจปิดกั้นบอทที่ดีบางตัว วิธีที่สมดุลกว่าคือการปิดกั้นเฉพาะบอทที่ไม่พึงประสงค์แทน:

http {
    map $http_user_agent $block_bad_bot {
        default 0;
        ~*curl 1;
        ~*wget 1;
        ~*python 1;
        ~*SqlMap 1;
        ~*Nikto 1;
        "" 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_bad_bot) {
            return 403;
        }

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

บันทึก (Log) การร้องขอที่ถูกปิดกั้น

เพื่อตรวจสอบ User-Agent ที่ถูกปิดกั้นและวิเคราะห์รูปแบบการโจมตี สำคัญที่เราต้องบันทึกข้อมูลของ User-Agent:

http {
    log_format blocked_bots '$remote_addr - $remote_user [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           '"$http_referer" "$http_user_agent"';

    server {
        listen 80;
        server_name example.com;

        access_log /var/log/nginx/blocked_bots.log blocked_bots if=$block_bad_bot;

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

หรือสามารถบันทึกทุกการร้องขอไปที่ access.log เดียวกันและวิเคราะห์ในภายหลัง:

grep ' 403 ' /var/log/nginx/access.log | tail -20
grep ' 403 ' /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn

การรวม User-Agent Blocking กับ Rate Limiting

นอกเหนือจากการปิดกั้น User-Agent แล้ว เราสามารถรวม Rate Limiting เพื่อป้องกันการทำให้เซิร์ฟเวอร์โอเวอร์โหลด (overload):

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;

    map $http_user_agent $block_bad_bot {
        default 0;
        ~*curl 1;
        ~*wget 1;
        ~*python 1;
        ~*SqlMap 1;
        ~*Nikto 1;
        "" 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_bad_bot) {
            return 403;
        }

        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;
        }
    }
}

Regular Expression สำหรับการจับคู่ User-Agent

Nginx ใช้ Regular Expression (regex) เพื่อจับคู่ User-Agent ได้อย่างยืดหยุ่น มีตัวดำเนินการสำคัญดังนี้:

  • ~ — Regex matching (case-sensitive)
  • ~* — Regex matching (case-insensitive)
  • !~ — Regex NOT matching (case-sensitive)
  • !~* — Regex NOT matching (case-insensitive)

ตัวอย่างการใช้ regex สำหรับ User-Agent:

http {
    map $http_user_agent $block_bad_bot {
        default 0;
        ~*^curl 1;
        ~*^wget 1;
        ~*python|requests|urllib 1;
        ~*bot(?!s) 1;
        ~*nmap|masscan|sqlmap|nikto 1;
        ^$ 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_bad_bot) {
            return 403;
        }

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

ทดสอบ User-Agent Blocking ด้วย curl

เราสามารถทดสอบการตั้งค่า User-Agent Blocking ด้วยเครื่องมือ curl ได้อย่างง่ายดาย:

curl -A "curl/7.68.0" http://example.com
curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" http://example.com
curl -H "User-Agent:" http://example.com
curl -I -A "curl/7.68.0" http://example.com
curl -v -A "curl/7.68.0" http://example.com

ผลลัพธ์ที่คาดหวัง:

  • ถ้าปิดกั้นได้สำเร็จ จะได้รับการตอบสนอง HTTP 403 Forbidden
  • ถ้าอนุญาต จะได้รับการตอบสนอง HTTP 200 OK

การบำรุงรักษาและอัพเดต Blocklist

ในการจัดการ User-Agent Blocking ให้มีประสิทธิภาพ จำเป็นต้องทำการบำรุงรักษาและอัพเดต blocklist เป็นระยะ ๆ:

1. บันทึกและวิเคราะห์บอทใหม่

grep ' 403 ' /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn | head -20

2. สร้าง Blocklist แยกต่างหาก

แนะนำให้สร้างไฟล์แยกต่างหากสำหรับ Blocklist เพื่อให้ง่ายต่อการจัดการ:

map $http_user_agent $block_bad_bot {
    default 0;
    ~*curl 1;
    ~*wget 1;
    ~*python 1;
    ~*MJ12bot 1;
    ~*AhrefsBot 1;
    ~*SqlMap 1;
    ~*Nikto 1;
    ~*nmap 1;
    ~*masscan 1;
    "" 1;
}

3. ทดสอบก่อนทำการ Reload

sudo nginx -t
sudo systemctl reload nginx

4. ใช้ GeoIP หรือ IP-based blocking เพิ่มเติม

สำหรับการป้องกันที่ครอบคลุมมากขึ้น สามารถรวม GeoIP blocking หรือ IP-based blocking กับ User-Agent Blocking:

http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;

    map $geoip_country_code $block_country {
        default 0;
        KP 1;
        IR 1;
    }

    map $http_user_agent $block_bad_bot {
        default 0;
        ~*curl 1;
        ~*wget 1;
        "" 1;
    }

    server {
        listen 80;
        server_name example.com;

        if ($block_country = 1) {
            return 403;
        }

        if ($block_bad_bot) {
            return 403;
        }

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

สรุป

User-Agent Blocking เป็นเทคนิคที่สำคัญในการป้องกันเว็บไซต์จากการโจมตีและการรบกวนจากบอทที่ไม่พึงประสงค์ ด้วยการใช้ Nginx configuration อย่างถูกต้อง เราสามารถ:

  • ปิดกั้น User-Agent ที่ไม่พึงประสงค์ได้อย่างมีประสิทธิภาพ
  • อนุญาตเฉพาะบอทที่เชื่อถือได้เท่านั้น
  • บันทึกและวิเคราะห์การโจมตี
  • รวม User-Agent Blocking กับ Rate Limiting และการป้องกันอื่น ๆ
  • บำรุงรักษา Blocklist ให้อัดทันต่อข้อมูลใหม่

การตั้งค่า User-Agent Blocking ที่ดีจะช่วยลดภาระงานของเซิร์ฟเวอร์ เพิ่มความปลอดภัย และปกป้องข้อมูลของเว็บไซต์อย่างมีประสิทธิภาพ

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

หากท่านกำลังมองหาบริการ Cloud Infrastructure ที่เชื่อถือได้ เพื่อตั้งใจจัดเก็บและจัดการเว็บไซต์ของท่าน Dot Enterprise Co., Ltd. (DE) มีบริการที่เหมาะสมสำหรับความต้องการของท่าน:

  • Cloud VPS — บริการเซิร์ฟเวอร์เสมือนจริงที่มีความยืดหยุ่นสูง สามารถปรับแต่ง Nginx configuration ได้อย่างเต็มที่ เหมาะสำหรับเว็บไซต์ที่มีความต้องการเฉพาะ
  • Cloud Hosting — บริการ Hosting ที่มีการจัดการแบบแมนเนจด์ (Managed) ซึ่งรวมถึงการป้องกันความปลอดภัยและการบำรุงรักษาเซิร์ฟเวอร์ตั้งแต่ต้น

บริการของ DE พร้อมให้บริการด้วยประสิทธิภาพและความเชื่อถือได้สูง เพื่อให้เว็บไซต์ของท่านสามารถป้องกันตัวเองจากการโจมตีและบอทที่ไม่พึงประสงค์ได้อย่างมีประสิทธิภาพ ลองติดต่อทีมของ DE วันนี้เพื่อรับการให้คำปรึกษาและอัพเดตข้อมูลเพิ่มเติม