บนแผนที่การโจมตีมีจุดหนาแน่นอยู่เหนือประเทศหนึ่ง และกฎที่ว่า «ห้ามทั้งประเทศไปเลย» ก็ผุดขึ้นมาเอง กฎนั้นแทบไม่ให้อะไรเลย: การเปลี่ยนประเทศทางออกใช้เวลาของผู้โจมตีเพียงไม่กี่นาที ขณะที่คนที่ตกอยู่ใต้การห้ามคือผู้เข้าชมของคุณเองและตัวคุณเองเวลาเดินทาง ที่แย่กว่านั้น ตัวเก็บข้อมูลที่มองเห็นได้ซึ่งมาจากคลาวด์เดียว หลังถูกปิดกั้นจะย้ายไปใช้ที่อยู่ตามบ้านเรือนและกลายเป็นสิ่งที่แยกไม่ออกจากคน
ด้านล่างนี้คือห้าขั้นตอนที่บนเซิร์ฟเวอร์เครื่องเดียวกันให้ผลจริง: ตัดตัวสแกนออก จำกัดจังหวะ ไม่ตัดสิ่งที่จำเป็น และถ้าจำเป็นจริง ๆ ก็ปิดกั้นให้ถูกวิธี ทั้งหมดตรวจสอบและตั้งค่าได้ในคราวเดียว
ขั้นที่ 1 ดูว่าใครเป็นคนสร้างจุดนั้นขึ้นมาจริง ๆ
ก่อนอื่นให้หาบันทึกคำขอก่อน บนเซิร์ฟเวอร์ที่มีหลายเว็บไซต์ access.log มักจะว่างเปล่า ส่วนรายการจะไปอยู่ในบันทึกของโฮสต์เสมือนแต่ละตัว:
sudo ls -lS /var/log/apache2/*access*.log /var/log/apache2/*requests*.log 2>/dev/null
ในคำสั่งต่อ ๆ ไปทั้งหมดให้แทนด้วยไฟล์ที่ขึ้นมาอยู่บนสุดของรายการนั้น เริ่มจากที่อยู่อันดับต้นของวัน แล้วจึงดูว่าที่อยู่อันดับหนึ่งขอสิ่งใดกันแน่:
sudo awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
sudo grep '^203\.0\.113\.' /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
คำสั่งที่สองตอบคำถามหลัก ถ้าในผลลัพธ์มีหน้าเว็บของคุณเองหลายสิบหน้าที่ต่างกัน นั่นคือตัวเก็บเนื้อหา: ไม่เป็นอันตราย และเพียงแค่ไม่นับว่าเป็นผู้เข้าชมก็พอ ถ้าในนั้นมี /wp-login.php, /.env, /phpmyadmin และสิ่งอื่นที่คุณไม่มีอยู่เลย นั่นคือตัวสแกน และขั้นที่ 2 จะจัดการกับมัน สำหรับ nginx บันทึกจะอยู่ใน /var/log/nginx/ ฟิลด์เหมือนกัน
ขั้นที่ 2 Jail สำหรับคำขอไปยังสิ่งที่คุณไม่มี
เส้นทางที่ร้องขอปลอมไม่ได้ — มันคือเจตนาในตัวเอง ต่างจากที่อยู่และ User-Agent ตัวกรอง /etc/fail2ban/filter.d/web-probes.local:
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) /(wp-login\.php|wp-admin|xmlrpc\.php|\.env|\.git/|phpmyadmin|administrator/)
ignoreregex =
Jail /etc/fail2ban/jail.d/web-probes.local:
[web-probes]
enabled = true
port = http,https
filter = web-probes
logpath = /var/log/apache2/*access.log
maxretry = 1
findtime = 1h
bantime = 1d
ตรงนี้ maxretry = 1 มีเหตุผลรองรับ: ไม่มีใครเข้าหน้าผู้ดูแลของคนอื่นโดยบังเอิญ นำไปใช้แล้วตรวจให้แน่ใจว่าตัวกรองจับบรรทัดในบันทึกของคุณเองได้:
sudo fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/web-probes.local
sudo systemctl reload fail2ban && sudo fail2ban-client status web-probes
ขั้นที่ 3 จำกัดจังหวะ
ตัวสแกนและตัวเก็บข้อมูลเผยตัวเองด้วยความเร็ว ไม่ว่าจะมาจากประเทศใด สามสิบหน้าต่อนาทีจากที่อยู่เดียวคือเกณฑ์ที่ไม่กระทบคนที่กำลังพลิกดูแค็ตตาล็อก:
[http-flood]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/site_access.log
maxretry = 30
findtime = 60
bantime = 1h
รายละเอียดสำคัญคือบันทึกใดที่ระบุไว้ใน logpath ถ้ารูปแบบนั้นครอบคลุมบันทึกของแผงควบคุมเองหรือส่วนผู้ดูแลด้วย คุณจะปิดกั้นตัวเอง: หน้าเดียวในนั้นลากคำขอสไตล์และสคริปต์ตามมาอีกสิบกว่ารายการ และสามสิบรายการก็ครบได้ในสองคลิก ด้วยเหตุนี้จึงให้แผงควบคุมมีไฟล์บันทึกแยกต่างหากที่ไม่ตรงกับรูปแบบของ jail ส่วนไฟล์สแตติกให้ตั้งอายุแคชยาว ๆ เพื่อให้เบราว์เซอร์ไม่ขอซ้ำทุกครั้งที่เปลี่ยนหน้า อาการที่เกิดขึ้นถ้าพลาดไปแล้ว: HTML มาถึง แต่รูปแบบการแสดงผลไม่มา หน้าค้าง การปลดการปิดกั้น:
sudo fail2ban-client set http-flood unbanip 203.0.113.10
ขั้นที่ 4 ปกป้องสิ่งที่ห้ามตัดทิ้ง
ก่อนเปิดใช้การปิดกั้น ให้เขียนข้อยกเว้นลงไปก่อน — ไม่เช่นนั้นสิ่งแรกที่ตกอยู่ใต้การปิดกั้นจะเป็นสิ่งที่จำเป็น:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 66.249.64.0/19
สิ่งที่ต้องมีในบรรทัดนี้แน่นอนและเหตุผล:
- ที่อยู่ของคุณเองหรือซับเน็ตของสำนักงาน สาเหตุที่พบบ่อยที่สุดของการเสียสิทธิ์เข้าถึงเซิร์ฟเวอร์คือกฎของตัวเอง ไม่ใช่การโจมตี
- ช่วง
66.249.64.0/19โรบอตค้นหาของ Google ระบุตัวได้จาก User-Agent แต่ส่วนของมันที่รัน JavaScript จะเข้ามาในฐานะChrome/Linuxธรรมดาและไม่บอกชื่อตัวเอง กฎใด ๆ ในทำนอง «ปิดกั้นทราฟฟิกจากศูนย์ข้อมูล» จะกระทบส่วนนั้นพอดี หลังจากนั้นหน้าเว็บจะหลุดออกจากดัชนีอย่างเงียบ ๆ ที่อยู่ที่น่าสงสัยตรวจได้ด้วยการสอบถามย้อนกลับ:dig -x 66.249.66.1 +shortต้องคืนชื่อในโซนgooglebot.com - ที่อยู่ของการแจ้งเตือนการชำระเงิน เว็บฮุกของระบบชำระเงินมาจากเซิร์ฟเวอร์ AWS และ Azure ถ้าคุณปิดคลาวด์เหล่านั้นทั้งหมด การยืนยันการชำระเงินจะเลิกมาถึง และคุณจะรู้ตอนที่ลูกค้าเขียนมาว่าเงินถูกตัดแล้วแต่ยังไม่ได้สิทธิ์เข้าใช้ ช่วงที่อยู่ดูได้จากเอกสารของผู้ให้บริการชำระเงินของคุณ
ขั้นที่ 5 ถ้าจำเป็นต้องปิดกั้นจริง ๆ ให้ปิดกั้นซับเน็ต ไม่ใช่ประเทศ
การหนาแน่นที่คงอยู่จากเครือข่ายเดียว ซึ่งอยู่ต่อเนื่องหลายวันและมาพร้อมคำขอแบบเดียวกัน คือผู้ลงมือรายเดียวที่ไล่ไปตามรายการ กรณีแบบนี้ปิดกั้นแบบเจาะจงและมีกำหนดเวลา:
sudo ufw deny from 198.51.100.0/22 to any
sudo ufw status numbered
ใช้คำสั่งที่สองจดหมายเลขของกฎไว้: ภายหลังต้องปลดการปิดกั้นผ่านหมายเลขนั้นเอง sudo ufw delete <หมายเลข> ตกลงกับตัวเองเรื่องกำหนดเวลา เช่น หนึ่งเดือน แล้วใส่การปลดลงในปฏิทิน กฎที่ตั้งไว้ «ตลอดไป» พอผ่านไปหนึ่งปีจะกลายเป็นรายการที่ไม่มีใครกล้าแตะ เพราะไม่มีใครจำได้ว่าที่อยู่เหล่านั้นเข้าไปอยู่ในนั้นด้วยเหตุใด
จะปิดกั้นซับเน็ตใดนั้นดูได้จากที่อยู่ในขั้นแรก: whois 198.51.100.17 | grep -iE 'route|cidr|netname'
อะไรเปลี่ยนไปหลังห้าขั้นตอนนี้
ตัวสแกนถูกตัดตามเจตนา ไม่ใช่ตามแหล่งที่มา และถูกจับได้ตั้งแต่คำขอแรก ตัวเก็บข้อมูลชนเพดานจำกัดจังหวะ โรบอตค้นหาและการแจ้งเตือนการชำระเงินยังผ่านได้ตามปกติ การปิดกั้นกว้าง ๆ ที่เหลืออยู่เพียงอย่างเดียวนั้นเจาะจง มีกำหนดเวลาที่รู้ชัดและมีเหตุผลที่เข้าใจได้
แผนที่ไม่ได้หายไปไหน แต่บทบาทเปลี่ยนไป: มันมีไว้ไม่ใช่เพื่อปิดประเทศ แต่เพื่อสังเกตเห็นการหนาแน่นนั้นเองและเทียบกับเมื่อสัปดาห์ก่อน สิ่งที่ต้องใช้คือประวัติ ไม่ใช่ภาพนิ่งของวันปัจจุบัน แผนที่แบบนั้นเมื่ออยู่คู่กับบันทึกการปิดกั้นและรายการพอร์ตที่เปิดอยู่จะเป็นอย่างไร ดูได้จากหน้าสาธิตด้านล่าง