ระดมเครื่องมือเล็ก ๆ เพื่อบล็อกบอต
(lambdacreate.com)- Gitea และบล็อกบนเซิร์ฟเวอร์ส่วนตัวถูกทราฟฟิก scraping กดดันจนมีการแจ้งเตือนดิสก์, CPU และหน่วยความจำต่อเนื่อง ผู้ดูแลจึงตั้งรับด้วยการผสาน การวิเคราะห์ log, Nginx และ Fail2Ban
- ตามเกณฑ์ของ Zabbix ทราฟฟิกพุ่งสูงกว่าปกติมาก โดยค่าเฉลี่ยรายเดือนของ Nginx อยู่ที่ 8 requests ต่อวินาที และช่วงเลวร้ายที่สุดขึ้นไปถึง 20+ requests ต่อวินาที
- สาเหตุไม่ใช่การไหลเข้าจากแหล่งเดียวแบบ Reddit หรือ Hacker News แต่ใกล้เคียงกับ distributed scraping ที่ IP หลายบล็อกมากวาด URL ของ
www.lambdacreate.comและkrei.lambdacreate.com - Nginx ส่งคืน 403 ให้ user agent อันตรายที่รู้จัก และใช้การจำกัดจำนวนคำขอต่อ IP ส่วนไคลเอนต์ที่ทำให้เกิด 403 มากเกินไปจะถูก Fail2Ban บล็อก 24 ชั่วโมง
- ณ เวลาที่เขียน รายการบล็อกเพิ่มขึ้นรวมเป็น 735 bans และโดยเฉพาะคำขอที่พยายามสร้าง tarball สำหรับทุก commit ของ repository สาธารณะใน Gitea เป็นตัวเพิ่มภาระให้เซิร์ฟเวอร์
ทราฟฟิก scraping ที่กดดันเซิร์ฟเวอร์ส่วนตัว
- ทราฟฟิกบอตไม่พึงประสงค์หลั่งไหลเข้าพื้นที่อินเทอร์เน็ตส่วนตัวอย่างฉับพลัน จนกระทบบริการที่ผู้อ่านจริงควรเข้าถึงได้
- บริการที่ทำดัชนีเพื่อการเก็บรักษาเว็บไซต์อย่าง Archive.org อยู่ในกลุ่มที่อนุญาต แต่ Amazon, Facebook, OpenAI และบอตสุ่มหลายรายถูกแยกเป็นกลุ่มที่นำคอนเทนต์ไปใช้เพื่อเป้าหมายของตนเอง
- มองว่าการเก็บข้อมูลอินเทอร์เน็ตขนาดใหญ่ของบริษัทใหญ่ และความต้องการข้อมูลสำหรับฝึกโมเดล AI ยิ่งทำให้ แรงกดดันจาก scraping เพิ่มขึ้น
- ทราฟฟิกนี้ไม่ใช่ผู้บริโภคจริงของ Lambdacreate แต่ถูกมองเป็นสิ่งรบกวนที่ลดความสามารถในการเข้าถึงของผู้อ่านมนุษย์
Zabbix ตรวจพบสัญญาณผิดปกติก่อน
- สิ่งแรกที่แจ้งปัญหาคือ Zabbix โดยเกิดการเตือนว่าดิสก์สำหรับคอนเทนเนอร์เต็ม
- ในสภาพแวดล้อมที่ใช้ LXD ได้ขยาย ZFS sparse file และปิดไซต์ชั่วคราวก่อนเปิดขึ้นใหม่ แต่สาเหตุหลักยังคงอยู่
- หลังจากนั้น instance ของ Gitea ใช้ดิสก์จนหมดทุกวัน พร้อมสร้างข้อมูลวันละ 20–30GB
- ในช่วงแรกมองว่าเป็นปัญหาที่ Gitea ไม่ได้เปิดใช้การล้าง archive ของ repository เป็นค่าเริ่มต้น จึงตั้งค่างานล้างข้อมูลแบบเข้มงวด
- ไม่นานก็มีการเตือน CPU และหน่วยความจำตามมา การ
git pullและgit pushบน Gitea ทำได้ยากขึ้น และไคลเอนต์ weechat ก็รักษาการเชื่อมต่อไว้ไม่ได้
จำนวนคำขอพุ่งขึ้นระดับ 10 เท่าจากปกติ
- เพราะมีการมอนิเตอร์แบบ out-of-band ไว้เพื่อเปรียบเทียบตัวชี้วัดในอดีตกับสถานะปัจจุบัน จึงยืนยันรูปแบบผิดปกติได้
- ในแดชบอร์ด Zabbix ตัวชี้วัดหลักคือ จำนวนคำขอของ Nginx และกราฟ throughput ของเครือข่าย
- ปริมาณคำขอเฉลี่ยของ Nginx ในรอบหนึ่งเดือนอยู่ที่ประมาณ 8 requests ต่อวินาที
- ช่วงเลวร้ายที่สุดมีคำขอเข้ามา 20+ requests ต่อวินาที แม้จะดูน้อยเมื่อเทียบกับบริการขนาดใหญ่ แต่สำหรับเซิร์ฟเวอร์ส่วนตัวถือเป็น 10 เท่า ของปกติ จึงส่งผลมาก
- ภาระการดูแลเซิร์ฟเวอร์เพิ่มขึ้น เพราะไม่ได้มีแค่จำนวนคำขอ แต่ยังมีการใช้ดิสก์และ CPU ที่เกี่ยวกับ Gitea เพิ่มขึ้นพร้อมกัน
ไล่ตรวจ log ด้วย lnav และ goaccess
- เพื่อให้เซิร์ฟเวอร์อยู่ได้นานพอสำหรับตรวจ log จึงปิดคอนเทนเนอร์และ Nginx ชั่วคราวแล้วเริ่มวิเคราะห์
- เครื่องมือที่ใช้คือ lnav และ goaccess
lnavแสดงไฟล์ log ในรูปแบบ TUI พร้อมสี และมีเลเยอร์ abstraction เหนือรูปแบบ log ทั่วไป ทำให้ query log ด้วย SQL ได้- ใน
access.logตรวจสอบโดยเน้นคำถามต่อไปนี้- มี IP ผู้เข้าชมทั้งหมดกี่รายการ
- มีรูปแบบของ IP address หรือไม่
- เป็นทราฟฟิกที่มาจาก referrer เฉพาะหรือไม่
- ใช้ user agent ใดบ้าง
- IP ใดเชื่อมโยงกับ user agent ใด
- ผลการวิเคราะห์พบว่าไม่ใช่ “hug of death” ที่หลั่งไหลมาจาก referrer เดียว แต่เป็น IP หลายบล็อกที่กวาด URL ทั่วทั้งไซต์
ส่ง 403 ตาม user agent และจำกัดคำขอ
- การรับมือแรกคือทำรายการ user agent ที่ก่อปัญหาใน Nginx แล้วส่งคืน 403
- ตัวอย่าง configuration ใช้
map $http_user_agent $badagentเพื่อทำเครื่องหมาย agent อย่างAdsBot-Google,Amazonbot,Amazonbot/0.1 - ใน configuration หลักของ Nginx มีการ include กฎ user agent และตั้ง rate limit ต่อ IP ด้วย
- ในการตั้งค่า virtual host มีพฤติกรรมดังนี้
- ใช้การจำกัดคำขอด้วย
limit_req zone=krei burst=20 nodelay; - หาก
$badagentเป็นจริง จะบล็อกการเข้าถึงคอนเทนต์ด้วยreturn 403;
- ใช้การจำกัดคำขอด้วย
- วิธีนี้ช่วยลดการประมวลผลฝั่ง backend ได้ แต่เซิร์ฟเวอร์ยังต้องรับคำขอ HTTP และจัดการ 403 ดังนั้นเมื่อมีคำขอพร้อมกันจำนวนมาก ภาระก็ยังเหลืออยู่
ทำให้การบล็อกไฟร์วอลล์อัตโนมัติด้วย Fail2Ban
- หลังจาก log 403 สะสมแล้ว สามารถใช้
lnavตรวจ IP ที่ไม่ซ้ำซึ่งได้รับ 403 ได้ goaccessใช้วิเคราะห์ log ทั้งเก่าและปัจจุบันร่วมกัน เพื่อดูจำนวนคำขอที่เข้ามายังเซิร์ฟเวอร์และ endpoint ที่ถูกเล็งมากที่สุด- เพื่อปกป้องเซิร์ฟเวอร์จริง จึงเพิ่ม Fail2Ban เข้ามา
- กฎ Fail2Ban เป็นรูปแบบง่าย ๆ ที่จับ IP ซึ่งทำให้เกิด response 403 มากเกินไปจาก Nginx access log
- เวลาบล็อกตั้งไว้ที่ 86400 วินาที หรือ 24 ชั่วโมง
- ผลลัพธ์
fail2ban-client status nginx-forbiddenณ เวลาที่เขียนมีดังนี้- ความล้มเหลวปัจจุบัน: 13
- ความล้มเหลวรวม: 57135
- ถูกบล็อกปัจจุบัน: 38
- ถูกบล็อกรวม: 735
เป้าหมายจริงไม่ใช่บล็อก แต่เป็นการสร้าง tarball ของ Gitea
- ท้ายที่สุดผู้อ่านก็กลับมาเข้าถึงบล็อกและบริการอื่นของ Lambdacreate ได้อีกครั้ง
- ในสถานการณ์ที่ต้องกันทราฟฟิกหุ่นยนต์ แม้แต่การเขียนบทความบล็อกก็ยังทำได้ยาก
- ทราฟฟิกที่เป็นปัญหาไม่ได้เป็นการ scrape บล็อก แต่เล็งไปที่ การสร้าง tarball ของทุก commit ใน repository สาธารณะแต่ละตัวของ instance Gitea
- ในระยะยาวจะพิจารณาวิธีขยายรายการบล็อก หรือกำหนดข้อยกเว้นให้บริการที่ถูกต้องตามกฎหมายอย่าง Archive.org
- จุดยืนคือไม่ต้องการให้คอนเทนต์หายไปจาก search engine แต่ก็ไม่อยากปล่อยให้กลายเป็นเชื้อเพลิงสำหรับการทำให้อินเทอร์เน็ตแย่ลงด้วย AI
ยังไม่มีความคิดเห็น