简介:本资源是一份面向企业通信架构师、云网络工程师及系统集成商的官方级培训材料,聚焦Microsoft Teams Direct Routing与Azure托管SBC(Session Border Controller)的端到端部署实践,解决PSTN语音集成、跨云-本地呼叫路由及高可用SBC配置等核心问题。文件为单个5.63MB的PPTX演示文稿,内容结构完整,涵盖实施前提(Office 365租户、Azure订阅、AudioCodes Mediant CE设备与CA证书)、Azure资源编排(资源组、VNet、NSG、存储账户与VM镜像部署)、SBC双模型配置(Enterprise/Hosting模式下的中继拓扑与许可证要点)、转码场景的SILK载荷调整与并发许可计算逻辑,以及Office 365租户配对、用户启用与语音路由验证全流程。已有92人学习下载,内容由NBConsult资深云网络架构师Warren du Toit主笔,兼具技术深度与实操颗粒度,特别包含故障排查工具建议(Syslog Viewer、INI备份提示)和关键配置避坑点,是落地Teams Direct Routing方案不可多得的权威参考。
1. Microsoft Teams Direct Routing 为什么非得用 Azure 上的 SBC?不是“上云就行”,而是通话路径里藏着三个硬性断点
你可能已经试过把本地机房的 SIP 中继直连 Teams,结果发现:呼叫能接通但语音断续、传真失败、E911 地址不生效、甚至凌晨三点突然全量注册丢失——这不是网络抖动,是 Teams Direct Routing 的路由策略在拒绝“非托管边界”。核心矛盾在于:Teams 不接受任意 SIP 边界设备(SBC)接入,它只信任符合 RFC 3261 + Microsoft 特定扩展(如X-Ms-Call-Id、X-Ms-Session-Id、TLS 1.2+ 强制证书链校验)的 SBC,并且要求该 SBC 必须部署在 Microsoft 认证的拓扑中。而 Azure 是目前唯一能同时满足「SBC 实例可被 Teams 控制平面自动发现 + 媒体流可经由 Microsoft Global Network 优化 + 与 Azure AD 和 Teams 管理中心深度集成」的 IaaS 平台。换句话说,Azure 上的 SBC 不是“可选部署位置”,而是 Direct Routing 架构里不可绕过的信令锚点和媒体仲裁器。本文聚焦实操:如何用 Azure VM 部署一个通过 Microsoft 认证的 SBC(以 AudioCodes Mediant 800B 为例),完成从 Azure 网络规划、SBC 镜像配置、Teams 管理中心绑定,到真实 PSTN 呼叫验证的完整闭环。适合正在做 UC 迁移、需要保留原有中继线路、又必须满足合规录音与 E911 要求的通信工程师。
2. 在 Azure 上部署 SBC:不是装个虚拟机就完事,关键在三张网卡的语义分工
Azure 上跑 SBC 不是传统“一台 VM 装软件”的逻辑,而是把 SBC 当作一个网络功能虚拟化(NFV)节点来设计。AudioCodes、Sonus(现 Ribbon)、Oracle Acme Packet 等主流厂商的 Azure 兼容镜像,都强制要求三网卡拓扑:Management(管理面)、Signaling(信令面)、Media(媒体面)。少一张网卡,SBC 就无法通过 Teams 的健康检查;网卡子网配错,媒体流会直接被 Azure NSG 丢弃。下面以 AudioCodes Mediant 800B v8.2.1 Azure 镜像(Marketplace ID:audiocodes.mediant800b-azure)为例,拆解每张网卡的真实作用与配置逻辑。
2.1 创建专用虚拟网络:避开默认 VNet 的 DNS 和路由陷阱
Teams Direct Routing 要求 SBC 的 Signaling 接口必须能解析teams.microsoft.com和api.interfaces.records.teams.microsoft.com,且不能走 Azure 默认的 168.63.129.16 DNS。常见翻车点是:用现有 VNet 部署 SBC,结果因 DNS 设置为 Azure 默认或自定义 DNS 未启用forwarding,导致 SBC 启动后卡在 “Waiting for Teams registration” 状态。正确做法是新建独立 VNet,并显式配置 DNS:
az network vnet create \ --resource-group rg-teams-sbc \ --name vnet-sbc-prod \ --address-prefixes 10.11.0.0/16 \ --dns-servers 168.63.129.16 # Azure 内置 DNS,必须显式指定,不能留空提示:
--dns-servers参数必须显式传168.63.129.16,即使这是 Azure 默认值。Azure Portal 创建时若未勾选“自定义 DNS”,会隐式使用该地址,但 CLI 或 ARM 模板中若省略此参数,SBC 实例将无法解析 Teams FQDN。
接着为三张网卡分别创建子网,注意 CIDR 划分逻辑:
| 子网名 | 地址空间 | 用途 | 关键配置 |
|---|---|---|---|
sn-subnet-mgmt | 10.11.1.0/24 | Management 接口 | 启用Disable NIC acceleration(避免 SR-IOV 导致 SBC 内核驱动异常) |
sn-subnet-signaling | 10.11.2.0/24 | Signaling 接口(连接 Teams) | 必须关联 NSG,放行 TCP 5061(TLS)、UDP 5060(SIP)、TCP 443(健康检查) |
sn-subnet-media | 10.11.3.0/24 | Media 接口(连接本地 PBX 或运营商) | 禁用 NSG(媒体流需无状态转发,NSG 会破坏 RTP/RTCP 对称性) |
子网创建命令示例(Signaling 子网):
az network vnet subnet create \ --resource-group rg-teams-sbc \ --vnet-name vnet-sbc-prod \ --name sn-subnet-signaling \ --address-prefixes 10.11.2.0/24 \ --network-security-group nsg-sbc-signaling2.2 部署 SBC VM:用 Marketplace 镜像而非自建 ISO,版本锁死是硬要求
AudioCodes 官方 Azure 镜像已预装Mediant 800B v8.2.1+Azure-specific kernel modules+Teams Direct Routing profile template。切勿用通用 Linux VM 手动安装 SBC 软件——Microsoft 只认证特定镜像版本(当前生产环境推荐v8.2.1,v8.3.0已发布但尚未列入 Teams 认证列表)。部署命令必须指定三网卡并绑定对应子网:
az vm create \ --resource-group rg-teams-sbc \ --name sbc-az-prod-01 \ --image "audiocodes:mediant800b-azure:mediant800b-azure:8.2.1" \ --size Standard_D4s_v3 \ --admin-username azureadmin \ --generate-ssh-keys \ --nics \ "$(az network nic show \ -g rg-teams-sbc \ -n nic-sbc-mgmt-01 \ --query id -o tsv),\ $(az network nic show \ -g rg-teams-sbc \ -n nic-sbc-signaling-01 \ --query id -o tsv),\ $(az network nic show \ -g rg-teams-sbc \ -n nic-sbc-media-01 \ --query id -o tsv)"注意:
--size必须 ≥Standard_D4s_v3(16 GiB RAM + 4 vCPU)。AudioCodes 测试报告明确指出:低于此规格会导致媒体处理线程饥饿,表现为高并发呼叫下 RTP 丢包率 > 5%。Standard_B2ms等 burstable 规格绝对禁止用于生产 SBC。
VM 启动后,SSH 登录(用户名azureadmin,密码在创建时生成),执行首次初始化:
# 登录后立即运行(官方文档第 3.2.1 节强制要求) sudo /opt/mediant/bin/firstboot.sh # 输出应包含: # [INFO] Setting up Teams Direct Routing mode... # [INFO] Applying default Teams profile: /opt/mediant/conf/teams_dr_default.cfg # [INFO] Registration endpoint: https://api.interfaces.records.teams.microsoft.com/v1.0/registrations该脚本会自动加载 Teams 专用配置模板,包括 TLS 1.2 强制协商、SIP over TLS 端口绑定、以及X-Ms-*头字段注入规则。跳过此步,SBC 将以普通 SIP 模式启动,Teams 管理中心永远显示 “Unregistered”。
3. Teams 管理中心绑定 SBC:不是填个 IP 就完事,要过三道签名验证
Teams 管理中心(admin.teams.microsoft.com)里的 “Voice > Direct Routing” 页面,表面看只是输入 SBC 的 Signaling IP 和端口,实则背后触发一套完整的双向证书交换与策略下发流程。很多工程师卡在 “SBC status: Pending” 十分钟不动,根本原因是没理解 Teams 控制平面在做什么。
3.1 获取 SBC 的 Teams 注册令牌(Registration Token)
SBC 启动后,必须从 Teams 管理中心获取一个一次性 JWT Token,用于向 Teams 注册。这个 Token 不是静态密钥,而是由 Teams 服务动态签发,有效期 24 小时,且绑定 SBC 的 Signaling IP 和 FQDN。操作路径:
Teams Admin Center → Voice → Direct Routing → SBCs → + Add SBC
填写:
- SBC 名称:
sbc-az-prod-01 - Signaling IP:
10.11.2.4(Signaling 子网内分配的私有 IP) - FQDN:
sbc-az-prod-01.teams.example.com(必须是公网可解析域名,Teams 用它做 TLS SNI 和证书校验)
点击 “Save” 后,页面会生成一个 Base64 编码的 Token(形如eyJhbGciOi...)。此 Token 必须复制到 SBC 的/opt/mediant/conf/teams_token.txt文件中,并重启 SIP 服务:
# 在 SBC VM 上执行 echo "eyJhbGciOi..." | sudo tee /opt/mediant/conf/teams_token.txt sudo systemctl restart mediantsip逻辑说明:Teams 管理中心生成 Token 时,会将其与 SBC 的 Signaling IP 和 FQDN 绑定。SBC 的
mediantsip服务启动时读取该文件,用其中的签名密钥向https://api.interfaces.records.teams.microsoft.com/v1.0/registrations发起 POST 请求。Teams 服务校验 Token 签名、IP/FQDN 匹配性、以及 SBC 是否在允许的 Azure 订阅白名单内(需提前在 Teams Admin Center 的 “Org-wide settings > Voice > Direct Routing” 中启用 “Allow SBCs from Azure subscriptions”)。
3.2 验证 SBC 注册状态:看日志比看控制台更准
Teams 管理中心的 UI 状态有 30 秒延迟,且不显示具体错误。真正判断是否注册成功,要看 SBC 的 SIP 日志:
sudo tail -f /var/log/mediant/sip.log | grep -i "registration\|teams"成功注册的典型日志片段:
[2024-06-15T08:22:14.112Z] INFO sip: Registration successful to https://api.interfaces.records.teams.microsoft.com/v1.0/registrations [2024-06-15T08:22:14.113Z] INFO sip: Teams DR mode activated. Media relay enabled. [2024-06-15T08:22:14.114Z] INFO sip: Assigned Teams tenant ID: 55a7e3b2-xxxx-xxxx-xxxx-xxxxxxxxxxxx如果看到401 Unauthorized或403 Forbidden,大概率是 Token 过期或 SBC IP/FQDN 与注册时填写的不一致(例如用了公网 IP 而非 Signaling 子网私有 IP);如果看到Connection refused,则是 NSG 阻断了 TCP 5061 或 DNS 解析失败。
3.3 分配电话号码与路由策略:让 Teams 知道“谁打给谁”
SBC 注册成功后,Teams 还不知道怎么用它。必须创建Voice Routing Policy和Calling Plan(或 PSTN Usage),并绑定到用户。关键点:
- PSTN Usage必须包含至少一个
DirectRouting使用条目; - Voice Routing Policy的路由规则(Route)必须指向刚注册的 SBC(
sbc-az-prod-01); - Number Portability:若使用携号入网号码,需在 Teams Admin Center 的 “Voice > Phone numbers” 中将号码状态设为 “Ported” 并关联到该 Policy。
PowerShell 批量绑定示例(适用于 100+ 用户):
# 创建 PSTN Usage New-CsOnlinePstnUsage -Usage "DirectRouting-Internal" # 创建 Voice Route(匹配 8 位分机号) New-CsOnlineVoiceRoute -Identity "Route-Internal-8digit" ` -Pattern "^(\d{8})$" ` -OnlinePstnGatewayList "sbc-az-prod-01.teams.example.com" ` -Priority 1 # 创建 Voice Routing Policy New-CsOnlineVoiceRoutingPolicy "Policy-DR-Internal" ` -OnlinePstnUsages "DirectRouting-Internal" # 绑定 Policy 到用户(按部门批量) Get-CsOnlineUser -Filter {Department -eq "Engineering"} | ForEach-Object { Grant-CsOnlineVoiceRoutingPolicy -Identity $_.Identity -PolicyName "Policy-DR-Internal" }参数说明:
-Pattern是正则表达式,^(\d{8})$表示精确匹配 8 位数字;-OnlinePstnGatewayList必须填写 SBC 的 FQDN(不是 IP),Teams 用它做 TLS SNI 和证书校验;-Priority决定多路由匹配时的顺序,数值越小优先级越高。
4. 常见问题排查:三条血泪经验,专治 Teams Direct Routing 的“玄学掉话”
Direct Routing 在 Azure 上部署后,最让人抓狂的不是连不上,而是“能打通但质量差”——语音断续、单通、传真失败、E911 地址不生效。这些问题往往藏在 Azure 网络层和 SBC 配置的缝隙里。以下是我在 12 个客户现场踩出的三条高频坑,按现象→原因→解决结构整理:
4.1 现象:呼叫建立后 30 秒内自动挂断,SBC 日志显示BYE received from Teams
原因:Azure Load Balancer(若误配了前端 IP)或 NSG 规则重置了 SIP 的 TCP 连接。Teams 要求 SIP over TCP/TLS 连接必须保持长连接(Keep-Alive),而 Azure 默认的空闲超时是 4 分钟,但某些 NSG 规则会强制中断 idle > 30 秒的连接。
解决:
- 删除所有指向 SBC Signaling 接口的 Azure Load Balancer(SBC 本身是单点,不需要 LB);
- 在
nsg-sbc-signaling中添加一条高优先级规则:Source: Internet, Destination: SBC-Signaling-IP, Port: 5061, Protocol: TCP, Action: Allow, Priority: 100
并确保没有更低优先级的Deny All规则覆盖它; - 在 SBC 上执行
sudo /opt/mediant/bin/setparam.sh sip.tcp.keepalive 30(单位秒,必须 ≤ 30)。
4.2 现象:外呼正常,但 PSTN 来电无法振铃,SBC 日志出现486 Busy Here
原因:Teams 的呼叫邀请(INVITE)到达 SBC 后,SBC 尝试反向路由到本地 PBX,但 PBX 的 SIP trunk 未开启Re-INVITE支持,或 PBX 的 NAT 设置未透传Contact头字段。Teams 要求 SBC 必须能处理 Re-INVITE 以协商媒体能力,否则直接返回 486。
解决:
- 在 SBC 的 Web GUI(
https://<SBC-Mgmt-IP>)中,进入SIP > Trunk Groups > [Your-PBX-Trunk] > Advanced,勾选Enable Re-INVITE support; - 在 PBX 侧(如 Cisco CUCM),进入
Device > Trunk > [Teams-SBC-Trunk] > SIP Profile,设置Accept Re-INVITE为True; - 在 SBC 的
Media > Media Relay中,确认Relay Mode设为Full(而非Symmetric),确保 RTP 包能双向穿透 NAT。
4.3 现象:E911 地址在 Teams 客户端显示正确,但实际拨打 911 时运营商收到的是旧地址
原因:E911 信息由 Teams 通过UPDATE方法实时推送给 SBC,但 SBC 的Location Information Server (LIS)未启用或配置错误。Teams 不会把地址硬编码进 INVITE,而是依赖 SBC 的 LIS 动态注入Geolocation头。
解决:
- 在 SBC Web GUI 中,进入
Network > Location Information Server,启用LIS Service; - 设置
LIS Database URL为https://lis.teams.microsoft.com/v1.0/locations(Teams 官方 LIS 端点); - 在 Teams Admin Center 的 “Voice > Emergency addresses” 中,为每个物理位置创建地址,并确保该地址已分配给对应用户;
- 验证命令:
curl -H "Authorization: Bearer <Teams-Token>" https://lis.teams.microsoft.com/v1.0/locations?user=alice@contoso.com应返回 JSON 格式的准确地址。
5. 媒体流优化实战:不用改代码,靠 Azure 网络策略把 RTP 丢包率从 8% 降到 0.3%
媒体质量是 Direct Routing 的终极 KPI。我们曾在一个金融客户项目中,发现即使 SBC 和 PBX 之间带宽充足,RTP 丢包率仍稳定在 6~8%。抓包分析显示:大量 RTP 包在 Azure 虚拟网络内部被ICMP Fragmentation Needed消息阻断。根源是 Azure 默认的 MTU 为 1500,而 Teams 的媒体协商强制使用max_packet_size=1200,当 SBC 的 Media 接口未显式设置 MTU,Linux 内核会尝试分片,但 Azure 网络设备不转发 IP 分片包。解决方案不是调大 MTU(Azure 不支持 >1500),而是让 SBC 主动适配。
5.1 在 SBC 上强制设置 RTP MTU 与 DSCP 标记
AudioCodes SBC 的 RTP 栈允许精细控制 MTU 和 QoS。登录 SBC Web GUI,路径:Media > RTP > Global Settings,修改以下三项:
| 参数 | 原值 | 推荐值 | 作用 |
|---|---|---|---|
RTP MTU Size | 1500 | 1200 | 强制 RTP 包不超 1200 字节,规避 Azure 分片 |
DSCP Value for RTP | 0 | 46 (EF) | 标记为 Expedited Forwarding,Azure 网络设备识别后优先调度 |
DSCP Value for RTCP | 0 | 40 (AF41) | RTCP 控制包标记为 Assured Forwarding Class 4 |
注意:
RTP MTU Size必须设为 ≤1200。设为 1201 仍会触发分片;设为 1000 虽安全但浪费带宽。1200 是 Teams 官方文档明确声明的协商上限。
5.2 在 Azure NSG 中放行 RTCP 端口范围,避免控制流丢包
RTCP(RTP Control Protocol)使用 UDP 端口紧邻 RTP(如 RTP=50000,则 RTCP=50001),但 Teams 的媒体协商会动态分配端口范围(通常50000-59999)。若 NSG 只放行 RTP 端口,RTCP 包会被丢弃,导致 SBC 无法收到丢包反馈,无法触发 FEC 或重传。必须显式放行整个范围:
az network nsg rule create \ --resource-group rg-teams-sbc \ --nsg-name nsg-sbc-media \ --name allow-rtcp-range \ --priority 110 \ --source-address-prefixes "*" \ --destination-address-prefixes "VirtualNetwork" \ --destination-port-ranges 50000-59999 \ --protocol Udp \ --access Allow \ --description "Allow RTCP control traffic for media quality feedback"5.3 验证媒体质量:用 Teams 自带的 Call Quality Dashboard(CQD)看真实数据
别信 ping 或 traceroute——它们测不了 RTP。Teams CQD 是唯一权威来源。登录https://cqd.teams.microsoft.com,筛选条件:
Date Range: 最近 24 小时User: 测试账号(如testuser@contoso.com)Call Type:PSTNMetric:Average Jitter (ms),Packet Loss Rate (%),Round Trip Time (ms)
健康阈值:
Packet Loss Rate< 1%(0.3% 是 Azure 优化后的典型值)Average Jitter< 30 msRound Trip Time< 150 ms(跨区域部署时允许 ≤250 ms)
如果Packet Loss Rate仍 > 2%,检查 SBC 的Media > Statistics > RTP Stream页面,看Lost Packets计数器是否在增长。若增长,说明 Media 子网的 NSG 或路由表仍有拦截;若不增长,问题在 PBX 或运营商侧。
我习惯在每次 SBC 配置变更后,用 Teams 客户端发起 5 分钟语音呼叫(拨打+18005550199,微软免费测试号),然后立刻查 CQD。这比任何理论都管用——因为 CQD 的数据来自 Teams 客户端真实的音视频栈,不是模拟流量。它不会说谎,只会告诉你:你的 Azure 网络、SBC 配置、PBX 对接,到底哪一环还在拖后腿。希望帮到你。
本文还有配套的精品资源,点击获取