It's me ;-)

Tự động block các IP từ spam comment vào .htaccess file

Sau khi viết bài về việc blog bị spam và áp dụng 1 số biện pháp thì tình trạng bị spam có giảm nhưng cơ bản thì 1 ngày cũng bị khoảng chục cái mail notification (do bọn nó bypass được hệ thống nhận dạng spam của WordPress)

Về cơ bản thì bọn spammer đấy nó cũng có hệ thống khá ngon nghẻ để vượt qua mấy cái captcha này (quên béng mất cái link tool đó, chỉ nhớ bản free nó cho 1 phút/captcha hay sao ấy) nên chắc phải sống chung với lũ thôi 🙁

Nhưng dù sao chặn được bao nhiêu thì mình cũng cứ nên chặn. WP cũng có 1 plugin khá ngon để chặn IP của mấy thằng spam nhưng mà nó không chặn ngay từ lúc nhận được request từ web server, và bản thân mình cũng không thích cài cắm thêm plugin vào blog của mình nên quyết định viết 1 script nhỏ để tự động đọc các comments bị đánh dấu là spam sau đó lấy IP của thằng spammer đó cho blacklist để chặn (sử dụng .htaccess)

Các bước thực hiện sẽ là:

  1. Định nghĩa marker trong file .htaccess (tương tự cho nginx). Ví dụ:
    # BEGIN BlockIPs....# END BlockIPs
  2. Kết nối vào database, lấy tất cả IP của các comments bị đánh dấu là spam
  3. Lấy kết quả của bước 2, convert thành block syntax. Mình đang dùng Apache với .htaccess nên syntax sẽ đơn giản là Deny from xxx.xxx.xxx.xxx
  4. Ghi kết quả của bước 3 (1 danh sách các IPs) vào giữa marker định nghĩa ở bước 1

Có thể thấy bước 4 là có vẻ khoai nhất trong mấy bước trên vì phải mở file rồi thay đổi nội dung giữa đoạn đánh dấu # BEGIN BlockIps cho đến # END BlockIps. Thật ra thì dùng regular expression cũng đơn giản, nhưng mình chợt nhớ là WordPress nó cũng hay có trò edit file .htaccess nên chắc chắn kiểu gì nó cũng có helper function cho mấy cái trò chỉnh sửa này 😉

Và quả nhiên đúng như mình nghĩ, WordPress có hàm insert_with_markers, đúng cái mình cần luôn =))

OK, vậy mình code thôi:

<?php
require_once 'wp-admin/includes/misc.php';

$mysqli = new mysqli("donamkhanh.com", "user", "password", "database");

if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
    exit;
}

$mysqli->real_query("SELECT CONCAT('Deny from ', comment_author_IP) deny_from
FROM `wp_comments` WHERE comment_approved = 'spam'
GROUP BY comment_author_IP");
$res = $mysqli->use_result();

$lines = [];
while ($row = $res->fetch_assoc()) {
    $lines[] = sprintf('Deny from %s', $row['deny_from']);
}

insert_with_markers('.htaccess', 'BlockIPs', $lines);

Việc cuối cùng là đặt lịch cứ 12h đêm hàng ngày thì chạy cái file này để cập nhật dữ liệu 😉

0 0 * * * php /var/www/html/block-ips.php >/dev/null 2>&1

Leave a Reply

Your email address will not be published. Required fields are marked *