centos配置Fail2Ban防止sip攻击`FreeSWITCH`


# 使用`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




免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM