快速遴選出 NGINX log 裡想擋掉的 IP,並用 ufw 或 TCP Wrapper 擋起來
需要運用 Linux pipeline 的技巧
假設有一種 request 帶有字串『BAD STRING』,你就認定是壞蛋要擋住
那麼第一步遴選出 IP 的步驟應該是
cat /var/log/nginx/access.log | grep 'BAD STRING' | awk '{print $1}'
找出有 『BAD STRING』 的行,然後用 awk 取出第一直欄的資料 (awk 預設以空格做直欄的劃分,進一步了解 awk 可參考菜鳥教程)
這時候 data stream 應該是每個 IP 一行,總共 N 行的資料,現在第二步要把它丟到 ufw 或 TCP Wrapper
先說 ufw,假設 ufw 有運作的情況下,只要用 xargs 把 IP list 變成 ufw 的 輸入參數 即可。
正常要用 ufw 新增一個擋指定 IP 的指令是
sudo ufw deny from [Your IP]
所以,串起來就是
cat /var/log/nginx/access.log | grep 'BAD STRING' | awk '{print $1}' | xargs sudo ufw deny from
很簡單吧!
把上面這行寫到某個 bash,中間 grep ‘BAD STRING’ 把它寫成自己想判斷的 pattern,定時執行,就是個很簡單的小防禦了。
不過呢~ 注意一下,瘋狂執行 sudo ufw deny from 的代價是 CPU 會飆升到 100% 喔! 你要確定這樣沒問題才行 (例如,有的主機架構,有設計自動擴展,當你的CPU持續衝高,就會帶來機器的持續增生,所以請小心,別回頭才發現帳單爆了)
或是,也可用 TCP Wrapper (若想了解一般 TCP Wrapper 使用可參考/etc/hosts.allow 及 /etc/hosts.deny 限制 IP 連線),要把資訊寫到 hosts.allow or hosts.deny ,單行的格式是
# 協定: IP(CIDR格式) ALL : 192.168.1.1/32 sshd: 192.168.0.0/16
所以串起來就類似
cat /var/log/nginx/access.log | grep 'BAD STRING' | awk '"ALL: "{print $1}"/32"' >> /etc/hosts.deny
除了 IP 之外的 ALL : 以及 /32 ,用 awk 把字串接出來,然後 append 到 /etc/hosts.deny 內,存檔後即生效,一樣是一行完成。也一樣可以很方便丟到 bash 內,定時執行~
提醒: 這裡記得先用一些測試性質的檔案,確認一些格式,例如換行之類的,都OK後,再寫入正式檔案,較為穩妥。
Leave a Reply