把 7101、7102 改用 TLS 注册,再通过测试短号互拨。在电话两边分别看到 SRTP 已协商,双方各说一句并请对方复述。证书握手、SIP 注册、媒体加密和双向声音都留一项结果,出现问题时就知道该从哪层查。示例对照 FreeSWITCH v1.11.3,使用内网测试节点和支持 SIP TLS、SDES-SRTP 的话机。两部话机原本就能注册互拨,节点使用 FreeSWITCH 转发媒体。
给 internal 配置 TLS 监听
用 fs_cli -x 'global_getvar conf_dir' 确认配置根目录。备份 sip_profiles/internal.xml 和将要修改的拨号计划。让测试 DNS 把 pbx.lab.example 指到测试节点,实际环境替换为自己的主机名。请本地 CA 为该名称签发证书,证书的 SAN 要包含这个 DNS 名称。将服务端私钥、叶证书及需要发送的中间证书按顺序放进 /etc/freeswitch/tls-lab/agent.pem,把 CA 证书包放为同目录的 cafile.pem。目录与私钥文件只给服务账号和维护人员所需权限。客户端的信任库另行导入相应 CA,服务器上的 cafile.pem 不会自动让话机信任它。
在现有 XML 的 settings 中修改以下项目,保留原监听 IP、域、口令认证和号码路由。示例只使用 SIP TLS。如果模板还有 WebSocket 监听,按测试范围单独关掉对应 ws-binding 和 wss-binding,并确认其他 profile 上有没有普通 SIP 监听。
<!-- 替换 internal 的 settings 中已有同名参数。 -->
<param name="tls" value="true"/>
<param name="tls-only" value="true"/>
<param name="tls-sip-port" value="5061"/>
<param name="tls-cert-dir" value="/etc/freeswitch/tls-lab"/>
<param name="tls-version" value="tlsv1.2"/>
<!-- 先进入拨号计划,再协商入局媒体。 -->
<param name="inbound-late-negotiation" value="true"/>
tls=true 开启 SIP TLS。tls-only=true 让这个 profile 不再绑定普通 SIP 端口,实验中只允许 TLS 话机重新注册。tls-sip-port 是 TCP 监听端口,本例 5061。第 17 期若已限制普通 SIP 端口,还要在测试防火墙上把允许来源和 5061 对齐,保持其他来源受限。RTP 仍用原来的 UDP 端口范围。证书绝对目录由 tls-cert-dir 指定,缺文件时实现可能走其他证书文件,验收以实际送出的证书为准。tls-version 是协议版本列表,本例只设双方支持的 TLS 1.2,扩展版本前按 Sofia、OpenSSL 和话机实际支持情况验证。
还有两个常用选项。tls-passphrase 用于加密私钥文件,本例假定服务可以直接读取受权限保护的密钥。需要双向证书认证时,再规划 tls-verify-policy 和话机的客户端证书。当前用例由话机验证服务端名称和证书链,分机身份继续走 SIP Digest。第一次迁移可以在隔离节点平行准备旧路径,记录两种传输分别在哪个端口,避免话机实际还走旧入口却被误判为切换成功。
为两条腿设定 SRTP
TLS 承载 SIP 消息。SDES 把媒体密钥信息放在 SDP 中,所以承载这些 SDP 的每一跳都要保护。下面把 SRTP 策略放在专用路由,不动其他号码。vanilla 的 default context 会包含 dialplan/default/*.xml。在 dialplan/default/18_srtp_lab.xml 写入下面的扩展。先确认 787101 和 787102 没被已有规则匹配。自定义 context 时,放到两部分机认证后实际使用的拨号计划中。
<include>
<extension name="fs18-secure-test">
<condition field="destination_number" expression="^78(710[12])$">
<!-- A 腿设为必需;向新建通道传播通用设置。 -->
<action application="set" data="rtp_secure_media_inbound=mandatory"/>
<action application="export" data="rtp_secure_media=mandatory"/>
<!-- B 腿明确设置出局方向的媒体策略。 -->
<action application="bridge" data="{rtp_secure_media_outbound=mandatory}user/$1@${domain_name}"/>
</condition>
</extension>
</include>
拨 787102 时,表达式取出 7102,拨 787101 就取出 7101。这里假设 user/ 使用该域的 TLS 注册 Contact,实验中只保留测试话机的 TLS 新注册,避免旧 Contact 参与呼叫。A 腿的 rtp_secure_media_inbound 设为 mandatory,B 腿在拨号串里显式设置 rtp_secure_media_outbound,通用变量也通过 export 传给新通道。方向变量存在时优先使用它。inbound-late-negotiation 让入局媒体协商可以等拨号计划先设置策略。测试路由到这段之前,保持没有主动接听或提前协商媒体的动作。
mandatory 要求协商 SRTP,optional 允许走兼容路径,forbidden 禁用安全媒体。这次验收使用 mandatory。两个端点要有共同支持的套件,必要时从设备协商结果检查套件列表。FreeSWITCH 在普通媒体转发模式下分别处理两条腿,所以确认一边加密以后,还要看另一边。7101、7102 是 SIP 分机,队列 agent 和 tier 仍按队列规则配置。
分四项验收
# 在隔离节点、没有活动通话时重新加载。
fs_cli -x 'reloadxml'
fs_cli -x 'sofia profile internal restart'
fs_cli -x 'sofia status profile internal'
# 从话机所在网段用实际的 CA 和主机名验证 TLS。
openssl s_client -connect pbx.lab.example:5061 \
-servername pbx.lab.example -verify_hostname pbx.lab.example \
-CAfile ./lab-ca.pem -verify_return_error </dev/null
重启 profile 前让测试通话结束。它会影响这个 profile 的通话和设备连接。先从话机所在网段检查 5061 的 TLS 握手、服务端证书链和域名。再让两部话机用 TLS、5061 注册,保留各自的认证凭据。若话机区分服务器地址和认证域,前者使用与证书相符的主机名,后者与原分机目录的域保持一致。
从 7101 拨 787102,再反向拨 787101。每次查看两侧的最终协商结果,确认安全媒体配置,如 SDP 中的 RTP/SAVP 与所选 crypto 套件,再检查双向声音。只保留协议和套件名,SDP 的 inline 密钥、鉴权头和号码对外分享前应脱敏。用同一条实验路由把一部话机的 SRTP 暂时关掉,预期无法完成允许明文媒体的通话。测试后恢复原设置。这里是验收预期,未在 FreeSWITCH 实例运行。
故障定位和回退
- 5061 不通。查 profile 实际监听、端口是否被其他实例占用、服务日志和防火墙。证书读不到时,检查服务账号能否进入目录并读取文件。
- 握手失败。对照 DNS 名称、证书 SAN、链、有效期和客户端时钟。旧设备若没有共同支持的协议版本,先确认兼容方案。
- TLS 能注册,拨号失败。检查短号是否进了实验路由,B 腿是否用新 Contact,双方是否支持同一种 SDES 套件。协商通过却无声时,分别核对两腿的媒体地址和 UDP 通路。
回退时从系统控制台恢复旧 profile 和话机的原传输设置,移走测试拨号文件,恢复本次新增的防火墙规则,再重新加载 XML 与 profile。用改动前的两个分机复验注册和互拨。