- การครอว์ลและสแครปแบบไม่เลือกหน้าจากบริษัท AI/เสิร์ชรายใหญ่ส่งผลกระทบอย่างรุนแรงต่อเซิร์ฟเวอร์และบริการส่วนบุคคล ทำให้เกิด การใช้ทรัพยากรสิ้นเปลืองและบริการไม่เสถียร อย่างต่อเนื่อง
- หลังตรวจจับทราฟฟิกผิดปกติด้วยการมอนิเตอร์บนพื้นฐานของ Zabbix·Loki ก็ใช้เครื่องมือวิเคราะห์ล็อกอย่าง lnav, goaccess และคิวรีแบบ SQL เพื่อระบุ แพตเทิร์นของผู้โจมตี, IP, User Agent ได้อย่างละเอียด
- สร้างระบบป้องกันหลายชั้นทีละขั้นผ่านการตั้งค่า Nginx เช่น บล็อก 403 ตาม User Agent, rate limit และการเชื่อมต่อกับ Fail2Ban จนสามารถบล็อก IP อันตรายได้หลายร้อยรายการและทำให้เซิร์ฟเวอร์กลับมามีเสถียรภาพ
- ปัญหาหลักคือบอตที่พยายามดาวน์โหลดที่เก็บ Gitea ทั้งหมดในรูป tarball จำนวนมาก และทราฟฟิกที่เพิ่มขึ้นอย่างมากนั้นไม่ใช่ผู้บริโภคคอนเทนต์ทั่วไป แต่เป็นทราฟฟิกที่มีเป้าหมายเพื่อ เก็บข้อมูลสำหรับ AI/ฝึกโมเดล
- ในระยะยาวกำลังพิจารณากลยุทธ์ที่ยกเว้นให้บริการที่ถูกกฎหมายอย่าง archive.org และยังคงให้เสิร์ชเอนจินเข้าถึงได้ ขณะเดียวกันก็ต่อต้าน AI en-shitification
บทนำ: ทราฟฟิกจากบอตที่ถาโถมใส่เซิร์ฟเวอร์เล็ก ๆ ของฉัน
- ช่วงหลังมานี้มีทราฟฟิกปริมาณมากจากแหล่งที่ไม่ทราบแน่ชัดพุ่งเข้าสู่ บล็อก lambdacreate และบริการต่าง ๆ ที่ฉันดูแลอยู่เป็นการส่วนตัว
- บริการที่ถูกกฎหมายอย่าง Archive.org เป็นสิ่งที่ยินดีต้อนรับ แต่การครอว์ลข้อมูลแบบไม่ยั้งคิดจากบริษัทยักษ์ใหญ่อย่าง Amazon, Facebook, OpenAI กลับสร้างความเสียหายให้กับเว็บไซต์
- เมื่อความต้องการเก็บข้อมูลเพื่อฝึกโมเดล AI และงานลักษณะคล้ายกันสูงขึ้น ปรากฏการณ์นี้ก็ยิ่งรุนแรงมากขึ้น
- ในสถานการณ์แบบนี้ คนที่ต้องรับมือไม่ใช่ผู้อ่านตัวจริง (มนุษย์) แต่เป็นทราฟฟิกจากบอตจำนวนมหาศาลเป็นหลัก
การยืนยันปัญหา: วินิจฉัยการพุ่งขึ้นของทราฟฟิกผ่านเครื่องมือมอนิเตอร์
- ใช้เครื่องมือมอนิเตอร์อย่าง Zabbix, Loki เพื่อวิเคราะห์สถานการณ์การใช้ทรัพยากรของเซิร์ฟเวอร์
- พบว่าอินสแตนซ์ Gitea มีปริมาณข้อมูลเพิ่มขึ้นถึง 20~30GB ต่อวัน พร้อมการแจ้งเตือน CPU/หน่วยความจำหลายรายการ
- จากผลการวิเคราะห์ทราฟฟิกของ nginx ค่าเฉลี่ยรายเดือน 8req/s พุ่งขึ้นชั่วขณะเป็นมากกว่า 20req/s
- แม้ทราฟฟิกจะไม่ถือว่าใหญ่มากในระดับมหาศาล แต่ก็เพิ่มขึ้นเกือบ 10 เท่า จากปกติจนทำให้ทรัพยากรเริ่มร่อยหรอ
วิเคราะห์สาเหตุของการโจมตี: เจาะลึกล็อกไฟล์
- ใช้ lnav และ goaccess วิเคราะห์ nginx access log ด้วย SQL
- ตรวจดูแพตเทิร์นอย่าง IP ผู้เยี่ยมชม, UserAgent, Referrer เป็นต้น
- ผลลัพธ์คือไม่ได้เป็นทราฟฟิกที่ไหลเข้ามาจากบริการหรือคอมมูนิตี้ใดโดยเฉพาะ แต่เป็น การครอว์ลจำนวนมากจากช่วง IP บางช่วง
- พบค่าที่ระบุหรือปลอมแปลงใน UserAgent จำนวนมาก เช่น Amazonbot, OpenAI, Applebot, Facebook
- เมื่อสิ่งนี้เริ่มรบกวนการใช้งานบริการจริง ความจำเป็นในการใช้นโยบายบล็อกที่เข้มงวดจึงชัดเจนขึ้น
วิธีแก้: ผสานการป้องกันหลายชั้นด้วย Nginx, Fail2Ban และอื่น ๆ
- ใช้ Nginx map เพื่อส่งคืน 403 ให้กับ UserAgent อันตรายทันที และนำ rate limit (จำกัดความเร็วในการเข้าชม) มาใช้
- ลดภาระของเซิร์ฟเวอร์ให้ต่ำที่สุดด้วยการลดความถี่ของเว็บรีเควสต์ แม้กระทั่งกับบอตใหม่หรือบอตที่ยังตรวจไม่พบ
- ตรวจจับ IP และ UserAgent อันตรายตัวใหม่ด้วย goaccess, lnav โดยอิงจากล็อกที่เกิด 403
- ใช้เครื่องมือความปลอดภัยอัตโนมัติ Fail2Ban เพื่อบล็อก IP ที่ทำให้เกิดการตอบกลับ 403 มากเกินไปโดยอัตโนมัติเป็นเวลา 24 ชั่วโมง
- มีบันทึกการแบนอัตโนมัติมากกว่า 735 ครั้ง
- อัตราการใช้ทรัพยากรจริงกลับสู่ภาวะปกติในระดับที่ชัดเจน
- ต่อจากนี้มีแผนจะใช้ กฎยกเว้นสำหรับบริการปกติ อย่าง archive.org และยังอนุญาตให้เสิร์ชเอนจินทำดัชนีได้ แต่จะยังคงบล็อกการครอว์ลแบบไม่เลือกหน้าเพื่อใช้ฝึก AI ต่อไป
บทสรุป: พลังของการผสานเครื่องมือและความจำเป็นของความปลอดภัยสำหรับบริการส่วนบุคคล
- ด้วยการใช้ มาตรการป้องกันหลายชั้น เหล่านี้อย่างต่อเนื่อง จึงสามารถกู้คืนการดูแลบล็อกส่วนตัวให้ราบรื่นและทำให้การเข้าถึงบริการกลับมาเป็นปกติ
- สิ่งนี้ยืนยันว่าการใช้เครื่องมือจัดการระบบและระบบอัตโนมัติขนาดเล็กหลายตัวร่วมกันมีประสิทธิภาพต่อความปลอดภัยของเซิร์ฟเวอร์ส่วนบุคคล
- ในสภาพแวดล้อมที่แม้แต่เซิร์ฟเวอร์ส่วนบุคคลก็ถูกครอว์ลอย่างไม่เลือกหน้าเพราะ ความต้องการฝึก AI ที่เพิ่มขึ้น การ บล็อกเชิงรุกและการทำระบบจัดการอัตโนมัติ จึงเป็นสิ่งจำเป็น
1 ความคิดเห็น
ความเห็นจาก Hacker News
มักจะเห็นอยู่บ่อย ๆ ว่าครอว์เลอร์ไร้มารยาทจำนวนมากแค่แกล้งทำตัวเป็นเสิร์ชเอนจินรายใหญ่ บางคนก็บอกว่าไม่ควรไปหลงเชื่อข้อมูลใน user-agent วิธีที่ผมชอบที่สุดอย่างหนึ่งคือใส่ข้อมูลล่อใน robots.txt (เช่น gzip bomb) แล้วตั้งให้ครอว์เลอร์ที่ตรวจพบสิ่งนี้ถูกบล็อกตั้งแต่คำขอถัดไป ทำได้ง่าย ๆ ด้วย Caddy และวิธีนี้มักจะจับตัวที่ทำผิดร้ายแรงได้ ผมไม่ได้คิดจะแก้ตัวให้พฤติกรรมของบอต แต่ถ้าบอตไม่กี่ตัวทำให้ไซต์ล่มได้ ก็เป็นหลักฐานว่าไซต์นั้นเปราะบางต่อผู้โจมตีที่มีเจตนาร้ายมาก
รู้สึกว่าคอมเมนต์สุดท้ายนี่แหละที่พูดได้ตรงประเด็นจริง ๆ อาจจะเป็นเพราะผมคนละเจเนอเรชันก็ได้ แต่ผมไม่เข้าใจว่าทำไมคนเขียนสมัยนี้ถึงหมกมุ่นกับการใช้ทรัพยากรให้น้อยมากขนาดนั้น เหมือนปู่ย่าตายายที่โวยวายเรื่องปิดไฟ LED หรือขับรถอ้อม 24 กม. เพื่อประหยัดค่าน้ำมัน 5 เซนต์ การยิง 20 คำขอต่อวินาทีนี่แทบไม่ใช่อะไรเลย ต่อให้สร้างแบบไดนามิกจริง ๆ ก็ตาม (ซึ่งทำไมต้องทำด้วย? เอาเวลาไปตั้งค่าแคชน่าจะคุ้มกว่าเยอะ) เดี๋ยวนี้บทความสไตล์ 'fuck the bots' กำลังฮิตก็จริง แต่หัวข้อนี้ไม่ใช่เรื่องใหม่เลย มีวิธีจัดการที่สร้างสรรค์กว่านี้อีกเยอะโดยไม่ต้องเสียเวลา
อยากฟังรายละเอียดเพิ่มเติมเรื่องการวาง gzip bomb ใน robots.txt ผมเข้าใจว่า AI ส่วนใหญ่ไม่สน robots.txt อยู่แล้ว เลยสงสัยว่าสุดท้ายมันจะจับได้แค่ครอว์เลอร์ใสซื่อบางส่วนหรือเปล่า ไม่ได้จะคัดค้านใคร แค่อยากรู้วิธีทำที่ไม่ทำผลเสียกับฝั่งที่ไม่มีพิษมีภัย
ผมดูแลหนึ่งในวิกิที่ใหญ่ที่สุดแห่งหนึ่งในสายงานของตัวเอง แต่แทบเป็นไปไม่ได้เลยที่จะโน้มน้าวคนอื่นในทีมพัฒนาให้ใช้ gzip bomb พวกเขายืนกรานว่าวิธีนี้มีความเสี่ยงสูงเกินไป (แนวคิดแบบกลัวข้อบังคับ EU) และไม่คุ้มที่จะผลักดัน เลยสงสัยว่ามีใครใช้วิธีนี้กับเว็บไซต์สาธารณะจริง ๆ ไหม
ทุกวันนี้บอตไม่เคารพไฟล์ robots.txt กันเลย น่าหงุดหงิดจริง ๆ ผมคิดว่าคนที่ทำสิ่งนี้ขึ้นมานี่เห็นแก่ตัวมาก ถ้าเป็นคนทำบอตแบบนั้นก็เชิญรับมือกันเองเลย
ถ้าฝังกับดัก (honeypot) ไว้ในไฟล์ robots ถึงจะจับพวกที่เมินมันไปเลยไม่ได้ แต่ก็ช่วยกรองบอตที่ตั้งใจมาปั่นป่วนและคอยหาช่องได้บ้าง
คุณก็สามารถพูดแบบเดียวกันกับคนที่ใช้แชตบอต เสิร์ชเอนจิน หรือเครื่องมือเปรียบเทียบราคาได้เหมือนกัน เพราะจริง ๆ แล้วผู้ใช้เหล่านี้นี่แหละคือตัวการสำคัญที่สร้างแรงจูงใจทางเศรษฐกิจให้สแครปเปอร์
ผมเข้าใจที่ผู้เขียนบอกว่า “ตอนนี้ไม่สนใจแล้ว” แต่ผมเห็นว่าใน IP ที่ถูกแบนมี Google, ripe.net และ semrush อยู่ด้วย ไม่รู้บริษัทอื่นนะ แต่ Google ผมคงไม่บล็อกจริง ๆ ถ้าอยากให้เว็บไซต์เป็นที่รู้จัก ผมก็คิดว่าไม่จำเป็นต้องบล็อก Semrush หรือ ripe.net เหมือนกัน ถึงคอนเทนต์ของผมจะถูก AI หรือพวกประหลาดเอาไปสแครป ผมก็คิดว่าในเมื่อเปิดเว็บสาธารณะตั้งแต่แรก ก็ควรทำใจไว้อยู่แล้วว่ามันจะถูกนำไปใช้บ้าง เปรียบเหมือนปิดไฟป้ายโมเทลแล้วชวนลูกค้าเข้าพัก
Semrush สร้างความเดือดร้อนหนักมากในหลายระดับมาเป็นเวลานาน ถึงขั้นที่ตลอด 8 ปีที่ผ่านมา ผมทิ้งข้อความพิเศษไว้ใน robots.txt ด้วย สุดท้ายถึงขั้นต้องให้ทีมกฎหมายเข้ามาขยับถึงจะสงบลงได้ จากมุมของผม การปล่อยให้บริษัทสาย 'SEO' มาถ่างทางผู้เข้าชมจริงแล้วไล่ขูดไซต์แบบหยาบ ๆ มันไม่มีคุณค่าอะไรเลย คู่แข่งของ Semrush ก็หนักไม่แพ้กัน ส่วน AI scraper ทุกวันนี้ก็คุณภาพต่ำมากจนผมเคยต้องส่งหนังสือร้องเรียนอย่างเป็นทางการซ้ำ ๆ ไปถึงนักลงทุนรายใหญ่และฝ่าย PR ด้วย ผมค่อย ๆ ทำให้สถานการณ์กลับมาปกติได้ ทั้งในทางเทคนิคและทางกฎหมาย
ปัญหาจริงคือบอตกินทราฟฟิกจำนวนมาก (แบนด์วิดท์ หน่วยความจำ CPU ทรัพยากรดิสก์) ซึ่งในบทนำก็พูดถึงมารยาทที่รับไม่ได้เอาไว้แล้ว ผมรู้สึกว่าไม่มีเหตุผลอะไรต้องยกทราฟฟิกพวกนี้ให้สแครปเปอร์ Google เองก็รัน AI scraper อยู่ด้วย เลยคิดว่าอาจเป็นสาเหตุที่ไปโผล่ในรายการบล็อก
มีบอตอันตรายจริง ๆ ที่แอบอ้างเป็น Google อยู่เหมือนกัน แต่ก่อน Google สแครปได้ค่อนข้างสุภาพกว่า ถ้าผู้เขียนจะบล็อกหรือไม่บล็อก ในเมื่อมันได้ทราฟฟิกที่ต้องการไปแล้วก็คงไม่สนอะไรนัก
สงสัยว่าตลอด 10 ปีที่ผ่านมา คนยังไม่รู้กันอีกหรือว่าไม่ควรใช้ Google โดยเฉพาะตอนนี้ที่ Google ใช้ AI มาคัดกรองเว็บไซต์อิสระแล้ว มีคอมเมนต์ที่ลิงก์ตรงไว้ด้วย ตอนนี้ผมมองว่า Google ใกล้จะเป็นภาระมากกว่าสินทรัพย์แล้ว
เพราะบอตทำให้ไฟล์ล็อกของเซิร์ฟเวอร์ใหญ่เกินไป จนเซิร์ฟเวอร์ของผมต้องปิดการล็อกไปเลย บอตไล่สแครปทั้ง API, ฟอร์ม, และแม้แต่ส่วนที่บนเว็บไซต์เข้าถึงได้เฉพาะผ่านการคลิกเท่านั้น Anthropic, openAI, Facebook และเจ้าอื่น ๆ ก็ยังสแครปเว็บไซต์ของผมอยู่
ถ้าเป็น API ที่เข้าถึงได้เฉพาะผ่านการคลิก ผมสงสัยว่าบอตเข้าถึงได้ยังไง
อยากรู้รายละเอียดเพิ่มเติมเกี่ยวกับ API แบบนั้น ว่าหมายถึงส่วนที่เป็นส่วนหนึ่งของ UI หรือส่วนที่มนุษย์เท่านั้นใช้ได้ หรือหมายถึงว่าไม่มีเส้นทางอื่นเลย ช่วงนี้ AI agent เลียนแบบพฤติกรรมผู้ใช้จริงได้แล้ว จนแทบจะแยกมนุษย์กับบอตไม่ออก
ตอนแรกผมคิดว่าดีที่บอตครอว์เลอร์ AI กรอก
User-Agentheader กันอย่างซื่อสัตย์ แต่ก็ค่อนข้างตกใจที่มันเป็นสาเหตุของทราฟฟิกเยอะระดับนี้ เว็บไซต์ส่วนใหญ่ไม่ได้ต้องการข้อมูลบ่อยขนาดนี้เลย แต่ทราฟฟิกกลับมากเกินไป ยิ่งถ้าเป็นบล็อกของนักพัฒนายิ่งไม่เข้าใจผมเป็นผู้สร้าง tirreno แพลตฟอร์มของเราถูกปรับให้เหมาะกับผู้ใช้ที่ล็อกอินอยู่แบบสด ๆ แต่ก็ใช้ตรวจจับและบล็อกบอตได้อย่างมีประสิทธิภาพเช่นกัน เราใช้วิธีแทนที่ octet สุดท้ายของ IP ด้วยเครื่องหมายดอกจัน (*) เพื่อทำให้ IP ไม่ระบุตัวตน และรวม subnet เดียวกันเป็นบัญชีเดียว สามารถตั้งให้สร้างบัญชีดำอัตโนมัติจากความผิดปกติของทราฟฟิกได้ (เช่น error 500/404, การพยายามล็อกอินแบบสุ่ม, IP จากดาต้าเซ็นเตอร์ ฯลฯ) และสามารถใช้ blacklist API ของ tirreno เพื่อรีไดเร็กต์ทราฟฟิกที่ไม่ต้องการไปยังหน้า error ได้ นอกจากนี้ยังมีแดชบอร์ดมอนิเตอร์เพื่อช่วยจัดการและลด false positive
tirreno Github, เดโมผู้ดูแลระบบ
เดี๋ยวนี้ ISP หลายแห่งเปลี่ยนไปใช้โครงสร้าง CGNAT เลยสงสัยว่าจัดการปัญหาที่ IP เดียวอาจแทนผู้ใช้จริงหลายร้อยคนได้อย่างไร
ผมก็กำลังพัฒนาการบล็อกบอตแบบเดียวกันจากช่วง IP สาธารณะที่เปิดเผยอยู่ ถ้ามีไอเดียปรับปรุงก็ยินดีรับเสมอ
เพราะการแทนที่ octet สุดท้ายของ IP แบบนี้ ทำให้ผมถูกจับรวมเป็นผู้ใช้คนเดียวกับเพื่อนบ้านในที่อยู่ที่ไม่เกี่ยวอะไรกับข้อมูลของผมเลย และ false positive จาก IP ศูนย์ข้อมูลก็ไม่ใช่เรื่องเล็กจริง ๆ ทุกวันนี้ถ้าอะไรไม่โดนบล็อก ผมยังต้องคลิกไฟจราจร 87 ดวงกว่าจะผ่านได้ สุดท้ายมันก็ดูเหมือนเป็นข้ออ้างว่าจะไม่เก็บข้อมูลส่วนตัวของผมโดยไม่ได้รับความยินยอมในขั้นตอนหลบ false positive อยู่ดี อยากให้มีโครงสร้างฟีดแบ็กที่ทำให้ลูกค้ารู้ได้ทันทีว่าพวกเขากำลังเสียผู้ใช้ที่ยอมจ่ายเงินจริง
มีเรื่องหนึ่งที่ผมสงสัยมานานแล้ว คือจะทำโครงสร้างแบบ “page knocking” ได้ไหม หมายถึงเปิดหน้าตามลำดับที่กำหนดก่อนถึงจะได้สิทธิ์เข้าใช้งาน เช่น ต้องเข้า URL ลับที่กำหนดไว้ก่อน หน้าอื่น ๆ ถึงจะไม่ขึ้น 404 แต่แสดงผลตามปกติ
สถาปัตยกรรมแบบนั้นไม่เหมาะกับกรณีที่ต้องให้ผู้ใช้ทั่วไปค้นหาโปรเจ็กต์ผ่านเสิร์ชเอนจินแล้วเข้าใช้งานได้ทันทีโดยไม่ต้องสร้างบัญชีหรือยืนยันตัวตนแยกต่างหาก
ในแง่การใช้งาน ต่อให้ออกแบบมาดีแค่ไหนก็คงเลี่ยงความไม่สะดวกไม่ได้ น่าจะมีปัญหาเวลาใช้บุ๊กมาร์กหรือส่งลิงก์ให้เพื่อนแล้วเจอแต่ 404 อยู่เรื่อย ๆ
เซิร์ฟเวอร์เล็ก ๆ ของผมทำงานได้ดี เลยไม่ได้ดูสถานะ fail2ban มาสักพักแล้ว
ผลลัพธ์คำสั่งเทียบกัน:
พอเห็นว่ามี IP ถูกบล็อกเกิน 220,000 รายการก็ช็อกนิดหน่อย
บอตชื่อ 'DotBot/1.2' ที่เราติดตามอยู่ทิ้งคำขอไว้มากกว่า 220,000 ครั้งในช่วง 2 สัปดาห์ที่ผ่านมา รูปแบบคือสุ่มขอชื่อไฟล์และโฟลเดอร์บนเว็บเซิร์ฟเวอร์ ด้วยความอยากรู้ว่ามันจะขุดคุ้ยลึกแค่ไหน ผมเลยตั้งใจไม่บล็อกและเฝ้าดูอยู่
ผมกำลังคิดว่าโครงสร้างการทำดัชนีแบบรวมศูนย์สำหรับ AI หรือเสิร์ชเอนจิน น่าจะต้องเปลี่ยนไปเป็นแบบ push หรือ submit ได้แล้วหรือเปล่า ถ้าเป็นโครงสร้างที่ผมแชร์เองโดยตรงเฉพาะตอนที่ต้องการ ปัญหาการสแครปก็น่าจะลดลงมาก
ตอนผมยังเด็กในยุค 90 เคยมีโทรศัพท์จาก ISP แจ้งว่าคอมพิวเตอร์ของผมติดบอตเน็ต และจะถูกตัดการเชื่อมต่ออินเทอร์เน็ต ผมเลยคิดว่าถ้ากลับไปใช้แนวทางแบบนั้น แล้วบล็อกทั้ง ASN ของ ISP ที่ปล่อยให้เรื่องนี้เกิดขึ้น ปัญหาพวกนี้อาจหมดไปก็ได้
residential proxy ไม่ได้เกิดจาก ISP ให้บริการโดยตรง แต่เกิดจากผู้ใช้ทั่วโลกที่ติดตั้งมัลแวร์ลงเครื่องตัวเองทั้งแบบตั้งใจและไม่รู้ตัว แล้วปล่อยให้คอมพิวเตอร์ของตัวเองกลายเป็นพร็อกซี เมื่อไม่นานมานี้มีบทความดี ๆ เกี่ยวกับเรื่องนี้ขึ้น HN ด้วย
ผมตั้งกฎไฟร์วอลล์ให้แจ้งเตือนทุกครั้งที่อุปกรณ์ใดในเครือข่ายของผมพยายามเชื่อมต่อขาออกไปยังพอร์ตที่เกี่ยวข้องกับมัลแวร์ รายการพอร์ตต้องอัปเดตเป็นระยะเพราะเป้าหมายของมัลแวร์เปลี่ยนตลอด เป็นวิธีเล็ก ๆ น้อย ๆ แต่ก็เป็นอีกชั้นของการป้องกัน