WP Anti Spam 小牆 1.84 From Willin Kan’s blog
小牆1.81 ~ 1.84 都是 小牆 1.8 的修改版, 不是升級版, 其實攔截方式都一樣, 只是手法有不同.
各版本的修改如下:
小牆 1.81
取消了 Trackbacks/Pingbacks 的攔劫, 並且將 spam 的基本資料存進檔頭.
小牆 1.82
修改 IP 取得方式.
小牆 1.83
IP 取得方式又改回來了, 非中文語系不能留言, 沒頭像的列入待審, 自動將 spam 加入黑名單.
小牆 1.84 (2011/10/15 最新版)
不記錄 IP, 改用 url 加入黑名單.
在看代碼之前, 我想先分享我處理 spam 的經驗:
spammer 留言後, 一定會回來檢查成果
對策: 不要保留 spam.
如果你的網頁可以留下 spam, 那它還會再來, 而且越來越多.
不僅 spam 如此, 人肉 AD 也是如此.
機器 spam 基本都是從根目錄的 wp-comments-post.php 注入
(但最近發現也有從主題 comments-ajax.php 注入)
對策: 讓他找不到地方注入.
最好能用 Ajax comments 將評論目標轉移到另個文件.
如果你用的是我的 Ajax comments, 可以將 comments-ajax.php 更名為 my-comments.php, 然後在 js 頭部的
ajax_php_url = js_url.replace(‘-ajax.js’,’-ajax.php’),
也改成
ajax_php_url = js_url.replace(‘comments-ajax.js’,’my-comments.php’),
上面的 my-comments.php 只是舉例, 你也可以改成 abc.php 或 xyz.php 反正你看得懂就行.
用了 ajax 之後, wp-comments-post.php 就沒用了, 你可刪掉它. 或是有用到 my-visitors 插件的, 可用插件所附的 wp-comments-post.php 替換它, 可記錄 spam 的一些資料.
非中文的 spam 佔了很大數量
對策: 限制語言.
Some Chinese Please 插件就是檢查評論中是否含有中文, 沒有中文就留言不了.
這裏有個問題, 使用 copy 中文留言即可行騙過關.
其實 PHP 的 $_SERVER[‘HTTP_ACCEPT_LANGUAGE’] 就可以知道瀏覽器的語系, 中文用的是 ‘zh-cn’ 或 ‘zh-tw’, 一定會有 ‘zh’.
所以 stripos($_SERVER[‘HTTP_ACCEPT_LANGUAGE’], ‘zh’) > -1 就是中文語系.
而 stripos($_SERVER[‘HTTP_ACCEPT_LANGUAGE’], ‘zh’) === false 就是非中文語系, 我們可以在頁面送出前讓評論關閉, 不用等他送出評論才判斷.
在 functions.php 用下語句可讓非中文語系評論關閉.
1
2 |
if ( stripos($_SERVER[‘HTTP_ACCEPT_LANGUAGE’], ‘zh’) === false )
add_filter( ‘comments_open’, create_function(”, “return false;”) ); // 非中文語系關閉評論 |
如果你的評論是向全世界開放的, 這方法就不適用了.
spam 的 email 多屬虛假, 所以沒頭像
對策: 沒頭像的列入待審.
這種判斷不是很準確, 但可以屏蔽大多數的人肉 spam, 如果判斷錯誤, 還可在後台讓它獲准, 不會丟失評論.
1
2 3 4 |
$f = md5( strtolower($comment[‘comment_author_email’]) );
$g = sprintf( “http://%d.gravatar.com”, (hexdec($f{0}) % 2) ) .’/avatar/’. $f .’?d=404′; $headers = @get_headers( $g ); if ( !preg_match(“|200|”, $headers[0]) ) add_filter(‘pre_comment_approved’, create_function(”, ‘return “0”;’)); |
上面就是檢查頭像的方式, 沒頭像的列入待審. (此代碼只能用於評論檢查, 不能直接放於 functions.php)
如果 spam 有頭像, 那更簡單, 直接在黑名單加上他的 email, 這輩子他就別想留言了.
同一個 spammer 會再回來
對策: 用黑名單關閉評論.
WP 內置了評論黑名單的功能, 你可以手工加入你想屏蔽的關鍵字, 系統會自動將評論標記為垃圾評論.
問題是, WP 還是准許黑名單上的人留言, 垃圾評論會一直累積. 若是遇到他們, WP 能自動關閉評論不是更好嗎?
在 comments.php 中可以加個判斷, 讓黑名單上的人無法再留言.
1
|
if ( comments_open() ) :
|
可以改成
1
|
if ( comments_open() && !wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, ”, $_SERVER[‘REMOTE_ADDR’], ”) ) :
|
這是檢查 author, email, url, IP 是否在黑名單上, 是的話只能看到 ‘評論已關閉’, 無法留言.
如果你的主題用的是 comment_form() 函數, 就要進 /wp-includes/comment-template.php 的 1550 行, 找到 if ( comments_open() ) 加上黑名單的判斷.
以後 WP 升級, 別忘了要做這步驟.
Ajax comments 的話, 可在 comments-ajax.php 下面 setcookie 之後, $comment_depth = 1 之前, 加上:
1
2 |
if (wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, ”, $_SERVER[‘REMOTE_ADDR’], ”))
err(__(‘Sorry, the comment form is closed at this time.’)); |
如此一來, 垃圾評論送出一次之後, 就不能再送出.
另外, 既然確定是 spam, 應該要自動加入黑名單.
$blacklist = get_option(‘blacklist_keys’);
update_option(‘blacklist_keys’, $comment[‘comment_author’] . “n” . $blacklist);
上面我只針對 author, 因為 spam 的 email 和 IP 不固定, 加了沒什麼意義.
用了這方法, 要經常檢查黑名單, 別人會用到的關鍵字要刪除, 否則有人會遭受池魚之殃.
後記: 我猛然想到, url 才是 spammer 最在乎的, 加入黑名單應該改用 url.
下面是將 url 加入黑名單的方法:
1
2 3 4 5 6 7 |
function add_black( $comment ) {
if (!($comment_author_url = $comment[‘comment_author_url’])) return; if ($pos = strpos($comment_author_url, ‘//’)) $comment_author_url = substr($comment_author_url, $pos + 2); if ($pos = strpos($comment_author_url, ‘/’)) $comment_author_url = substr($comment_author_url, 0, $pos); $comment_author_url = strtr($comment_author_url, array(‘www.’ => ”)); if (!wp_blacklist_check(”, ”, $comment_author_url, ”, ”, ”)) update_option(‘blacklist_keys’, $comment_author_url . “n” . get_option(‘blacklist_keys’)); } |
spammer 越來越聰明了
對策: 用小牆要自己變化.
如果你只是 copy 代碼去用, 那只是基本運用而已, 還是會被破解的.
命名應該有所變化, 人人都不同, 讓 spammer 找不到規律.
舉例說:
小牆用 name=’w’ 為評論欄, 你可改為 a, b2, c3f7, text543col, spam987…. 只要首字為英文, 其它字元符合命名規則的都可以.
大家用的欄位名都不一樣, 誰會知道該填哪一格, 自然不易被破解.
否則 spam 設定填入 ‘w’ 的話, 全部用 ‘w’ 的小牆要全倒.
要改的位置有兩個: 一個是 18 行 $2w$3 中間的 w, 一個是 24 行 $w = ‘w’; 後面的 w, 改的兩個字串要完全一樣.
使用後, 萬一所有評論都被列入垃圾, 請注意你的其它插件是否也用到了$_POST[‘comment’], 此時插件要做適當修改,
改法請參考這裏.
還有要說的是, 小牆 1.82 所獲得的 IP 如果用了代理會抓代理之前的, 雖然比較準確, 但在屏蔽 IP 時失效.
所以小牆 1.83 用回 $_SERVER[‘REMOTE_ADDR’], 這 IP 才屏蔽得到.
小牆 1.84 拿掉 IP, 因為 WordPress 已有, 另外改用 url 加入黑名單.
以下就是小牆 1.84
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/* <<小牆>> Anti-Spam v1.84 by Willin Kan. */
class anti_spam { function anti_spam() { if ( !current_user_can(‘read’) ) { add_action(‘template_redirect’, array($this, ‘w_tb’), 1); add_action(‘init’, array($this, ‘gate’), 1); add_action(‘preprocess_comment’, array($this, ‘sink’), 1); } } // 設欄位 function w_tb() { if ( is_singular() ) { // 非中文語系 if ( stripos($_SERVER[‘HTTP_ACCEPT_LANGUAGE’], ‘zh’) === false ) { add_filter( ‘comments_open’, create_function(”, “return false;”) ); // 關閉評論 } else { ob_start(create_function(‘$input’,’return preg_replace(“#textarea(.*?)name=([“‘])comment([“‘])(.+)/textarea>#”, “textarea$1name=$2w$3$4/textarea><textarea name=”comment” cols=”100%” rows=”4″ style=”display:none”></textarea>”,$input);’) ); } } } // 檢查 function gate() { $w = ‘w’; if ( !empty($_POST[$w]) && empty($_POST[‘comment’]) ) { $_POST[‘comment’] = $_POST[$w]; } else { $request = $_SERVER[‘REQUEST_URI’]; $way = isset($_POST[$w]) ? ‘手動操作’ : ‘未經評論表格’; $spamcom = isset($_POST[‘comment’]) ? $_POST[‘comment’] : ”; $_POST[‘spam_confirmed’] = “請求: “. $request. “n方式: “. $way. “n內容: “. $spamcom. “n — 記錄成功 –“; } } // 處理 function sink( $comment ) { // 不管 Trackbacks/Pingbacks if ( in_array( $comment[‘comment_type’], array(‘pingback’, ‘trackback’) ) ) return $comment; // 已確定為 spam |
如果不想屏蔽非中文語系, 可參考 1.8 的原始寫法.
國內服務器檢查頭像會比較慢, 要不要用可自己斟酌. 不用的話可以刪掉 47 ~ 56 行.
第 46, 55 行的 $this->add_black( $comment ); 是自動加入黑名單, 不用的話可注釋掉.
我知道我在網路上得罪了很多 spammer, 他們恨我入骨, 會想辦法詆毀我, 這個大家可以理解, 我就不多解釋了.