尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
FreeSWITCH呼入呼出路由配置详解:从Dialplan到Gateway的实战指南
简介这份文档面向使用 Freeswitch 搭建 VoIP 通信平台的运维与开发人员聚焦呼入呼出路由配置这一关键环节帮助读者理清拨号计划、SIP 中继与对等中继模式下的外呼实现思路。资源包内共 1 个 doc 文件约 221KB内容围绕 Freeswitch 整体架构展开涵盖程序启动流程、消息分发机制、mod_sofia 模块组成与启动过程等核心知识点并配有术语定义与条目编号规范便于按模块查阅。文档以个人学习总结的形式梳理了系统架构与模块协作关系可作为理解呼入路由、外呼策略及中继配置的参考底稿适合需要快速建立 Freeswitch 整体认知的初中级读者对照实践。目前已有 6455 人学习下载具备一定的参考热度。1. 从一通打不通的外线说起FreeSWITCH 呼入呼出路由到底在配什么很多团队第一次把 FreeSWITCH 接上 SIP 网关内部分机互拨一切正常一拨外线就静默挂断或者外面打进来直接落到默认的public上下文里被拒。问题往往不在网关而在拨号计划Dialplan和 SIP 中继gateway这两层没对齐。这份 FreeSWITCH 呼入呼出路由配置详解核心就是围绕dialplan的 XML 路由规则、sip_profiles下的中继定义以及呼入落到哪个 context、呼出走哪条 gateway 这条主线展开的。它适合已经能把 FreeSWITCH 跑起来、但卡在“内呼通、外呼不通”这一步的运维和通信开发人员也适合需要给小型呼叫中心做落地路由的工程师。下面按“先看清结构、再动手配、最后排坑”的顺序拆。2. 先看清 FreeSWITCH 的呼叫骨架Core、Module 与 Dialplan 的分工在改任何一行 XML 之前得先知道一个呼叫进来之后FreeSWITCH 内部是谁在接、谁在转、谁在决定下一步。这份文档把 Core 启动、模块加载、事件分发讲得比较细落到路由配置上真正要盯住的是三个东西SIP 端点模块mod_sofia、拨号计划模块mod_dialplan_xml、以及中继网关gateway。它们的分工决定了你改哪个文件、重启哪个模块。2.1 从 switch.c 启动到模块加载路由能力从哪来FreeSWITCH 主入口在src/switch.c的main()它做四件事解析启动参数、给全局目录变量SWITCH_GLOBAL_dirs赋值、创建 pid 文件、调用switch_core_init_and_modload()。这个函数内部先跑switch_core_init()做核心初始化再调switch_loadable_module_init()加载模块。模块加载顺序很关键先加载集成模块CORE_SOFTTIMER_MODULE、CORE_PCM_MODULE然后遍历conf/modules.conf和conf/post_load_modules.conf最后为每个模块的 runtime 入口起线程。对路由来说mod_sofia必须在modules.conf里被加载否则 SIP 栈根本不存在sip_profiles里的中继配置也不会生效。常见做法是确认modules.conf里有load modulemod_sofia/并且mod_dialplan_xml也在列表里——后者负责把dialplan/目录下的 XML 解析成可执行的路由动作。如果只加载了 sofia 没加载 dialplan_xml呼叫能进来但找不到路由表现就是直接挂断。提示改完modules.conf后不要只reloadxml模块增删需要重启进程或至少reload mod_sofia否则新模块的接口不会注册到 hash 表里。2.2 事件分发与呼叫状态为什么路由要看 CHANNEL_CREATE 和 CHANNEL_ANSWER文档里列了一长串事件类型路由配置真正相关的是SWITCH_EVENT_CHANNEL_CREATE、SWITCH_EVENT_CHANNEL_ANSWER、SWITCH_EVENT_CHANNEL_BRIDGE、SWITCH_EVENT_CHANNEL_HANGUP。事件分发机制是switch_event_init()初始化EVENT_DISPATCH_QUEUE队列并起分发线程队列容量和 CPU 个数相关消息先 push 进队列再由switch_event_dispatch_thread分发。这跟路由有什么关系当一通外线呼入mod_sofia收到 INVITE 后创建 channel触发CHANNEL_CREATE然后进入拨号计划匹配。如果你在 dialplan 里配了bridge到某个 gateway成功桥接时会有CHANNEL_BRIDGE如果 gateway 认证失败或对端拒绝你会看到CHANNEL_HANGUP且 cause 是CALL_REJECTED或NORMAL_TEMPORARY_FAILURE。排障时用fs_cli订阅这些事件比盲改 XML 快得多# 订阅与路由相关的核心事件观察一通外呼的完整生命周期 fs_cli -x /event plain CHANNEL_CREATE CHANNEL_ANSWER CHANNEL_BRIDGE CHANNEL_HANGUP这条命令的逻辑是让fs_cli以 plain 格式订阅四类事件输出里能看到每个 channel 的Caller-Destination-Number、variable_sip_gateway、Hangup-Cause。参数说明plain是输出格式后面跟事件名列表多个事件用空格分隔。实际排障时我一般再加CHANNEL_EXECUTE能看到 dialplan 执行到哪个 application 就断了。2.3 Dialplan 与 SIP Profile 的边界谁决定呼入 context谁决定呼出 gateway这是最容易混淆的一层。呼入方向sip_profiles/internal.xml或external.xml里的param namecontext valuepublic/决定这通呼叫落到哪个 dialplan context呼出方向dialplan 里的action applicationbridge datasofia/gateway/网关名/号码/决定走哪条中继。也就是说profile 管“进门”dialplan 管“出门”gateway 定义在sip_profiles/gateway/或 profile 内的gateway段里。文档里提到 mod_sofia 由 FreeSWITCH 的 TU 层加 Nokia sofia-sip 协议栈组成NUA 对上、NTA 对下传输层 UDP/TCP 对应用层透明。落到配置上这意味着你在 gateway 里写register还是registerfalse、proxy指向谁决定了 NUA 的行为而dialplan只关心“把呼叫交给哪个 gateway 名字”。两者通过 gateway 名字解耦改中继地址不用动 dialplan这是这套结构最大的好处。3. 呼入路由落地从 external profile 到 public context 的完整链路呼入不通九成问题出在“呼叫进来了但没匹配到正确的 context 或 extension”。这一章按配置文件顺序走一遍先确认 external profile 的 context 和端口再在 public context 里写 extension 匹配被叫号码最后用transfer或bridge落到内部分机或 IVR。3.1 external profile 的关键参数context、sip_port 与 auth-calls外部呼入一般走conf/sip_profiles/external.xml。核心参数就几个sip_port是监听端口网关对接常用 5060context决定呼入落到哪个 dialplan默认是publicauth-calls控制是否对呼入做认证对接网关时如果网关不做注册通常设false否则会被 401 挡掉。下面是一段精简后的 profile 片段profile nameexternal settings !-- 外部呼入监听端口与网关侧填写的一致 -- param namesip-port value5060/ !-- 呼入落到 public context由 dialplan/public.xml 接管 -- param namecontext valuepublic/ !-- 网关不注册时关闭呼入认证避免 401 -- param nameauth-calls valuefalse/ !-- 允许的编解码按网关实际能力裁剪 -- param nameinbound-codec-prefetch valuePCMA,PCMU/ /settings /profile逻辑说明sip-port必须和网关侧配置的对端端口一致网关填 5060 你这边就不能改成 5080context写public后所有从这条 profile 进来的呼叫都会去dialplan/public.xml找 extensionauth-calls设false的前提是网关侧做了 IP 白名单或专线对接公网暴露的 profile 不要这么设。参数怎么改如果网关要求注册把auth-calls改回true并在directory里建对应用户编解码按网关实际支持的填填了网关不支持的会导致协商失败、单通或无声。3.2 public context 的 extension 匹配destination_number 正则与 transfer 动作呼入落到public后dialplan/public.xml里的 extension 按destination_number正则匹配。常见做法是匹配网关送来的被叫号码前缀然后transfer到内部 context 的分机或者直接bridge到某个分机。下面这段匹配以0开头的外线号码并转到内部defaultcontextinclude context namepublic !-- 匹配网关送来的任意被叫号码按需收窄正则 -- extension namefrom_gateway condition fielddestination_number expression^(\d)$ !-- 转到内部 default context由内部 dialplan 继续路由 -- action applicationtransfer data$1 XML default/ /condition /extension /context /include逻辑说明expression^(\d)$捕获全部数字被叫号码$1在transfer里引用捕获组transfer的data格式是“目标号码 XML context”这里把号码原样带到defaultcontext 再匹配分机。参数怎么改如果网关送来的是带区号的号码正则改成^0(\d{10})$之类$1取后十位如果呼入要直接进 IVR把transfer换成answer加playback或ivr应用。失败时看什么fs_cli里dialplan没匹配会打No route检查destination_number实际值和正则是否对得上用fs_cli -x show channels看dest字段。3.3 呼入直转分机与 IVR 的分流写法实际项目里往往不是所有呼入都转分机总机号进 IVR、直线号直转分机。做法是在publiccontext 里按号码段写多个 extension靠正则区分。比如^9(\d{3})$进 IVR^8(\d{3})$直转分机extension nameto_ivr condition fielddestination_number expression^9(\d{3})$ action applicationanswer/ action applicationsleep data500/ action applicationivr datamain_ivr/ /condition /extension extension nameto_extension condition fielddestination_number expression^8(\d{3})$ action applicationtransfer data$1 XML default/ /condition /extension逻辑说明answer先应答避免主叫听到静默sleep 500给媒体协商留时间ivr指向conf/ivr_menus/下的菜单名直转分支用transfer把后三位带到defaultcontext。参数说明sleep单位毫秒设太大主叫会觉得慢500 到 1000 之间比较稳ivr的菜单名要和ivr.conf.xml里的name一致写错会报Cannot find IVR。这里的分流逻辑完全靠正则顺序FreeSWITCH 按文件内 extension 顺序匹配第一个命中的生效所以把更具体的正则放前面。4. 呼出路由落地gateway 定义、bridge 写法与对等中继模式外呼不通的典型现象是拨号后立刻挂断fs_cli里看到sofia/gateway/xxx返回404或503。这一章从中继定义开始到 dialplan 里的bridge写法再到对等中继模式下 IP 和端口的填法把外呼链路补齐。4.1 gateway 定义register、proxy 与对等中继的填法中继定义可以放在conf/sip_profiles/external/下的独立 XML也可以写在 profile 内的gateway段。对等中继模式不注册、按 IP 对接的关键是register设falseproxy填网关地址和端口。下面是一个对等中继的 gateway 定义gateway namegw_pstn !-- 对等中继不向网关注册 -- param nameregister valuefalse/ !-- 网关地址和端口按实际对接填写 -- param nameproxy value192.0.2.10:5060/ !-- 主叫号码前缀部分网关要求带区号 -- param namecaller-id-in-from valuetrue/ !-- 认证用户名密码对等模式网关不校验时可留空 -- param nameusername value/ param namepassword value/ /gateway逻辑说明registerfalse表示 FreeSWITCH 不主动向网关发 REGISTER网关侧按 IP 信任proxy是外呼 INVITE 的目的地址写错就是503caller-id-in-fromtrue让主叫号码放在 From 头部分网关只认 From 不认 P-Asserted-Identity。参数怎么改网关要求注册时把register改true并填username/passwordproxy支持host:port端口不写默认 5060如果网关要求特定 realm加realm参数。失败时看什么fs_cli -x sofia status gateway gw_pstn看 State 是否NOREG对等模式正常或REGEDfs_cli -x sofia loglevel all 9开详细日志看 INVITE 发到哪。4.2 dialplan 外呼 extensionbridge 到 gateway 的号码拼接外呼 extension 一般放在defaultcontext匹配内部拨号习惯比如0开头走外线。核心动作是bridge到sofia/gateway/网关名/号码号码部分要按网关要求补全或去前缀extension nameoutbound_pstn !-- 内部拨 0 加号码走外线 -- condition fielddestination_number expression^0(\d{7,11})$ !-- 去掉前缀 0把剩余号码交给网关 -- action applicationset dataeffective_caller_id_number1001/ action applicationbridge datasofia/gateway/gw_pstn/$1/ /condition /extension逻辑说明^0(\d{7,11})$匹配 0 加 7 到 11 位号码$1是去掉 0 后的号码effective_caller_id_number设置外显号码不设会用分机号部分网关会拒bridge的data格式是sofia/gateway/网关名/被叫号码网关名必须和 gateway 定义里的name完全一致。参数怎么改网关要求带区号就在$1前拼区号比如sofia/gateway/gw_pstn/010$1需要走多条中继做负载就写多个 gateway 名并用|分隔FreeSWITCH 会按顺序尝试。失败时看什么Hangup-Cause是CALL_REJECTED多半是网关拒了主叫号码或号码格式NO_ROUTE_DESTINATION是 gateway 名写错或没加载。4.3 外呼失败的分层排查从 gateway 状态到 SIP 响应码外呼排障我一般按三层走先看 gateway 状态再看 dialplan 是否命中最后看 SIP 响应码。第一层fs_cli -x sofia status确认gw_pstn在列表里且 State 正常第二层fs_cli -x console loglevel debug后拨号看日志里有没有Dialplan: outbound_pstn这行没有就是正则没匹配第三层看 INVITE 的响应403是网关策略拒、404是号码不存在、503是网关不可达、488是编解码协商失败。# 三层排查的组合命令 fs_cli -x sofia status # 第一层gateway 是否加载 fs_cli -x console loglevel debug # 第二层开 debug 看 dialplan 命中 fs_cli -x sofia loglevel all 9 # 第三层看 SIP 信令细节逻辑说明sofia status列出所有 profile 和 gateway 的状态console loglevel debug让 dialplan 匹配过程打到控制台sofia loglevel all 9把 sofia-sip 协议栈日志开到最细能看到完整 INVITE 和响应。参数说明日志级别排完记得调回info和0否则日志量会拖慢系统。这套顺序的好处是先排除配置层再进协议层避免一上来就抓包。5. 避坑与排查呼入呼出配置里最容易翻车的五件事这一章是我自己踩过、也见别人反复踩的五个坑每个按“现象 → 原因 → 解决”写。路由配置的玄学大多不是 FreeSWITCH 本身的问题而是 profile、dialplan、gateway 三者的边界没对齐。5.1 呼入直接挂断日志显示 No route现象外线打进来主叫听到一声忙音或直接断fs_cli里出现No route to destination。原因呼入落到的 context 里没有匹配destination_number的 extension或者 profile 的context写成了default但default.xml里没有对应正则。解决先用fs_cli -x show channels看呼入 channel 的context和dest实际值再对照dialplan/public.xml的正则常见错误是网关送来的号码带或空格正则^(\d)$匹配不上改成^\?(\d)$并做号码规整。5.2 外呼 401/403网关拒绝认证现象拨外线后立刻断SIP 响应401 Unauthorized或403 Forbidden。原因gateway 的register和username/password与网关侧不一致或者对等中继模式下网关仍要求认证。解决fs_cli -x sofia status gateway gw_pstn看注册状态401说明认证失败核对username/password和网关侧账号对等模式确认网关侧是否真的关了认证没关就补认证参数或让网关侧加 IP 白名单。5.3 单通能听到对方对方听不到自己现象外呼接通后一方有声一方无声或呼入后主叫听不到 IVR。原因媒体路径没打通常见是ext-rtp-ip/ext-sip-ip没设或设错NAT 环境下 RTP 包发到了内网地址。解决在 profile 里显式设ext-rtp-ip和ext-sip-ip为公网地址fs_cli -x sofia status profile external确认ext-rtp-ip生效抓包看 RTP 是否双向单向就是地址填错。5.4 改完 XML 不生效reloadxml 也没用现象改了dialplan/public.xml或 gateway 定义reloadxml后行为不变。原因reloadxml只重载 XML 注册表gateway 定义变更需要sofia profile external rescan或重启 profile模块增删更要重启进程。解决dialplan 改动用reloadxml即可gateway 改动用fs_cli -x sofia profile external rescanprofile 参数改动用sofia profile external restart模块改动重启进程。5.5 多网关负载时呼叫总走第一条现象配了两条 gateway 做冗余但所有外呼都走第一条第一条挂了也不切。原因bridge的data里多个 gateway 用|分隔时FreeSWITCH 按顺序尝试但第一条返回503后是否继续取决于失败原因和continue_on_fail设置。解决在bridge前设continue_on_failtrue或改用distributor模块做真正的负载简单冗余可以在bridge的 data 里写sofia/gateway/gw1/$1|sofia/gateway/gw2/$1并确认失败码会触发切换。6. 进阶用 dialplan 变量和事件钩子把路由做成可观测的配置能通只是第一步真正上线后要能回答“这通电话为什么走了这条路由”。我的习惯是在 dialplan 里埋变量、在事件里留痕把黑匣子变成可查的链路。具体做法是在 extension 里用set打标记再用fs_cli或 ESL 按变量过滤。extension nameoutbound_pstn_tagged condition fielddestination_number expression^0(\d{7,11})$ !-- 打路由标记便于事后按变量检索 -- action applicationset dataroute_tagpstn_gw1/ action applicationset dataeffective_caller_id_number1001/ action applicationbridge datasofia/gateway/gw_pstn/$1/ /condition /extension逻辑说明route_tag是自定义 channel 变量会随CHANNEL_CREATE等事件带出事后用fs_cli -x show channels或 CDR 里的variable_route_tag就能知道这通走了哪条规则。参数说明变量名不要和系统保留变量冲突前缀加个业务名比较稳如果要多级路由可以在每个bridge前改route_tag的值最后一条生效的就是实际走的那条。验证方法上我一般做两件事一是用originate主动发起测试呼叫不依赖外部网关先验证 dialplan 匹配和变量设置二是订阅CHANNEL_HANGUP事件把Hangup-Cause和route_tag一起打到日志跑一轮回归就能看出哪条路由失败率高。# 主动发起测试呼叫验证 dialplan 匹配和变量 fs_cli -x originate {route_tagtest,origination_caller_id_number1001}sofia/gateway/gw_pstn/013800000000 park() # 订阅挂断事件按 route_tag 过滤失败 fs_cli -x /event plain CHANNEL_HANGUP逻辑说明originate的{}里是 channel 变量park()让呼叫停在 park 状态便于观察不真正接通第二条订阅挂断事件输出里看variable_route_tag和Hangup-Cause的对应关系。参数说明origination_caller_id_number设主叫号码测试时用测试号避免骚扰真实用户park()可以换成playback( silence_stream://2000 )做短时媒体测试。有个血泪教训早期我图省事所有外呼都写在一个 extension 里正则写得很宽结果某次网关调整号码格式后一半外呼匹配到了错误分支排查花了大半天。从那以后我每次改 dialplan 都强制走一遍originate测试加事件订阅确认route_tag和Hangup-Cause对得上才上线。这套习惯比事后抓包省事得多希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

