Trên bản đồ tấn công có một vệt đậm nằm trên một quốc gia, và quy tắc «cấm cả nước đó» tự nó hiện ra trong đầu. Nó hầu như không mang lại gì: đổi quốc gia đầu ra chỉ tốn của kẻ tấn công vài phút, trong khi lệnh cấm lại rơi trúng chính khách truy cập của bạn và cả bạn khi đi công tác. Tệ hơn nữa, một trình thu thập dữ liệu nhìn thấy được, đến từ một đám mây duy nhất, sau khi bị chặn sẽ chuyển sang các địa chỉ dân cư và trở nên không thể phân biệt với con người.
Dưới đây là năm bước thực sự mang lại kết quả trên chính máy chủ đó: cắt các trình quét, giới hạn nhịp độ, không cắt những thứ cần thiết và, nếu vẫn thật sự cần, thì chặn cho đúng. Tất cả đều có thể kiểm tra và thiết lập trong một lần ngồi.
Bước 1. Xem ai thực sự tạo ra vệt đậm đó
Trước tiên hãy tìm nhật ký yêu cầu. Trên máy chủ có nhiều trang, access.log thường trống, còn các dòng ghi lại đi vào nhật ký của máy chủ ảo tương ứng:
sudo ls -lS /var/log/apache2/*access*.log /var/log/apache2/*requests*.log 2>/dev/null
Trong mọi lệnh tiếp theo, hãy thay bằng tệp nằm ở đầu danh sách đó. Trước hết là các địa chỉ dẫn đầu trong ngày, sau đó là thứ mà địa chỉ đứng đầu thực sự yêu cầu:
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
Lệnh thứ hai trả lời câu hỏi chính. Nếu trong kết quả là hàng chục trang khác nhau của chính trang web bạn, đó là một bộ thu thập nội dung: vô hại, và chỉ cần không tính nó là khách truy cập. Nếu ở đó có /wp-login.php, /.env, /phpmyadmin và những thứ khác mà bạn không hề có, đó là một trình quét, và bước 2 sẽ xử lý nó. Với nginx, các nhật ký nằm trong /var/log/nginx/, các trường vẫn như vậy.
Bước 2. Một jail cho những yêu cầu tới thứ bạn không có
Đường dẫn được yêu cầu thì không thể giả mạo — chính nó là ý định, khác với địa chỉ và User-Agent. Bộ lọc /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
Ở đây maxretry = 1 là hợp lý: không ai vô tình truy cập vào trang quản trị của người khác. Hãy áp dụng và kiểm tra rằng bộ lọc bắt được các dòng trong nhật ký của chính bạn:
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
Bước 3. Giới hạn nhịp độ
Trình quét và trình thu thập tự để lộ mình qua tốc độ, bất kể chúng đến từ quốc gia nào. Ba mươi trang mỗi phút từ một địa chỉ là ngưỡng không chạm tới người đang lật xem một danh mục:
[http-flood]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/site_access.log
maxretry = 30
findtime = 60
bantime = 1h
Chi tiết then chốt là nhật ký nào được ghi trong logpath. Nếu mẫu đó bao luôn nhật ký của chính bảng điều khiển hay khu vực quản trị, bạn sẽ tự chặn mình: một trang ở đó kéo theo cả chục yêu cầu tới kiểu dáng và tập lệnh, còn ba mươi thì chỉ hai cú nhấp là đủ. Vì vậy người ta cho bảng điều khiển một tệp nhật ký riêng không khớp với mẫu của jail, còn các tệp tĩnh thì đặt thời hạn lưu đệm dài để trình duyệt không yêu cầu lại chúng ở mỗi lần chuyển trang. Dấu hiệu, nếu điều đó vẫn xảy ra: HTML về tới nơi, phần trình bày thì không, trang treo. Gỡ lệnh chặn:
sudo fail2ban-client set http-flood unbanip 203.0.113.10
Bước 4. Bảo vệ những thứ không được cắt
Trước khi bật các lệnh chặn, hãy ghi ra các ngoại lệ — nếu không, thứ đầu tiên rơi vào chúng lại chính là thứ cần thiết:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 66.249.64.0/19
Những gì nhất thiết phải có trong dòng đó và vì sao:
- Địa chỉ của chính bạn hoặc dải mạng con của văn phòng. Nguyên nhân phổ biến nhất khiến mất quyền truy cập vào máy chủ là quy tắc của chính mình, chứ không phải một cuộc tấn công;
- Dải
66.249.64.0/19. Robot tìm kiếm của Google nhận biết được qua User-Agent, nhưng phần của nó chạy JavaScript lại đến dưới dạng mộtChrome/Linuxthông thường và không tự xưng danh. Bất kỳ quy tắc kiểu «chặn lưu lượng từ trung tâm dữ liệu» nào cũng đánh trúng đúng phần đó, sau đó các trang lặng lẽ rơi khỏi chỉ mục. Một địa chỉ đáng ngờ có thể kiểm tra bằng truy vấn ngược:dig -x 66.249.66.1 +shortphải trả về một tên trong vùnggooglebot.com; - Các địa chỉ gửi thông báo thanh toán. Webhook của các hệ thống thanh toán đến từ máy chủ AWS và Azure. Nếu bạn đóng trọn các đám mây đó, xác nhận thanh toán sẽ không còn tới nơi, và bạn chỉ biết điều đó khi khách hàng viết rằng tiền đã bị trừ còn quyền truy cập thì không có. Các dải địa chỉ được lấy từ tài liệu của nhà cung cấp thanh toán của bạn.
Bước 5. Nếu vẫn cần chặn — hãy chặn dải mạng con, không phải quốc gia
Một sự dày lên ổn định từ một mạng duy nhất, kéo dài nhiều ngày và đi kèm những yêu cầu cùng kiểu, chính là một người thực hiện đang đi theo danh sách. Trường hợp đó được chặn có trọng điểm và có thời hạn:
sudo ufw deny from 198.51.100.0/22 to any
sudo ufw status numbered
Bằng lệnh thứ hai, hãy ghi nhớ số thứ tự của quy tắc: về sau phải gỡ lệnh chặn đúng qua số đó, sudo ufw delete <số>. Hãy tự thỏa thuận với mình một thời hạn — ví dụ một tháng — và ghi việc gỡ bỏ vào lịch. Những quy tắc đặt ra «vĩnh viễn» sau một năm sẽ biến thành một danh sách mà không ai dám đụng vào, bởi không ai còn nhớ vì sao những địa chỉ đó lọt vào đấy.
Chặn dải mạng con nào thì có thể tra ra từ địa chỉ ở bước đầu tiên: whois 198.51.100.17 | grep -iE 'route|cidr|netname'.
Điều gì thay đổi sau năm bước này
Các trình quét bị cắt theo ý định chứ không theo xuất xứ, và bị bắt ngay từ yêu cầu đầu tiên. Các trình thu thập đụng phải giới hạn nhịp độ. Robot tìm kiếm và thông báo thanh toán vẫn đi qua được. Lệnh chặn rộng duy nhất còn lại là có trọng điểm, với thời hạn đã biết và lý do rõ ràng.
Bản đồ thì vẫn ở đó, nhưng vai trò của nó thay đổi: nó cần không phải để đóng cửa các quốc gia, mà để nhận ra chính sự dày lên đó và so sánh với tuần trước. Muốn vậy cần có lịch sử chứ không phải ảnh chụp của ngày hiện tại. Một bản đồ như thế trông ra sao bên cạnh nhật ký chặn và danh sách cổng mở, các trang giới thiệu bên dưới sẽ cho thấy.