在Internet上部署sip服务器的同学都知道,各种scanner不停的探测,尝试各种呼叫规则,尝试各类国际呼叫,如果没有前置防火墙,会被烦死,笔者就亲见因sip用户密码设置太简单而被恶意盗打国际长途的案例,因国际长途费用巨大,还被报警处理。今天笔者就以FreeSWITCH+CentOS7.9+firewalld+fail2ban单机在internet部署为例,实战讲解sip安全加固。
本篇内容假定您已经安装并了解firewalld和fail2ban,否则您应该先回头了解一下这两位,不然其中的配置理解有困难。另外,操作系统加固和sip用户密码加固不在本篇文章讨论范围内。
本篇文章的精髓在于对firewalld的理解,其中用到的PREROUTING_direct链已经内置在firewalld中。对永久封禁,可以不使用PREROUTING_direct,只使用PUBLIC_direct,但对于临时检测到的sip攻击,想要有效的配合fail2ban进行封禁,最好使用PREROUTING_direct,不然您会发现临时封禁可能会失效,至于为什么会这样,有赖于您对firewalld和iptables的理解。
实战之前,先在firewalld上放行sip,注意,没有用sip service方法,主要是不想用 系统的nf_conntrack_sip。
#FreeSWITCH端口设置为5060
firewall-cmd --permanent --zone=public --add-port=5060/udp
#FreeSWITCH RTP端口范围设置为16000-32000
firewall-cmd --permanent --zone=public --add-port=16000-32000/udp
一、永久封禁已知的几种sip scanner,如下:
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5060 -m string --string "VaxSIPUserAgent" --algo bm -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5060 -m string --string "sipcli" --algo bm -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5080 -m string --string "VaxSIPUserAgent" --algo bm -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5080 -m string --string "friendly-scanner" --algo bm -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5080 -m string --string "sipcli" --algo bm -j DROP
针对信令中的sip agent,直接封禁。按照这个模板,您也可以将您项目中遇到的其他sip scanner加入其中直接禁掉,请注意用到了firewalld内置的PREROUTING_direct链。
二、配置fail2ban对检测到的sip攻击ip进行临时封禁。
1、安装fail2ban后,在centos7.9+firewalld环境下,在/etc/fail2ban/jail.d/下增加freeswitch.conf,内容如下:
[freeswitch]
enabled = true
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /opt/freeswitch/log/freeswitch.log
findtime = 5m
bantime = 240h
maxretry = 5
其中的logpath路径根据您自己的实际目录进行配置。
2、此时可以查看/etc/fail2ban/jail.d/00-firewalld.conf,fail2ban使用的默认ban/unban动作是firewall-rich-rules:
[DEFAULT]
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]
启动fail2ban,用测试工具故意向FreeSWITCH发起恶意用户注册,虽然fail2ban检测到了此次scanner攻击,也针对scanner ip进行了ban操作,但实际上FreeSWITCH日志中仍显示有大量的scanner存在,意即scanner发的sip包仍到达了FreeSWITCH,封禁失败。
使用firewall-cmd查看active zone(public)的rich rules,能看到添加的rich-rules:
rich rules:
rule family="ipv4" source address="192.168.1.12" port port="5060" protocol="tcp" drop
rule family="ipv4" source address="192.168.1.12" port port="5061" protocol="tcp" drop
rule family="ipv4" source address="192.168.1.12" port port="5060" protocol="udp" drop
rule family="ipv4" source address="192.168.1.12" port port="5061" protocol="udp" drop
使用iptables查看对应的规则如下:
Chain IN_public_deny (1 references)
target prot opt source destination
DROP tcp -- 192.168.1.12 0.0.0.0/0 tcp dpt:5060 ctstate NEW,UNTRACKED
DROP tcp -- 192.168.1.12 0.0.0.0/0 tcp dpt:5061 ctstate NEW,UNTRACKED
DROP udp -- 192.168.1.12 0.0.0.0/0 udp dpt:5060 ctstate NEW,UNTRACKED
DROP udp -- 192.168.1.12 0.0.0.0/0 udp dpt:5061 ctstate NEW,UNTRACKED
iptables列出的规则已经很能说明问题了,就这默认配置,是没法ban scanner ip的,因为默认没有untrack、正在scan,不满足ctstate条件。
3、既然rich-rule模式不行,按照百度搜索的结果,很多人建议用ipset模式。于是改用firewallcmd-ipset来进行ban/unban的动作,修改/etc/fail2ban/jail.d/00-firewalld.conf
[DEFAULT]
banaction = firewallcmd-ipset[actiontype=<multiport>]
banaction_allports = firewallcmd-ipset[actiontype=<allports>]
再次启动测试工具向FreeSWITCH发起恶意注册,同2)类似,fail2ban也检测到了此次scanner攻击,也针对scanner ip进行了ban操作,但仍旧封禁失败。
使用firewall-cmd查看direct规则:
ipv4 filter INPUT_direct 0 -p tcp -m multiport --dports 5060,5061 -m set --match-set f2b-freeswitch-tcp src -j REJECT --reject-with icmp-port-unreachable
ipv4 filter INPUT_direct 0 -p udp -m multiport --dports 5060,5061 -m set --match-set f2b-freeswitch-udp src -j REJECT --reject-with icmp-port-unreachable
使用iptables查看规则:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:67
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
INPUT_direct all -- 0.0.0.0/0 0.0.0.0/0
INPUT_ZONES all -- 0.0.0.0/0 0.0.0.0/0
DROP all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain INPUT_direct (1 references)
target prot opt source destination
REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 5060,5061 match-set f2b-freeswitch-tcp src reject-with icmp-port-unreachable
REJECT udp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 5060,5061 match-set f2b-freeswitch-udp src reject-with icmp-port-unreachable
此时的conntrack记录:
ipv4 2 udp 17 179 src=192.168.1.12 dst=192.168.1.69 sport=5080 dport=5060 src=192.168.1.69 dst=192.168.1.12 sport=5060 dport=5080 [ASSURED] mark=0 zone=0 use=2
看到firewalld、iptables规则以及conntrack记录,对iptables和firewalld比较了解的同学估计也理解了为啥不能ban。。。
4、看了方法2和3的配置以及背后firewalld和iptable的规则,估计同学们有N种思路能让ban正常起来,本篇内容提供两种简单的方法,能让系统正常加固,抵御sip攻击:
1)方法1,启用NOTRACK
firewall-cmd --direct --add-rule ipv4 raw PREROUTING_direct 0 -p udp --dport 5060 -j NOTRACK
2)方法2,配置fail2ban使用firewalld内置的PREROUTING _direct链
使用方法1虽然能对检测到的sip攻击进行封禁,但NOTRACK的方法毕竟对业务路由可能会有影响,这催生了方法2,仅修改fail2ban的默认配置,使用firewalld内置的PREROUTING_direct链就能很完美的实现检测并封禁的功能,如下:
第一步,/etc/fail2ban/jail.d/00-firewalld.conf中使用firewall-ipset
第二步,修改/etc/fail2ban/action.d/firewallcmd-ipset.conf
将actionstart和actionstop中的filter修改为raw,如下:
[Definition]
actionstart = ipset create <ipmset> hash:ip timeout <default-ipsettime> <familyopt>
firewall-cmd --direct --add-rule <family> raw <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
actionflush = ipset flush <ipmset>
actionstop = firewall-cmd --direct --remove-rule <family> raw <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
<actionflush>
ipset destroy <ipmset>
将chain改为PREROUTING_direct,如下:
[Init]
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: [ STRING ]
#
chain = PREROUTING_direct
第三步,修改/etc/fail2ban/action.d/firewallcmd-common.conf
将blocktype改为DROP,如下:
# Option: blocktype (ipv4/ipv6)
# Notes See iptables/firewalld man pages for jump targets. Common values are REJECT,
# REJECT --reject-with icmp-port-unreachable, DROP
# Values: STRING
#blocktype = REJECT --reject-with <rejecttype>
blocktype = DROP
改完重启fail2ban测试,仅仅通过简单修改fail2ban配置,完美解决了检测sip攻击并封禁的问题。