knowledge/docs/freeswitch/fail2ban.md

240 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 【安全】使用fail2ban自动拦截向FreeSWITCH发起恶意注册的IP地址
> wandoubaba / 2023-07-10
通常情况了如果我们的FreeSWITCH应用是面向互联网开放的话就要对互联网开放SIP端口那么就避免不了来自一些“不友善”的IP发来的尝试SIP注册的请求我们往往会在FreeSWITCH的日志中看到类似这下面这样的信息
```log
2023-07-10 19:12:35.902557 98.23% [WARNING] sofia_reg.c:3211 Can't find user [8001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="8001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
2023-07-10 19:13:38.522558 98.27% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
2023-07-10 19:14:42.342569 98.10% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
```
> 自从1.10.7开始FreeSWITCH的日志中都会在时间戳的后面加上空闲CPU百分比这里的FreeSWITCH版本是1.10.8。
从上面这些内容我们不难看出,有个主机一直从`194.61.28.102`这个IP在向我们的FreeSWITCH发直SIP注册请求想要注册分机号`8001`或者`80018001`去网上查询一下可以看到这个IP的地理位置位于美国的加里福尼亚洲笔者可以肯定两点
1. 我们的业务没有美国的客户。
2. 我们的SIP账号中没有8001或者80018001这样的账号。
因此我们可以非常肯定,这种注册行为完全是我们所不欢迎的。
通常情况下我们可以通过将这个IP添加到系统防火墙的黑名单来拒绝来自这种恶意IP的请求但是完全靠这种手动操作是治标不治本的因为过不了多久就会有来自其他IP的恶意注册请求出现靠手动处理完全是禁不绝的。
那么,能不能有一种自动化的工具能够代替人工来做这种自动捕捉和禁止的动作呢?
答案就是:**fail2ban**
## fail2ban简介
fail2ban是一款入侵防御软件通过监控指定日志文件中的文本行可以自动捕获到尝试操作失败的事件进而得到入侵来源地址并自动将地址加入系统防火墙黑名单中从而实现对系统自动入侵防御的目的。
## 用fail2ban防止FreeSWITCH被恶意注册
本文假设系统中已经正确安装、配置并运行了FreeSWITCH。
### 针对Debian上的FreeSWITCH1.10.8
版本信息
|软件/组件|版本|
|---|---|
|操作系统|Debian10.2.1-6(bullseye)|
|FreeSWITCH|1.10.8|
|fail2ban|0.11.2|
#### 安装fail2ban
```sh
sudo apt-get install fail2ban
```
#### 配置fail2ban
fail2ban默认已经内置了针对多种常见服务的入侵防御配置但是默认都不是开启的状态默认情况下fail2ban只是开启了针对`sshd`服务的防御下面我们就一步一步开始打开针对FreeSWITCH的恶意注册防御。
##### 目录结构
|目录或文件|作用|说明|
|---|---|---|
|/etc/fail2ban/fail2ban.conf|fail2ban的主配置文件|一般情况下不需要修改这里|
|/etc/fail2ban/jail.conf|fail2ban的默认拦截配置文件|官方建议不要修改这个文件|
|/etc/fail2ban/filter.d/|fail2ban的默认捕获规则目录|这里包含各种服务的规则文件,如果需要修改,建议在这里基于.conf文件创建.local文件|
|/etc/fail2ban/jail.d/|fail2ban的具体拦截规则目录|在这里创建.local文件来配置拦截规则如freeswitch.local|
|/etc/fail2ban/action.d/|fail2ban执行拦截的执行动作配置|一般情况下不需要修改这里的文件|
##### 创建拦截规则
在`/etc/fail2ban/jail.d/`目录下创建名为`freeswitch.local`的文件:
```sh
touch /etc/fail2ban/jail.d/freeswitch.local
```
编辑`/etc/fail2ban/jail.d/freeswitch.local`文件
```ini
[freeswitch]
enabled = true
filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']
banaction = ufw
maxretry = 5
findtime = 3600
bantime = 259200
ignoreip = 127.0.0.1/32
port = 5060,5061
logpath = /usr/local/freeswitch/log/freeswitch.log
```
规则说明:
- `enabled = true` 表示开启这个规则。
- `filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']` 是针对FS版本1.10.7之后版本的日志文件中在每行时间戳后面会加下空间CPU百分比加上这行就可以正常识别到事件如果不加上这行就无法正确识别到事件参考<https://github.com/fail2ban/fail2ban/issues/3143>)。
- `banaction = ufw` 表示拦截时使用ufw命令如果不加这句则默认在拦截时会使用iptables命令如果系统中使用了ufw来管理防火墙建议加上这句否则有可能拦截无效
- `maxretry = 5` 表示相同事件连续发生的次数这里设置为5表示连续尝试5次就被视为恶意行为
- `findtime = 3600` 表示监控的周期配合maxretry使用这里的配置表示“3600秒内发生5次尝试即被视为恶意行为”。
- `bantime = 259200` 表示拦截时间这里设置为259200秒就是72小时也就是3天
- `ignoreip = 127.0.0.1/32` 表示不拦截的IP地址。
- `port = 5060,5061` 是SIP服务的端口号包括TLS
- `logpath = /usr/local/freeswitch/log/freeswitch.log` 是FreeSWITCH是实时日志文件的绝对路径。
上面这个拦截规则实现的效果就是在1小时之内如果来自同一个IP的SIP注册失败次数达到5次就认为这个IP发起了恶意注册请求3天内自动拒绝来自这个IP的所有请求。
##### 检查事件匹配规则
```sh
cat /etc/fail2ban/filter.d/freeswitch.conf
```
可以看到类似下面的内容
```ini
# 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.
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = freeswitch
# Parameter "mode": normal, ddos or extra (default, combines all)
# Usage example (for jail.local):
# [freeswitch]
# mode = normal
# # or with rewrite filter parameters of jail:
# [freeswitch-ddos]
# filter = freeswitch[mode=ddos]
#
mode = extra
# Prefix contains common prefix line (server, daemon, etc.) and 2 datetimes if used systemd backend
_pref_line = ^%(__prefix_line)s(?:(?:\d+-)?\d+-\d+ \d+:\d+:\d+\.\d+)?
prefregex = ^%(_pref_line)s \[WARN(?:ING)?\](?: \[SOFIA\])? \[?sofia_reg\.c:\d+\]? <F-CONTENT>.+</F-CONTENT>$
cmnfailre = ^Can't find user \[[^@]+@[^\]]+\] from <HOST>$
mdre-normal = %(cmnfailre)s
^SIP auth failure \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip <HOST>$
mdre-ddos = ^SIP auth (?:failure|challenge) \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip <HOST>$
mdre-extra = %(cmnfailre)s
<mdre-ddos>
failregex = <mdre-<mode>>
ignoreregex =
datepattern = ^(?:%%Y-)?%%m-%%d[ T]%%H:%%M:%%S(?:\.%%f)?
{^LN-BEG}
# Author: Rupa SChomaker, soapee01, Daniel Black, Sergey Brester aka sebres
# 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\.$
```
这是fail2ban官方内容的事件匹配规则针对本文档所使用各组件版本这里的规则不需要修改。
##### fail2ban命令
```sh
## 启动系统服务
systemctl start fail2ban
## 重启系统服务(修改配置生效)
systemctl restart fail2ban
## 停止系统服务
systemctl stop fail2ban
## 用fail2ban-client命令启动服务
fail2ban-client start
## 用fail2ban-client命令重载全部配置修改配置生效
fail2ban-client reload
## 用fail2ban-client命令重载指定监禁配置把<JAIL>换成具体的名称)
fail2ban-client reload <JAIL>
## 用fail2ban-client命令停止服务
fail2ban-client stop
## 查看当前保护状态
fail2ban-client status
## 查看当前保护的具体服务状态(把<JAIL>换成具体的名称)
fail2ban-client status <JAIL>
## 查看版本
fail2ban-client version
## 手动监禁一个IP把<JAIL>换成具体名称,把<xx.xx.xx.xx>换成具体IP
fail2ban-client set <JAIL> banip <xx.xx.xx.xx>
## 手动将一个IP解除监禁把<JAIL>换成具体名称,把<xx.xx.xx.xx>换成具体IP
fail2ban-client set <JAIL> unbanip <xx.xx.xx.xx>
```
##### fail2ban日志
位置 `/var/log/fail2ban.log`
##### 查看拦截是否生效
在本文的示例环境中,使用了`ufw`做为系统防火墙管理工具所以我们使用ufw命令可以看到拦截是否生效
```sh
ufw status
```
结果可能类似下面:
```sh
Status: active
To Action From
-- ------ ----
Anywhere REJECT 194.61.28.102
Anywhere REJECT 193.107.216.55
Anywhere REJECT 193.107.216.29
Anywhere REJECT 193.107.216.143
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
....
```
上面被REJECT的这几个IP就是被fail2ban监禁的IP。
关于fail2ban的更多玩法可以到fail2ban的官方github上去了解<https://github.com/fail2ban/fail2ban>