2016年5月22日 星期日

來自CN的你

小弟部署的shadowsocks版本通常為shadowsocks-libev,通常安裝後會在/root目錄設置
一個名為ss-json,製造約干json的描述文件放到裡面,每一個不同端口和密碼,以腳本
一次啟動它們,並在 /etc/rc.local設為開機啟動,並會把ss-libev的日誌寫到/root/ss.log,
方便查找問題。

我有十個VPS以上,有時用戶報告服務器連不上,便會檢查ss.log看看是否服務器被牆,
還是用戶黏貼密碼,使行末多了\r (*nix行末是\n , windows是\n\r),這些看不到的字符,
服務器是看到的,便認為密碼不對,拒絕轉發流量,或是看看是否多天沒人使用,這
就要另找用戶測試是否被牆,通常三數個用戶不同地方連不上,IP是被牆了。

檢查的時候總會發現一些不明來歷的IP,通常來自CN,不斷嘗試連接服務器,日誌會
記錄下來,型式是這樣

2016-05-22 14:41:46 ERROR: invalid password or cipher
2016-05-22 14:41:46 ERROR: failed to handshake with 39.82.187.54

簡單執行 grep -B1 '39.82.187.54' ss.log 便能看到,於多枚VPS都有這樣的情況,不管有
沒有招收用戶,只要搭建起來這些不速之客便會探訪,這樣我寫了一個小腳本,統計
這些IP的錯誤連接數
這是其中一個服務器的數字,應該算是暴力破解了,到另一個服務器統計IP的錯誤連接
數字,並把IP導入文件,如圖

這枚服務器不算多,最高是200+ CN的IP,錯誤連接數達到10000+,直到我重灌系統之
前,於是找出這些IP來源,使用一個很久前在DDWRT寫的小腳本 ,執行後如是
這就不禁令人懷疑,這些IP是否來自GFW?很多都來自相同的IP段,而且似乎是自動
程式,那個嘗試連線,達到3000+錯誤的IP已經連續攻擊了3天,除了晚上會離開,
差不多是以7-11的時間不間斷攻擊。其實shadowsocks各版本開發者都已知這個情況,
並分別提出解決方案

以shadowsocks-libev解決方法是一次性認證,在運行時加入 -A 參數,開啟了OTA,沒通
過認證的拒絕連接,Python版的shadowsocks給出autoban.py ,封鎖這些惡意IP。

我是libev用戶,解決方法大約3個

1) 開啟OTA,執行時這樣

    nohup ss-server -A -u -v -c /path/to/whatever.json &>> /path/to/ss.log &

2) 足夠強度的密碼,無視這些惡意IP攻擊,反正破解不了
3) 寫一個類似autoban.py的腳本,達到某個數目的錯誤,便自動把該IP封鎖。

這三個方式以第一個官方給出的解決辦法最佳,直接拒絕連接,一了百了,杜絕這些惡意
IP的攻擊,也不知它們是否探針還是甚麼。不過我有超過100+用戶使用由我提供的免費ss
服務,不知道他們用的是甚麼客戶端,而目前的ss客戶端並不是每一個都支持,ios的客戶
端好像暫時(這篇文章發佈前)只有shadowrocket支援,總不可能每個人都問用甚麼客
戶端,個別開啟OTA,這也不能杜絕沒有開啟OTA的端口受到攻擊。

第二個方法是我目前使用的方式,不予理會這些惡意IP,在大部分客戶端沒有支援OTA之
前,會一直使用下去(非常無奈的辦法)。

第三個是仿效autoban.py ,寫一個簡單的bash腳本,放到cron裡,定時監測由ss-libev '-v'
參數產生的日誌文件,達到某一數目便調用系統iptables把該IP banned掉,到某一時間內
便給它們『出獄』,這樣可減緩攻擊的速度,反正閒著無事,寫了連測試也是花很少時間
,便寫了這個名為badip.sh放到cron裡實驗。

這個以封鎖為主的方式不能解決2個情況:『誤傷填錯密碼的用戶』和『分配到被封鎖IP
的用戶』,如果不能使用第一個和第二個解決辦法(不能無視被攻擊而不採取行動),那可
在vps以root下載我的腳本

wget --no-check-certificate -O badip.sh \

然後執行crontab -e ,例如每15分鐘檢查日誌一次,加入

*/15 * * * * /path/to/badip.sh

我測試時是這樣

*/15 * * * * /root/bin/badip.sh

如果改為20分鐘便這樣

*/20 * * * * /path/to/badip.sh

腳本預設錯誤疊加50次便封鎖該IP,如果不適合你的要求,請在腳本找到

if (ip[x] > 50)

把數字改為你覺得合理的,定50是因為考慮輸入錯誤密碼的用戶,如果不介意誤傷,可
設少些。另這腳本主要靠ss產生的日誌作為依據,我是在家目錄裏,如果文件不是在那
目錄,在腳本找到

logfile="$HOME/ss.log" #change if it is not your ss.log directory

改為你的儲存的目錄和正確的文件名,例如

logfile="/etc/shadowsocks-libev/ss.log" #change if it is not your ss.log directory

執行的ss-server命令必須有'-v'參數,例如

nohup ss-server -v -c /path/to/whatever.json &>> whatever &

我們再利用crontab -e 命令,把這些惡意IP一段時間便放監,同時清空日誌,重新計算,

0 3 * * * /sbin/iptables -F
0 3 * * * : > /path/to/ss.log

這就在凌晨3:00清空iptables列表和日誌,這可避免封鎖列表越來越長,令系統效率
減低。如果同時安裝了fail2ban程序,也會把由fail2ban投入『監獄』的IP釋放,不想這
樣,請自行參考iptables手冊設置cron job分別處理,這裡不囉嗦了。

這個腳本手動執行會是這樣
下圖是執行的結果,大於50錯誤次數的IP封鎖了,再運行它會檢查是否在封鎖列表中,
如果放在cron沒有提示顯示的
目前為止我是採取第二個方式,直到大部份ss客戶端支援shadowsocks-libev的OTA為止。
第三個方法只是給不能採用1和2方式的朋友多一個選擇,直到所有/大部份客戶端支
援shadowsocks-libev的OTA臨時解決方案。

:)

6 則留言:

  1. badip.sh要給執行權限, chmod +x badip.sh ,忘了

    回覆刪除
  2. 另外使用內建命令 : 清空ss.log好像不成功,請改為 cat /dev/null > /path/to/ss.log 試試

    回覆刪除
    回覆
    1. 在 cron 裡不成,命令列執行 : > /path/to/ss.log 沒有問題的

      刪除
    2. 你好博主,我从推上关注到你的博客,感谢你的分享,身在墙内,最近干扰加剧,我的SS已失效,能否分享下你的SS?想验证下Libev OTA能否有效对抗gfw的大流量监测干扰,保证不滥用,我的email:身分ID加上ITEKE.TK邮箱后缀。祝好!

      刪除
  3. 你好博主,我从推上关注到你的博客,感谢你的分享,身在墙内,最近干扰加剧,我的SS已失效,能否分享下你的SS?想验证下Libev OTA能否有效对抗gfw的大流量监测干扰,保证不滥用,我的email:身分ID加上ITEKE.TK邮箱后缀。祝好!

    回覆刪除