VMware虚拟机去虚拟化实操:硬盘显卡BIOS指纹伪造指南

VMware虚拟机去虚拟化实操:硬盘显卡BIOS指纹伪造指南

简介:本资源是一份面向虚拟化技术学习者与安全测试人员的VMware虚拟机‘去虚拟化’实操指南,聚焦于绕过鲁大师等硬件检测工具的识别机制。内容系统覆盖VMware 16.1.2环境搭建、硬盘/声卡/网卡/显卡参数的十六进制精准修改、自定义BIOS注入(含…

📅 2026/10/24 16:53:11
MATLAB车牌识别完整实战:灰度化、边缘检测与模板匹配全流程解析

MATLAB车牌识别完整实战:灰度化、边缘检测与模板匹配全流程解析

简介:面向MATLAB图像处理学习者和车牌识别初学者的系统论文文档,以车牌识别方法研究为主线,详细覆盖车牌区域提取、字符切割与字符识别三个核心模块,并围绕研究背景、理论概况和系统程序设计展开说明。压缩包内仅包含1个doc文件&a…

📅 2026/10/24 16:53:11
从 IPC 到 PDF 导出:Electron 跨平台 Markdown 编辑器开发实践

从 IPC 到 PDF 导出:Electron 跨平台 Markdown 编辑器开发实践

简介:DBeditor 是面向开发者、技术写作者与前端学习者的跨平台 Markdown 编辑器项目,强调在 Linux、macOS 与 Windows 上保持统一体验,并以简洁扁平、大量留白的界面减少菜单干扰。它适合想了解桌面端编辑器如何组织界面、路由与前端模块的读…

📅 2026/10/24 16:48:11
MORE NEWS

更多资讯

📰

冒险岛WZ编辑工具:支持自定义加密的资源解析框架

简介:这是一款面向《冒险岛》游戏MOD开发者、资源逆向爱好者及客户端定制人员的WZ文件编辑与加密工具集,专为破解、分析和重打包游戏核心资源(如图像、音频、脚本)提供完整支持。资源包共34个文件,含17个DLL动态库&…

📰

JDK 1.7.0_03:工控与遗留系统不可替代的JVM底座

简介:本资源为Java 7开发环境标准安装包,面向Java初学者、教学实验人员及需兼容旧版JDK的开发者,解决无管理员权限或快速部署Java开发环境的痛点。压缩包内含完整JDK 1.7.0_03(含JRE),无需安装,…

📰

algs4编程作业全解析:从并查集到动态规划,附避坑指南

简介:普林斯顿大学《算法》课程编程作业的Java解答集,面向正在学习算法与数据结构、渴望通过实际编码提升能力的开发者与自学者。这套解答完整覆盖课程中多道经典作业,帮助读者深入理解算法设计思路、数据结构选型与代码实现细节。压缩包共20…

📰

ITU-T G.959.1光接口标准:跨域互联的物理层基石

简介:ITU-T G.959.1-2018 是国际电信联盟(ITU-T)发布的光传送网(OTN)物理层接口核心标准,面向光通信系统工程师、传输网络架构师及标准化研究人员,用于规范跨管理域的光接口互操作性&#xff0c…

📰

TypeScript 教程:从类型系统到工程化实践的完整学习路径

简介:TypeScript教程以PDF文档形式呈现,系统梳理了TypeScript类型系统的核心知识点,从布尔、数字、字符串、数组、元组等基础数据类型,到枚举、接口、类的进阶用法均有覆盖,同时讲解任意值、空值等特有概念&#xff0c…

📰

Python核心概念解析:可变性、无序性与对象模型

简介:本资源是南开大学软件学院Python课程期末复习的系统性整理笔记,面向计算机相关专业本科生及Python初学者,聚焦核心考点与易错难点,助力高效备考与知识体系构建。内容覆盖数据结构(字典、集合、元组、列表的特性与…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