# 使用`Fail2Ban`防止sip攻擊`FreeSWITCH` `FreeSWITCH`在公網運行容易遭受sip攻擊,解決的辦法有很多種,而`Fail2Ban`安裝配置以及調試比較簡單,不失為一種好的選擇。 `Fail2Ban`版本很多,配置方式略有差別。 本次測試是基於`Fail2Ban 0.9.6`版本,其他相關信息如下: - Debian9 - FreeSWITCH 1.10.3,`base_dir`是`/usr/local/freeswitch` ## 安裝`Fail2Ban` ```shell cd /usr/src; git clone https://github.com/fail2ban/fail2ban.git -b 0.9.6 cd /usr/src/fail2ban; python3 setup.py install #配置成服務 cp files/debian-initd /etc/init.d/fail2ban
#centos
cp files/redhat-initd /etc/init.d/fail2ban
https://github.com/fail2ban/fail2ban/blob/0.11/files/redhat-initd update-rc.d fail2ban defaults service fail2ban start ``` ## 配置`iptables` ```shell iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT iptables -A INPUT -p tcp --dport 5066 -j ACCEPT iptables -A INPUT -p tcp --dport 7443 -j ACCEPT iptables -A INPUT -p tcp --dport 5060:5061 -j ACCEPT iptables -A INPUT -p udp --dport 5060 -j ACCEPT iptables -A INPUT -p tcp --dport 5080 -j ACCEPT iptables -A INPUT -p udp --dport 5080 -j ACCEPT iptables -A INPUT -p udp --dport 16384:32768 -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT ``` ## 配置 `FreeSWITCH` 1. sip_profiles/internal.xml ``` <param name="log-auth-failures" value="true"/> ``` 2. autoload_configs/switch.conf.xml 要修改一個配置項目 ``` <param name="threaded-system-exec" value="true"/> ``` ## 配置 fail2ban ### 配置 freeswitch jail 找到 `/etc/fail2ban/jail.conf` 的 freeswitch 段,修改成下面這樣: ``` [freeswitch] enabled = true port = 5060,5061,5080 action = iptables-allports[name=freeswitch, protocol=all] logpath = /usr/local/freeswitch/log/freeswitch.log filter = freeswitch maxretry = 5 bantime = -1 findtime = 3600 ignoreip = 127.0.0.1/8 192.168.0.0/16 10.0.0.0/8 172.16.0.0/16 ``` 其中: * port = 5060,5061,5080 # sip profile 的端口 * action = iptables-allports[name=freeswitch, protocol=all] # 這里不用改動 * logpath = /usr/local/freeswitch/log/freeswitch.log # freeswitch.log的全路徑 * filter = freeswitch #這里不用改動 * maxretry = 5 # 嘗試次數 * bantime = -1 # -1 永久 ban(禁止) * findtime = 3600 # 發現的時間,這幾個參數合起來的意思就是,如果 1 小時內檢查到 哪個 IP 地址,做了 5 次嘗試,那么永久禁止他 * ignoreip = 127.0.0.1/8 192.168.0.0/16 10.0.0.0/8 172.16.0.0/16 # ip 白名單 ### 配置 freeswitch filter 修改`/etc/fail2ban/filter.d/freeswitch.conf`,改成下面這樣: ``` # Fail2Ban configuration file # # Enable "log-auth-failures" on each Sofia profile to monitor # <param name="log-auth-failures" value="true"/> # -- this requires a high enough loglevel on your logs to save these messages. # # In the fail2ban jail.local file for this filter set ignoreip to the internal # IP addresses on your LAN. # [Definition] #failregex = ^\.\d+ \[WARNING\] sofia_reg\.c:\d+ SIP auth (failure|challenge) \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[.*\] from ip <HOST>$ # ^\.\d+ \[WARNING\] sofia_reg\.c:\d+ Can't find user \[\d+@\d+\.\d+\.\d+\.\d+\] from <HOST>$ failregex = ^\.\d+ \[WARNING\] sofia_reg\.c:\d+ SIP auth failure \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[.*\] from ip <HOST>$ ^\.\d+ \[WARNING\] sofia_reg\.c:\d+ Can't find user \[\d+@\d+\.\d+\.\d+\.\d+\] from <HOST>$ ignoreregex = # Author: Rupa SChomaker, soapee01, Daniel Black # https://freeswitch.org/confluence/display/FREESWITCH/Fail2Ban # Thanks to Jim on mailing list of samples and guidance # # No need to match the following. Its a duplicate of the SIP auth regex. # ^\.\d+ \[DEBUG\] sofia\.c:\d+ IP <HOST> Rejected by acl "\S+"\. Falling back to Digest auth\.$ ``` 現在運行`systemctl restart fail2ban`重啟服務 再運行 `fail2ban-client status`,輸出如下: ``` Status |- Number of jail: 1 `- Jail list: freeswitch ``` 運行`fail2ban-client status freeswitch`,輸出如下: ``` Status for the jail: freeswitch |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- File list: /usr/local/freeswitch/log/freeswitch.log `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list: ``` 現在試着ban一個ip,執行這個命令: ``` fail2ban-client set freeswitch banip 113.113.113.113 ``` 然后用`fail2ban-client status freeswitch`查看 ``` Status for the jail: freeswitch |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- File list: /usr/local/freeswitch/log/freeswitch.log `- Actions |- Currently banned: 1 |- Total banned: 3 `- Banned IP list: 113.113.113.113 ``` 可以看到, `113.113.113.113` 這個地址已經被ban 執行這個命令`iptables -nvL --line-numbers` 輸出如下: ``` Chain INPUT (policy DROP 9 packets, 2952 bytes) num pkts bytes target prot opt in out source destination 1 1057 132K f2b-freeswitch all -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 3 13 808 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 6 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 7 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5066 8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:7443 9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpts:5060:5061 10 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 11 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5080 12 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:5080 13 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpts:16384:32768 14 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 6 packets, 496 bytes) num pkts bytes target prot opt in out source destination Chain f2b-freeswitch (1 references) num pkts bytes target prot opt in out source destination 1 0 0 REJECT all -- * * 113.113.113.113 0.0.0.0/0 reject-with icmp-port-unreachable 2 1057 132K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 ``` 用這個命令解除,`fail2ban-client set freeswitch unbanip 113.113.113.113` ## 把 FreeSWITCH 運行起來,運行`tail -f /var/log/fail2ban.log`進行觀察,再結合`/usr/local/freeswitch/log/freeswitch.log`的日志內容,進行調試,不斷優化。 ## fail2ban.lua 一般情況下`Fail2Ban`工作的很好,但還是有特殊的呼叫流程`Fail2Ban`抓不到。為此,筆者寫了個`fail2ban.lua`,彌補`Fail2Ban`的不足 1. 修改`lua.conf.xml`,增加下面倆個配置項目: ``` <hook event="CUSTOM" subclass="sofia::wrong_call_state" script="fail2ban.lua"/> <hook event="CUSTOM" subclass="sofia::register_failure" script="fail2ban.lua"/> ``` 下面是`fail2ban.lua`的內容(代碼比較簡單,不再解釋了): ``` function OnEvent(e) local subclass = e:getHeader("Event-Subclass") or "" if string.find(subclass, "sofia::") ~= 1 then return end local ip = e:getHeader("network_ip") or e:getHeader("network-ip") if not ip then return end local ua = e:getHeader("user-agent") or "" local to_user = e:getHeader("to-user") or "" local from_user = e:getHeader("from-user") or "" local auth_result = e:getHeader("auth-result") or "" local registration_type = e:getHeader("registration-type") or "" local s = string.format("*** %s, ip = %s, ua = %s, to = %s, from = %s, result = %s, type = %s\n", subclass, ip, ua, to_user, from_user, auth_result, registration_type) freeswitch.consoleLog("NOTICE", s) if subclass == "sofia::wrong_call_state" or subclass == "sofia::register_failure" then local cmd = "fail2ban-client set freeswitch banip " .. ip freeswitch.consoleLog("ERR", cmd .. "\n") os.execute(cmd) end end freeswitch.consoleLog("INFO", "fail2ban.lua, ===\n" .. event:serialize() .. "===\n") OnEvent(event) ``` ## 參考資料: <https://docs.fusionpbx.com/en/latest/firewall/fail2ban.html> <https://docs.fusionpbx.com/en/latest/firewall/iptables.html> <https://freeswitch.org/confluence/display/FREESWITCH/Fail2Ban>
https://blog.csdn.net/weixin_43103905/article/details/95060220
注意:
如果遇到報錯“no directory /var/run/fail2ban to contain the socket file /var/run/fail2ban/fail2ban.sock”, 請手動創建相關文件夾:
mkdir /var/run/fail2ban
#開機啟動
$ systemctl enable fail2ban
$ systemctl start fail2ban
redhat-initd