Fail2Ban
Fail2Ban 是一個入侵檢測系統框架,它可以保護電腦伺服器免受蠻力攻擊。以Python程式設計語言編寫,並能夠在類Unix系統上運行,這些系統具有本地安裝的封包控制系統或防火牆的介面,例如Iptables或TCP Wrapper。
Install Fail2Ban on Debian
Installation
Download: https://www.fail2ban.org/wiki/index.php/Downloads
# Debian 7.x
tar xzf 0.9.2.tar.gz
cd fail2ban-0.9.2/
python setup.py install
Verify
fail2ban-client -h
Configuration for Asterisk
On Asterisk)
/etc/asterisk/logger.conf:
...
[logfiles]
...
fail2ban => notice,warning,security
Restart the logger on Asterisk
asterisk -rx "logger reload"
asterisk -rx "logger show channels"
On Fail2Ban)
/etc/fail2ban/jail.d/asterisk.conf
[asterisk]
enabled = true
logpath = /var/log/asterisk/fail2ban
maxretry = 5
bantime = 259200
Configuration for SSH
/etc/fail2ban/jail.d/sshd.conf
[sshd]
enabled = true
bantime = 7200
findtime = 900
maxretry = 4
Auto startup
cd fail2ban-0.9.2/
cp files/debian-initd /etc/init.d/fail2ban
chmod 0755 /etc/init.d/fail2ban
update-rc.d fail2ban defaults
Service start
service fail2ban start
Setup Logrotate
/etc/logrotate.d/fail2ban
/var/log/fail2ban.log {
missingok
notifempty
size 30k
create 0600 root root
postrotate
/usr/bin/fail2ban-client set logtarget /var/log/fail2ban.log 1>/dev/null || true
#/usr/bin/fail2ban-client reload 2> /dev/null || true
endscript
}
FAQ
Q:以下 Call Log 無法被偵測到
Call from '' (195.154.134.116:5071) to extension '8011441295298642' rejected because extension not found in context 'public'.
Ans:設定 Asterisk 的 allowguest=no
編輯 sip.conf
allowguest=no
Apply the changes
#> asterisk -rx "sip reload"
#> asterisk -rx "sip show settings" | grep -i "Allow unknown access"
Allow unknown access: No
Learning Fail2Ban
Fail2ban 是一套以 Python 語言所撰寫的 GPLv2 授權軟體,藉由分析系統紀錄檔,並透過設定過濾條件 (filter) 及動作 (action),當符合我們所設定的過濾條件時,將觸發相對動作來達到自動化反應的效果 (如封鎖來源 IP、寄信通知管理者、查詢來源 IP 資訊等)。因其架構相當彈性,我們可以針對自己的需求,設計不同的過濾條件與動作來達到伺服器防護的功能,或是及時的反應某些異常資訊。常見應用有:
- 阻擋 SSH、FTP 多次嘗試錯誤連線;
- 阻擋特定的瀏覽器或網路爬蟲;
- 提供管理者了解異常伺服器服務要求 (如 apache、bind、postfix、vsftpd、proftpd…)。
常見的像是 SSH 服務,當使用者嘗試輸入帳號密碼進行登入時,如發生驗證錯誤,系統將紀錄事件於記錄檔中。藉由即時的分析系統紀錄檔,我們可以過濾出一些有用的資訊,再加以判斷此類事件是否對伺服器服務有害。
GitHub: https://github.com/fail2ban/fail2ban
Tutorials
- Configure fail2ban to use route instead of iptables to block connections
- How to Create a Simple IP Blocker Script Using iptables and Fail2Ban
- Fail2Ban Prometheus Exporter
Fail2Ban FAQ
Q:服務啟動後出現錯誤
WARNING Determined IP using DNS Lookup:
Ans: 編輯 /etc/fail2ban/jail.conf
usedns = no
Q:[v0.10.0] 啟動後出現錯誤
iptables v1.4.14: unknown option "-w"
Ans:如果你的 iptables 版本不是 v1.4.20 以上,可能發生啟動錯誤,解決方式如下:
新增 /etc/fail2ban/action.d/iptables-common.local
[Init]
lockingopt =
Q:[Asterisk] 以下 Call Log 無法被偵測到
Call from '' (195.154.134.116:5071) to extension '8011441295298642' rejected because extension not found in context 'public'.
Ans:設定 Asterisk 的 allowguest=no
編輯 sip.conf
allowguest=no
套用新設定
#> asterisk -rx "sip reload"
#> asterisk -rx "sip show settings" | grep -i "Allow unknown access"
Allow unknown access: No
Q:[Asterisk] 如何驗證一條新規則
Ans: 對於特定的 log 內容,要增加一條新規則,該如何驗證是否有效。
需要過濾的 log 內容:
[2015-01-28 05:40:16] NOTICE[-1] Ext. 9015448702956577: Incoming SIP connection from unknown peer failed for 31.3.244.234 - Unknown connection from peer
在 /etc/fail2ban/filter.d/asterisk.conf 增加一條新規則
NOTICE.* .*: Incoming SIP connection from unknown peer failed for <HOST> - Unknown connection from peer
要驗證此規則是否有效,可以使用以下指令
fail2ban-regex /var/log/asterisk/fail2ban "NOTICE.* .*: Incoming SIP connection from unknown peer failed for <HOST> - Unknown connection from peer"
Tips: fail2ban-regex <path/to/log> <failregex or /etc/fail2ban/filter.s/XXX.conf>
Q:為何沒有 /var/log/fail2ban.log
Ans: 檢查 /etc/fail2ban/fail2ban.conf
#logtarget = SYSLOG
logtarget = /var/log/fail2ban.log
重啟 fail2ban 服務
Q:[Asterisk] 在 Elastix/CentOS 5.3 始終無法 ban IP
使用 fail2ban-client 檢查,明明 log 內有異常連線,但卻無法 ban IP
# fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: asterisk-iptables
# fail2ban-client status asterisk-iptables
|- filter
| |- File list: /var/log/asterisk/fail2ban
| |- Currently failed: 0
| `- Total failed: 0
`- action
|- Currently banned: 0
| `- IP list:
`- Total banned: 0
解決方法:
編輯 /etc/asterisk/logger.conf
;syslog keyword : This special keyword logs to syslog facility
;將下行註解拿掉
syslog.local0 => notice,warning,error
Reload Asterisk
Q:如何將 IP 從阻擋清單移除
# iptables -D fail2ban-ASTERISK -s 123.123.123.123 -j DROP
或
# iptables -L fail2ban-ASTERISK -nv --line-number
Chain fail2ban-ASTERISK (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * * 134.213.134.172 0.0.0.0/0
2 0 0 DROP all -- * * 46.105.127.222 0.0.0.0/0
3 0 0 DROP all -- * * 116.255.152.101 0.0.0.0/0
4 1364 363K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
# iptables -D fail2ban-ASTERISK 2 ;刪除第 2 規則
Q:[Asterisk] 如何阻擋不會紀錄來源 IP 的 DDoS 攻擊 Received incoming SIP connection
CLI Log:
Received incoming SIP connection from unknown peer to 003333002972597886748"
以上訊息只有在 sip_general.conf 的 allowguest=yes (by default),才會出現。
此篇也適合解決 Sending fake auth rejection for device 100<sip:100@123.123.123.123> ,這類的攻擊手法。
方法是先 註解 allowguest=no,然後完成下面的步驟。
注意:比較安全的做法應該是將 allowguest=no,然後在 Asterisk 11 以後版本,Log 就可以紀錄到惡意的來源 IP,然後就可以用 Fail2ban 來將其阻擋。
Ans: 編輯 /etc/asterisk/extensions.conf
[from-sip-external]
; 註解原有內容,加上以下內容
exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN})
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})})
exten => _.,n,Set(foo=${SIPCHANINFO(recvip)})
exten => _.,n,Log(NOTICE,Incoming SIP connection from unknown peer failed for ${foo} - Unknown connection from peer)
exten => _.,n,Hangup
exten => h,1,Hangup
exten => i,1,Hangup
exten => t,1,Hangup
編輯 /etc/fail2ban/filter.d/asterisk.conf
...
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Wrong password
...
...
NOTICE.* .*: Incoming SIP connection from unknown peer failed for <HOST> - Unknown connection from peer
Q:[Asterisk] 如何阻擋 Sending fake auth rejection
在 Asterisk 1.11+)
Failed to authenticate device 1005<sip:1005@123.123.123.123>;tag=2071f8ca
在 Asterisk 1.8)
Sending fake auth rejection for device 100<sip:100@123.123.123.123>;tag=99fdd5d7
Ans:不同 Asterisk 版本的解決方法
Asterisk 11)
此版新增一個 Security Log Level 的功能,透過啟用這個,可以記錄攻擊者的來源 IP,然後再透過 fail2ban 去阻擋。
編輯 /etc/fail2ban/filter.d/asterisk.conf
# 加上 SECURITY 那行
failregex = Registration from '.*' failed for '<HOST>:.*' - Wrong password
...
...
SECURITY.* .*: SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d+",SessionID="0x[\da-f]+",LocalAddress="IPV[46]/(UD|TC)P/[\da-fA-F:.]+/\d+",RemoteAddress="IPV[46]/(UD|TC)P/<HOST>/\d+"(,Challenge="\w+",ReceivedChallenge="\w+")?(,ReceivedHash="[\da-f]+")?$
Asterisk 1.8/1.6)
舊版的 Asterisk 要阻擋這類行為,只能修改原始檔 channels/chan_sip.c,使系統可以記錄攻擊者的來源 IP,修改後必須重新編譯 Asterisk 才能被套用,再設定 fail2abn 去阻擋。
Fail2ban Setup
內建白名單
方法一:修改設定
/etc/fail2an/jail.conf
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
ignoreip = 127.0.0.1/8 ::1 192.168.9.0/24 192.168.31.0/24
方法二:指令模式
fail2ban-client
# set <JAIL> addignoreip <IP>
# set <JAIL> delignoreip <IP>
fail2ban-client set sshd addignoreip 123.123.123.123
fail2ban-client set sshd delignoreip 123.123.123.123
驗證結果
fail2ban-client get <JAIL> ignoreip
fail2ban-client get asterisk ignoreip
fail2ban-client get sshd ignoreip
黑名單功能客製
使用方法:
- 新增要封鎖的 IP:
fail2ban-client set blacklist banip xxx.xxx.xxx.xxx - 解除已封鎖的 IP:
fail2ban-client set blacklist unbanip xxx.xxx.xxx.xxx - 檢視已封鎖 IP:
fail2ban-client status blacklist
設定步驟:
/etc/fail2ban/filter.d/blacklist.conf :
# /etc/fail2ban/filter.d/blacklist.conf
# Fail2Ban Blacklist for Repeat Offenders (filter.d)
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
# The name of the jail that this filter is used for. In jail.conf, name the
# jail using this filter 'blacklist', or change this line!
_jailname = blacklist
failregex =
ignoreregex =
/etc/fail2ban/action.d/blacklist.conf :
# /etc/fail2ban/action.d/blacklist.conf
# Fail2Ban Blacklist for Repeat Offenders (action.d)
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = iptables -N f2b-<name>
iptables -A f2b-<name> -j RETURN
iptables -I <chain> -j f2b-<name>
# Sort and Check for Duplicate IPs in our text file and Remove Them
sort -u /etc/fail2ban/ip.blacklist -o /etc/fail2ban/ip.blacklist
# Persistent banning of IPs reading from our ip.blacklist text file
# and adding them to IPTables on our jail startup command
cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I f2b-<name> 1 -s $IP -j DROP; done
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = iptables -D <chain> -j f2b-<name>
iptables -F f2b-<name>
iptables -X f2b-<name>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = iptables -n -L <chain> | grep -q 'f2b-<name>[ \t]'
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = iptables -I f2b-<name> 1 -s <ip> -j DROP
# Add the new IP ban to our ip.blacklist file
echo '<ip>' >> /etc/fail2ban/ip.blacklist
# I don't want reporting on any badboys service
# curl http://www.badips.com/add/badbots/<ip>/
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = iptables -D f2b-<name> -s <ip> -j DROP
# Remove IP from our ip.blacklist file
sed -i -e '/<ip>/d' /etc/fail2ban/ip.blacklist
[Init]
# Chain to insert the f2b-<name> jump rule into
chain = INPUT
/etc/fail2ban/jail.d/blacklist.conf :
- bantime 與 findtime 可以依需要做調整,單位:秒
# Usage:
# Add a bad IP - fail2ban-client set blacklist banip xxx.xxx.xxx.xxx
# Remove an IP - fail2ban-client set blacklist unbanip xxx.xxx.xxx.xxx
[blacklist]
enabled = true
banaction = blacklist
bantime = 2592000 ; 1 month
findtime = 2592000 ; 1 month
DROP vs REJECT
參數語法:
- DROP:
-j DROP - REJECT:
-j REJECT --reject-with icmp-port-unreachable
- Blacklist / 惡意 IP — 不要讓對方知道這個 IP 有在運作,浪費攻擊者的 timeout 時間
- SSH / 敏感服務的暴力攻擊來源 — 讓攻擊者摸不著到底主機在不在
- 防火牆外網 — 降低 footprint,不暴露主機存在
- 大量攻擊 (DDoS) — DROP 比 REJECT 省資源(不用產生 ICMP 封包)
- 內部服務、正常使用者 — 快速讓 client 知道此路不通,避免卡在 timeout
- 你希望 client 端有良好的 UX — 例如封鎖特定 port 但對方應立即知道被擋而不是等到 timeout
- Debug — 區分是「防火牆擋了」還是「服務沒開」
- 合法但未授權的流量 — 例如只允許內網連的服務,外部 IP 連過來給 REJECT 而非 DROP
- icmp-port-unreachable(預設值)— 最常見,告訴對方「這個 port 沒在聽」
- icmp-host-unreachable — 告訴對方「這台主機不存在」
- icmp-net-unreachable — 告訴對方「這個網段不存在」
- tcp-reset — 直接發 TCP RST,對 TCP 連線來說就像远端關閉連線,比 ICMP 更乾淨
fail2ban command
常用指令表
| Cmd | Description |
|
service fail2ban restart systemctl restart fail2ban |
restart fail2ban service (after edit configuration) |
| fail2ban-client reload | restart fail2ban client |
| fail2ban-client status | get list activated jail |
| fail2ban-client status <JAIL> example: fail2ban-client status wplogin example: fail2ban-client status sshd |
get <JAIL> status (the number of unsuccessful attempts and the list of banned IPs) |
| fail2ban-regex /var/lib/docker/containers/<CONTAINERID>/<CONTAINERID>-json.log /etc/fail2ban/filter.d/wplogin.conf | test regex wplogin |
| fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf | test regex sshd |
| fail2ban-regex "line" "failregex" | test regex |
| fail2ban-client set <JAIL-NAME> unbanip <IP-ADDRESS> | manually unban IP |
| fail2ban-client set <JAIL-NAME> banip <IP-ADDRESS> | manually Ban IP |
| tail -f /var/log/fail2ban.log | view fail2ban logs |
| iptables -L –line-numbers | list IP blocked with line numbers |
| iptables -D <Jail-Name> -s <IP-ADDRESS> -j DROP Example: Jail-Name =f2b-wplogin Jail-Name =f2b-sshd |
Unban IP |
| fail2ban-server -b | start fail2ban server |
| docker inspect –format='{{.LogPath}}' $INSTANCE_ID | return instance log file path |
| fail2ban-client get <JAIL-NAME> ignoreip |
Test ignoreip for JAIL |
Check the version
fail2ban-client version
Check the Help
fail2ban-client -h