这里是一个关于SBC的安全机制,实际上,这个机制它只是整个安全防范的其中之一,在这之前,还可以做地理防范,可以允许一个地理范围内的发送注册请求过来,比如你公司只可能是上海范围内的注册,则我们在防火墙上,就可以设置,只允许上海的IP发送请求,并且只可以是Yealink的电话机,并且可以指定电话机的型号,比如只可以是T31的注册;
如果设置的是T31,则T19都不可能注册过来;地理防范是可以用防火墙或者是ECS的安全组完全可以实现,只允许指定区域的IP才可能注册上,UA可以设置设备型号验真,本章节介绍的是验正密码;如果说,密码错误次数达上限,则封锁IP,这里的前提是它已经UA正确了过后,才可能进入这个环节;比如我们设置的是T19,但是使用的是T31,则会直接拉黑,根据不可能进到校对密码的流程当中;

前面二关已经正确了,然后第三关了;假如说在指定的时间范围内,密码错误,并且已经达到上限,立即封锁这个IP地址,但是如果你密码正确了,则正常处理;
🔐 SIP 密码错误自动封禁 IP 完整指南
适用环境:Kamailio 5.x 作为Asterisk 透明代理
目标:自动检测暴力破解,实时封禁攻击 IP,零误伤正常用户,当然了这里的127.0.0.1是本机的意思,如果你的部署方案不同,则需要修改IP信息,下面的方案,我们已经在Kamailio的5.6.3及5.8.8版本上测试完全可行。
一、痛点分析
VoIP 系统常遭受分机密码穷举攻击。现有防护存在明显不足:
- Fail2Ban 延迟高,解析日志才能封禁,攻击者已尝试大量密码。
- 难以区分正常挑战与密码错误,易将首次 401 挑战误认为攻击,导致正常用户被封。
- 代理模式下真实 IP 丢失,Kamailio 转发给IPPBX后,响应中的 $si 变成 127.0.0.1,无法获取攻击者 IP。
二、设计思路
我们利用 Kamailio 内置的 哈希表(htable) 和 事务回调,在请求阶段暂存客户端真实 IP 和“是否携带密码”的标志,通过 SIP 协议的 Call‑ID 将请求与响应精准关联。在专用的响应处理块中,只对“携带密码仍被拒绝”的 401/403 进行计数,达到阈值后复用已有的 ip_ban 表直接封禁。
- 完全在 Kamailio 内部实现,不依赖数据库、不修改后端
- 正常用户注册成功(200 OK)立即清零所有计数和封禁
- 首次 401 挑战不计数,避免误伤
- 封禁记录 1 小时后自动过期,无需人工解封
三、实现原理
1. 请求-响应关联
在 REGISTER 请求转发前,将真实客户端 IP 和 Authorization 标记存入哈希表:
# 以 Call-ID 为键存储 IP 和是否携带密码
$sht(reg_req_info=>$ci + "_ip") = $si;
if (is_present_hf("Authorization") || is_present_hf("Proxy-Authorization")) {
$sht(reg_req_info=>$ci + "_auth") = "1";
} else {
$sht(reg_req_info=>$ci + "_auth") = "0";
}
t_on_reply("REPLY_HANDLER");
响应返回时,利用相同的 Call-ID 读取真实 IP:
$var(client_ip) = $sht(reg_req_info=>$ci + "_ip");
$var(auth_flag) = $sht(reg_req_info=>$ci + "_auth");
2. 精准计数策略
| 场景 | Authorization 头 | 响应码 | 操作 |
|---|---|---|---|
| 正常首次挑战 | 无 | 401 | ❌ 不计数 |
| 暴力破解(错误密码) | 有 | 401/403 | ✅ 计数 +1 |
| 注册成功 | 有/无 | 200 OK | 🧹 清零所有计数和封禁 |
if (t_check_status("401|403")) {
if ($var(auth_flag) == "1") {
$var(cnt) = (int)$sht(auth_stats=>$var(client_ip)) + 1;
$sht(auth_stats=>$var(client_ip)) = $var(cnt);
if ($var(cnt) >= 5) {
$sht(ip_ban=>$var(client_ip)) = 10;
$sht(auth_stats=>$var(client_ip)) = $null;
}
}
}
# 注册成功立即清零
if (t_check_status("2[0-9][0-9]")) {
$sht(auth_stats=>$var(client_ip)) = $null;
$sht(ip_ban=>$var(client_ip)) = $null;
}
3. 封禁与解封机制
- 计数窗口:5 分钟(
auth_stats表autoexpire=300) - 封禁阈值:同一 IP 在窗口内累计 5 次携带错误密码的 401/403
- 封禁动作:将该 IP 写入
ip_ban表(值=10),在请求入口处统一丢弃:
if ($sht(ip_ban=>$si) >= 5) {
xlog("L_WARN", "IP封禁中: $si\n");
drop;
}
- 解封方式:
- 主动解封:该 IP 成功注册一次(200 OK)立即清除
ip_ban和auth_stats。 - 自动过期:封禁记录在 1 小时后自动消失(
ip_ban表的autoexpire=3600)。
- 主动解封:该 IP 成功注册一次(200 OK)立即清除
四、配置步骤
只需修改 /etc/kamailio/kamailio.cfg,共三处:
- 新增两个 htable:
modparam("htable", "htable", "auth_stats=>size=6;autoexpire=300") modparam("htable", "htable", "reg_req_info=>size=8;autoexpire=60") - 在 REGISTER 转发前插入存储 IP 和 Auth 标记的代码(见上文)。
- 新增专用响应路由
onreply_route[REPLY_HANDLER](见上文)。
cp /etc/kamailio/kamailio.cfg /etc/kamailio/kamailio.cfg.bak.$(date +%Y%m%d_%H%M%S) # ... 写入新配置 ... kamailio -c /etc/kamailio/kamailio.cfg && systemctl restart kamailio
五、测试验证
- 从外网使用错误密码连续注册 5 次。
- 查看日志:
tail -f /var/log/kamailio.log | grep -E "auth_failed|封禁"
应看到类似输出:auth_failed count=4 ip=xxx.xxx.xxx.xxx 暴力破解封禁 IP:xxx.xxx.xxx.xxx (1小时内自动解封)
- 检查内存黑名单:
kamcmd htable.dump ip_ban
- 使用正确密码从同一 IP 注册,观察日志中“清零计数”信息,验证自动解封。
六、经验分享
htable + Call‑ID 关联 巧妙解决了代理模式下真实 IP 追踪难题。通过精准判断“携带密码仍被拒绝”,实现了对暴力破解的实时封禁,同时对正常用户零误伤。目前已在生产环境稳定运行,极大降低了 SIP 账户被盗的风险。
当然了,安全防范是一直在进步的,需要一直了解新技术,新的机制和原理,IPPBX也是需要更新到新的版本。
本站所有文章,如果是技术类文章,均为内部学习交流使用,非专业技术人员,请勿对设备进行任何修改及操作,以免造成设备无法运行,或者损坏,导致设备不可正常使用。建议定期对设备数据进行备份和保存。
📞 我们专注于通信器材销售和各厂家电话交换机的维护,并提供上海地区的调试和安装,可以提供各种电话交换机的主机板、CPU、外线板及分机板,各类连接套件,提供弱电布线;包含网络线、电话线、门禁。
