7101 和 7102 要在办公网注册互拨,其他来源进不了分机的 SIP 端口。两个分机即使来自允许的地址,注册时也要用各自的密码。下面以 FreeSWITCH v1.11.3 的 vanilla 配置和一台直接接收话机 SIP 的 Linux 测试机为例。先限定在内网 IPv4、普通 UDP/TCP SIP,假设 internal 监听 5060。公网、中继、TLS 和 WebSocket 有各自的监听入口,要按实际部署另做规则。
用主机防火墙先限制来源
先用 7101 和 7102 在原配置下分别注册、互拨并确认双向声音,留一个改动前的参照。记下服务器实际看到的来源 IP。测试时每部话机用一个固定地址,并准备一个不在名单里的测试终端。两个终端若共用 NAT 出口,服务器看到的可能是同一个 IP,防火墙就无法用这个条件分别识别它们。
在测试机新建 /etc/nftables.d/fs17-lab.nft。下面是一张独立的实验表,使用前确认表名尚未占用,按现场替换两个地址和端口。例子里的 192.0.2 地址来自文档保留网段,只是占位。这个例子针对经过本机 input hook 的流量,容器端口转发或前置 SBC 要到实际经过的链路上应用策略。
table inet fs17_lab {
chain sip_input {
# 只给测试 SIP 端口加来源限制,其他流量继续走现有规则。
type filter hook input priority -10; policy accept;
# 两个地址均为文档占位,加载前替换为服务端看到的来源。
ip saddr { 192.0.2.71, 192.0.2.72 } udp dport 5060 counter accept
ip saddr { 192.0.2.71, 192.0.2.72 } tcp dport 5060 counter accept
# 剩下的 IPv4 和 IPv6 流量都会在这里被拦下。
udp dport 5060 counter drop
tcp dport 5060 counter drop
}
}
inet 同时处理 IPv4 和 IPv6。两条带 ip saddr 的规则只让指定 IPv4 来源通过这一关。后面的两条按目标端口拦住其余来源,并通过 counter 留下命中计数。链优先级 -10 是处理顺序,数字越小越早执行。其他现有链仍可能丢包,所以规则里的 accept 只代表本链通过。策略只圈住示例 SIP 端口,RTP、管理端口和其他业务继续走现网规则。加载前看一遍已有规则和服务实际绑定,确认 5060 上没有共用业务。
让 SIP Profile 继续查分机密码
用 fs_cli -x 'global_getvar conf_dir' 找配置根目录,备份 sip_profiles/internal.xml。在现有 settings 中合并下面这段。保留原来的域、端口和拨号计划。目录里的 7101、7102 继续各用独立密码。实验 profile 中把已有的 apply-register-acl 和 apply-proxy-acl 配置项移除,确认没有后续 include 又把信任项加回来。
<!-- 合并进 internal 的 settings;已有同名设置直接替换。 -->
<!-- 清掉原有信任列表,分机继续走口令认证。 -->
<param name="apply-inbound-acl" value="none"/>
<param name="auth-calls" value="true"/>
<param name="auth-calls-acl-only" value="false"/>
<param name="accept-blind-reg" value="false"/>
<param name="accept-blind-auth" value="false"/>
<param name="inbound-reg-force-matching-username" value="true"/>
apply-inbound-acl=none 清空先前累积的入站信任列表。vanilla 内部 profile 原来引用 domains,这个列表会把目录用户的 cidr 带进来,命中时可能按地址认可身份。实验里将来源限制交给防火墙,把用户认证交回 SIP Digest。auth-calls=true 让入站 INVITE 进入呼叫认证流程,auth-calls-acl-only=false 保留常规挑战路径。两个 accept-blind 选项都关闭。inbound-reg-force-matching-username 用于要求注册身份和认证用户名相符。
特别容易踩的是 apply-register-acl。在 v1.11.3 的 Sofia 注册源码中,来源不在列表里会返回 403,命中时可以进入 REG_AUTO_REGISTER,绕过正常的密码挑战路径。所以把它加到分机 profile 后,拿正确密码注册成功,只做到了正向验证。要看设备是否走了预期的 Digest,还得换错误密码试一次。运营商或可信 SBC 按 IP 放行是另一种部署方式,适合在单独的 profile 和受限拨号入口上按链路设计。经过 SBC 时,地址层只看得到实际对端,原始身份需要由可信设备及各段的认证流程来确认。
加载后分别验收地址和口令
保留系统控制台。以下命令用于独立测试机。重启 Sofia profile 可能打断该 profile 的通话和注册,先让通话结束。reloadxml 先更新配置,profile 重启后再核对状态和新注册。
# 确认当前 SIP profile、实际端口与管理规则。
fs_cli -x 'sofia status profile internal'
sudo nft list ruleset
# 检查语法后,仅加载实验表。
sudo nft -c -f /etc/nftables.d/fs17-lab.nft
sudo nft -f /etc/nftables.d/fs17-lab.nft
sudo nft list table inet fs17_lab
# 在无活跃通话的测试机上重新读取 Sofia profile。
fs_cli -x 'reloadxml'
fs_cli -x 'sofia profile internal restart'
fs_cli -x 'sofia status profile internal reg'
从名单内的 7101 开一个新的注册会话,观察挑战与携带认证的重试,确认最终注册成功。按相同步骤验证 7102,再各拨对方一次,确认双向声音。随后从允许的来源用测试账号和错误密码发起新注册,预期没有成功的绑定。旧注册可能仍在表里,先通过话机注销或等它过期,再按时间和地址确认这次尝试。最初的 401 是挑战,可以出现在正常注册里。检查最终响应和新绑定,才能知道密码是否通过。
再从自有的第三台测试终端尝试注册,确认防火墙 drop 计数增加,FreeSWITCH 侧没有收到这次请求。使用同一个已授权测试账号即可,区别只在来源。若 SIP 端口被丢包,终端可能超时,看不到 403,这是预期的网络层表现。7101、7102 在这里是 SIP 分机,队列里的 agent 和 tier 属于后续派单层。
出问题时定位和回退
- 名单里的话机也超时。检查 drop 计数、服务器看到的源地址、目标端口及其他防火墙链。如果使用容器转发,确认流量实际走的是 input 还是 forward。
- 错误密码仍能注册。先排除旧绑定,再核对连接的 profile。检查是否还有注册 ACL、盲注册或其他信任入口,并用脱敏信令核对是否完成了新认证。
- 注册成功却打不通。单独看 INVITE 的认证和拨号 context。注册挑战通过只说明注册流程成功,拨号路由、座席状态和媒体连通还要各自检查。
- 换了密码后反复挑战。核对用户名、realm 与实际收到的算法选项。RFC 8760 定义了更强的 Digest 算法,设备是否支持要看双方配置和兼容性。
需要回退时,优先保留管理控制台,恢复备份的 profile 并重启确认,然后仅移除本次新增的表 sudo nft delete table inet fs17_lab。临时文件如果已被系统防火墙配置包含,同步移除该引用,避免下次启动又加载。用原来的两部分机复验注册和互拨。上述结果是根据公开资料写出的验收预期,未在现场运行。