From 4faddeca155461ca43d759b630f9ce08eace545c Mon Sep 17 00:00:00 2001 From: jack ning Date: Tue, 21 Oct 2025 14:55:06 +0800 Subject: [PATCH] Update post-commit --- deploy/kamailio/dispatcher.list | 3 + deploy/kamailio/kamailio-local.cfg | 79 +++++ deploy/kamailio/kamailio-setup.md | 214 +++++++++++++ deploy/kamailio/kamailio.cfg | 89 ++++++ deploy/kamailio/kamctlrc | 168 ++++++++++ deploy/kamailio/readme.md | 479 +++++++++++++++++++++++++++++ 6 files changed, 1032 insertions(+) create mode 100644 deploy/kamailio/dispatcher.list create mode 100644 deploy/kamailio/kamailio-local.cfg create mode 100644 deploy/kamailio/kamailio-setup.md create mode 100644 deploy/kamailio/kamailio.cfg create mode 100644 deploy/kamailio/kamctlrc create mode 100644 deploy/kamailio/readme.md diff --git a/deploy/kamailio/dispatcher.list b/deploy/kamailio/dispatcher.list new file mode 100644 index 0000000000..84ba9fccf0 --- /dev/null +++ b/deploy/kamailio/dispatcher.list @@ -0,0 +1,3 @@ +1 sip:14.103.165.199:5060;transport=udp +2 sip:14.103.165.199:5060;transport=tcp +3 sip:14.103.165.199:5080;transport=tcp diff --git a/deploy/kamailio/kamailio-local.cfg b/deploy/kamailio/kamailio-local.cfg new file mode 100644 index 0000000000..f933e6bcae --- /dev/null +++ b/deploy/kamailio/kamailio-local.cfg @@ -0,0 +1,79 @@ +#!define WITH_NAT + +#!substdef "!MY_PUBLIC_IP!124.220.58.234!g" +#!substdef "!DISPATCHER_LIST!/etc/kamailio/dispatcher.list!g" + +listen=udp:0.0.0.0:5060 advertise MY_PUBLIC_IP:5060 +alias="sip.weiyuai.cn" + +mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +loadmodule "sl.so" +loadmodule "tm.so" +loadmodule "rr.so" +loadmodule "maxfwd.so" +loadmodule "sanity.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "pv.so" +loadmodule "xlog.so" +loadmodule "dispatcher.so" +loadmodule "nathelper.so" + +modparam("dispatcher", "list_file", "DISPATCHER_LIST") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "dst_avp", "$avp(dsdst)") +modparam("dispatcher", "cnt_avp", "$avp(dscnt)") + +modparam("rr", "enable_full_lr", 1) +modparam("rr", "append_fromtag", 0) + +modparam("tm", "fr_timer", 3000) +modparam("tm", "fr_inv_timer", 90000) + +# NAT helper +modparam("nathelper", "received_avp", "$avp(rcv)" +) + +route[DISPATCH] { + if(!ds_select_dst(1, 0)) { + send_reply(500, "No Upstream"); + exit; + } + t_on_reply("NAT_REPLY"); + t_relay(); + exit; +} + +onreply_route[NAT_REPLY] { + # Fix nat on replies + if(isflagset(FLT_NATS)) { + fix_nated_contact(); + } +} + +request_route { + if (!mf_process_maxfwd(10)) { + send_reply(483, "Too Many Hops"); + exit; + } + if (!sanity_check("1511", "7")) { + send_reply(400, "Bad Request"); + exit; + } + + # NAT handling + force_rport(); + if (nat_uac_test(19)) { + setflag(FLT_NATS); + fix_nated_contact(); + } + + if (is_method("OPTIONS") && ($ru == "sip:sip.weiyuai.cn" || $rU == "")) { + send_reply(200, "OK"); + exit; + } + + record_route(); + route(DISPATCH); +} diff --git a/deploy/kamailio/kamailio-setup.md b/deploy/kamailio/kamailio-setup.md new file mode 100644 index 0000000000..f077ece860 --- /dev/null +++ b/deploy/kamailio/kamailio-setup.md @@ -0,0 +1,214 @@ +# Kamailio 部署与配置指南(反代 FreeSWITCH 的 5060/UDP) + +本文档指导你将 Nginx 的 5060/UDP 转发切换为由 Kamailio 负责的专业 SIP 代理,以解决 UDP/NAT 回包路径问题。Nginx 继续用于 HTTP/WS/WSS(例如 WSS 到 FreeSWITCH)。 + +适用环境 +- OS: Ubuntu 24.04(命令对 Debian/Ubuntu 通用) +- 公网 IP(Kamailio):`124.220.58.234` +- FreeSWITCH 公网 IP:`14.103.165.199` +- SIP 域名:`sip.weiyuai.cn` +- 协议/端口:SIP/UDP 5060 + +> 若你的实际 IP/域名不同,请将文档中的示例值替换为你的真实值。 + +--- + +## 1. 释放 Nginx 的 5060/UDP(如果之前由 Nginx 代理) + +1) 编辑 `/etc/nginx/nginx.conf`,删除 `stream {}` 内监听 5060/udp 的 server 段。 +2) 验证并重载: + +```bash +sudo nginx -t && sudo systemctl reload nginx +sudo ss -lunp | grep -E '(:5060\s)' || echo "no udp:5060 listener" +``` + +--- + +## 2. 安装 Kamailio 与必要模块 + +```bash +# 若存在无效的第三方源导致 apt update 失败,先禁用(示例) +# sudo mv /etc/apt/sources.list.d/mysql.list /etc/apt/sources.list.d/mysql.list.disabled || true + +sudo apt-get update +sudo DEBIAN_FRONTEND=noninteractive apt-get install -y kamailio kamailio-extra-modules +``` + +安装完成后,系统会创建 systemd 服务 `kamailio.service`。 + +--- + +## 3. 配置 Kamailio(最小可用代理到 FreeSWITCH) + +三个关键点: +- Kamailio 监听 0.0.0.0:5060,并 advertise 公网 IP,确保 Via/Record-Route 对外可用 +- 转发所有 SIP 请求到 FreeSWITCH:`14.103.165.199:5060` +- 基础 NAT 处理:`force_rport` 与 `fix_nated_contact` + +### 3.1 上游列表 `/etc/kamailio/dispatcher.list` + +```bash +sudo tee /etc/kamailio/dispatcher.list >/dev/null <<'EOF' +1 sip:14.103.165.199:5060 +EOF +``` + +### 3.2 主配置 `/etc/kamailio/kamailio.cfg` + +如下为最小、可直接使用的配置。若该文件已有内容,建议先备份再覆盖。 + +```bash +sudo tee /etc/kamailio/kamailio.cfg >/dev/null <<'EOF' +#!KAMAILIO + +debug=2 +log_stderror=no +children=4 +enable_sctp=no + +listen=udp:0.0.0.0:5060 advertise 124.220.58.234:5060 +alias="sip.weiyuai.cn" + +mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +# Modules +loadmodule "sl.so" +loadmodule "tm.so" +loadmodule "rr.so" +loadmodule "sanity.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "pv.so" +loadmodule "xlog.so" +loadmodule "dispatcher.so" +loadmodule "nathelper.so" + +# Module params +modparam("rr", "enable_full_lr", 1) +modparam("rr", "append_fromtag", 0) + +modparam("tm", "fr_timer", 30000) +modparam("tm", "fr_inv_timer", 120000) + +modparam("sanity", "autodrop", 0) + +modparam("dispatcher", "list_file", "/etc/kamailio/dispatcher.list") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "ds_probing_mode", 1) + +modparam("nathelper", "received_avp", "$avp(rcv)") + +route[DISPATCH] { + if(!ds_select_dst(1, 0)) { + send_reply(500, "No Upstream"); + exit; + } + t_on_reply("NAT_REPLY"); + if(!t_relay()) { + sl_reply_error(); + } + exit; +} + +onreply_route[NAT_REPLY] { + if(isflagset(5)) { + fix_nated_contact(); + } +} + +request_route { + if (!sanity_check("1511", "7")) { + send_reply(400, "Bad Request"); + exit; + } + + # Basic NAT handling + force_rport(); + if (nat_uac_test(19)) { + setflag(5); + fix_nated_contact(); + } + + # Stay in the signaling path + record_route(); + + route(DISPATCH); +} +EOF +``` + +> 如 FreeSWITCH 实际对外监听为 `5080/udp`,请将 dispatcher.list 中的端口改为 5080。 + +--- + +## 4. 启动与验证 + +```bash +# 语法检查 +sudo kamailio -c -f /etc/kamailio/kamailio.cfg + +# 启动服务 +sudo systemctl enable --now kamailio +sudo systemctl status --no-pager -l kamailio + +# 确认监听 5060/udp +sudo ss -lunp | grep -E '(:5060\s)' || true +``` + +### 4.1 本机快速测试(OPTIONS) + +```bash +printf 'OPTIONS sip:weiyuai.cn SIP/2.0\r\nVia: SIP/2.0/UDP 124.220.58.234:5060;branch=z9hG4bK-9999;rport\r\nMax-Forwards: 70\r\nFrom: ;tag=9999\r\nTo: \r\nCall-ID: 9999@sip.weiyuai.cn\r\nCSeq: 1 OPTIONS\r\nContact: \r\nContent-Length: 0\r\n\r\n' | nc -u -w2 124.220.58.234 5060 | sed -n '1,80p' +``` + +如果看到 `SIP/2.0 200 OK` 且 `Record-Route` 中包含 Kamailio(公网/内网地址),说明路径正常。 + +--- + +## 5. 需要同时检查的外部条件 + +- 云安全组/防火墙: + - Kamailio 机(124.220.58.234)入站放行 UDP/5060 + - FreeSWITCH 机(14.103.165.199)入站允许来自 124.220.58.234 的 UDP/5060 +- FreeSWITCH: + - external_sip_ip 与 external_rtp_ip 设置为 14.103.165.199(公网) + - 外部 profile 监听端口确认与上游一致(5060 或 5080) + - ACL 允许 124.220.58.234 +- 客户端: + - 注册到 `sip:用户名@sip.weiyuai.cn:5060`,失败时抓包对照 Kamailio/FreeSWITCH 日志 + +--- + +## 6. 常见问题排查 + +- `config file ok` 但服务起不来: + - `journalctl -xeu kamailio` 查看错误详细 +- 返回 4xx/5xx 或无回包: + - Kamailio:`journalctl -u kamailio -f` + - FreeSWITCH 日志:检查是否收到请求、是否 ACL 拒绝 + - 核对安全组/端口是否放通 +- Via/Contact 显示内网地址: + - 确保 Kamailio 配置了 `advertise 公网IP` + - FreeSWITCH external_sip_ip/external_rtp_ip 设置是否正确 + +--- + +## 7. 回滚方案(改回直连 FreeSWITCH) + +- 将 DNS A 记录 `sip.weiyuai.cn` 指向 `14.103.165.199` +- 在 14.103.165.199 放行 UDP/5060(或 5080) +- 关闭 Kamailio:`sudo systemctl disable --now kamailio` + +--- + +## 8. 进阶建议(可选) + +- 负载均衡/高可用:在 `/etc/kamailio/dispatcher.list` 中加入多台 FreeSWITCH,设置失败转移与探测 +- 抗扫描/限速:启用 `pike` 与 `htable`,对异常源做封禁 +- 媒体穿透:如遇复杂 NAT,考虑配合 TURN/ICE,或引入 `rtpengine`(或 `rtpproxy`) +- 安全:限制来源网段、TLS/SIPS、对注册/呼叫做鉴权策略 + +--- + +完成后,请用外网软电话进行注册与呼叫测试;若需要,我可根据你的现网参数进一步完善配置(例如:5080/udp、多上游、SIP 头策略、限速等)。 diff --git a/deploy/kamailio/kamailio.cfg b/deploy/kamailio/kamailio.cfg new file mode 100644 index 0000000000..b490568cc9 --- /dev/null +++ b/deploy/kamailio/kamailio.cfg @@ -0,0 +1,89 @@ +#!KAMAILIO + +debug=2 +log_stderror=no +children=4 +enable_sctp=no + +listen=udp:0.0.0.0:5060 advertise 124.220.58.234:5060 +# Enable TCP listeners for SIP on 5060 and external TCP on 5080 +listen=tcp:0.0.0.0:5060 advertise 124.220.58.234:5060 +listen=tcp:0.0.0.0:5080 advertise 124.220.58.234:5080 +alias="sip.weiyuai.cn" + +mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +# Modules (tm must be loaded before modules depending on it) +loadmodule "tm.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "sanity.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "pv.so" +loadmodule "xlog.so" +loadmodule "dispatcher.so" +loadmodule "nathelper.so" + +# Module params +modparam("rr", "enable_full_lr", 1) +modparam("rr", "append_fromtag", 0) + +modparam("tm", "fr_timer", 30000) +modparam("tm", "fr_inv_timer", 120000) + +modparam("sanity", "autodrop", 0) + +modparam("dispatcher", "list_file", "/etc/kamailio/dispatcher.list") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "ds_probing_mode", 1) + +modparam("nathelper", "received_avp", "$avp(rcv)") + +route[DISPATCH] { + # Select upstream set based on received transport and port + if ($proto == "udp" && $Rp == 5060) { + if(!ds_select_dst(1, 0)) { send_reply(500, "No Upstream UDP5060"); exit; } + } else if ($proto == "tcp" && $Rp == 5060) { + if(!ds_select_dst(2, 0)) { send_reply(500, "No Upstream TCP5060"); exit; } + } else if ($proto == "tcp" && $Rp == 5080) { + if(!ds_select_dst(3, 0)) { send_reply(500, "No Upstream TCP5080"); exit; } + } else { + if(!ds_select_dst(1, 0)) { send_reply(500, "No Upstream"); exit; } + } + t_on_reply("NAT_REPLY"); + if(!t_relay()) { + sl_reply_error(); + } + exit; +} + +onreply_route[NAT_REPLY] { + if (isflagset(5)) { + # Only attempt to fix Contact on provisional/success replies that actually carry Contact + if ($rs >= 100 && $rs < 300 && is_present_hf("Contact")) { + fix_nated_contact(); + } + } +} + +request_route { + if (!sanity_check("1511", "7")) { + send_reply(400, "Bad Request"); + exit; + } + + # Basic NAT handling + force_rport(); + if (nat_uac_test(19)) { + setflag(5); + if (is_present_hf("Contact")) { + fix_nated_contact(); + } + } + + # Stay in the signaling path + record_route(); + + route(DISPATCH); +} diff --git a/deploy/kamailio/kamctlrc b/deploy/kamailio/kamctlrc new file mode 100644 index 0000000000..ce0bd9d93b --- /dev/null +++ b/deploy/kamailio/kamctlrc @@ -0,0 +1,168 @@ +## The Kamailio configuration file for the control tools. +## +## Here you can set variables used in the kamctl and kamdbctl setup +## scripts. Per default all variables here are commented out, the control tools +## will use their internal default values. + +## the SIP domain +# SIP_DOMAIN=kamailio.org + +## chrooted directory +# CHROOT_DIR="/path/to/chrooted/directory" + +## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE +## by default none is loaded +## +## If you want to setup a database with kamdbctl, you must at least specify +## this parameter. +# DBENGINE=MYSQL + +## database host +# DBHOST=localhost + +## database port +# DBPORT=3306 + +## database name (for ORACLE this is TNS name) +# DBNAME=kamailio + +## database path used by dbtext, db_berkeley or sqlite +# DB_PATH="/usr/local/etc/kamailio/dbtext" + +## database read/write user +# DBRWUSER="kamailio" + +## password for database read/write user +# DBRWPW="kamailiorw" + +## database read only user +# DBROUSER="kamailioro" + +## password for database read only user +# DBROPW="kamailioro" + +## database access host (from where is kamctl used) +# DBACCESSHOST=192.168.0.1 + +## database super user (for ORACLE this is 'scheme-creator' user) +# DBROOTUSER="root" + +## password for database super user +## - important: this is insecure, targeting the use only for automatic testing +## - known to work for: mysql +# DBROOTPW="dbrootpw" + +## option to ask confirmation for all database creation steps +# DBINITASK=yes + +## database character set (used by MySQL when creating database) +#CHARSET="latin1" + +## user name column +# USERCOL="username" + + +## SQL definitions +## If you change this definitions here, then you must change them +## in db/schema/entities.xml too. +## FIXME + +# FOREVER="2030-05-28 21:32:15" +# DEFAULT_Q="1.0" + + +## Program to calculate a message-digest fingerprint +# MD5="md5sum" + +## awk tool +# AWK="awk" + +## gdb tool +# GDB="gdb" + +## If you use a system with a grep and egrep that is not 100% gnu grep compatible, +## e.g. solaris, install the gnu grep (ggrep) and specify this below. +## +## grep tool +# GREP="grep" + +## egrep tool +# EGREP="egrep" + +## sed tool +# SED="sed" + +## tail tool +# LAST_LINE="tail -n 1" + +## expr tool +# EXPR="expr" + + +## Describe what additional tables to install. Valid values for the variables +## below are yes/no/ask. With ask (default) it will interactively ask the user +## for an answer, while yes/no allow for automated, unassisted installs. + +## If to install tables for the modules in the EXTRA_MODULES variable. +# INSTALL_EXTRA_TABLES=ask + +## If to install presence related tables. +# INSTALL_PRESENCE_TABLES=ask + +## If to install uid modules related tables. +# INSTALL_DBUID_TABLES=ask + +## Define what module tables should be installed. +## If you use the postgres database and want to change the installed tables, then you +## must also adjust the STANDARD_TABLES or EXTRA_TABLES variable accordingly in the +## kamdbctl.base script. + +## Kamailio standard modules +# STANDARD_MODULES="standard acc lcr domain group permissions registrar usrloc msilo +# alias_db uri_db speeddial avpops auth_db pdt dialog dispatcher +# dialplan" + +## Kamailio extra modules +# EXTRA_MODULES="imc cpl siptrace domainpolicy carrierroute userblocklist htable purple sca" + + +## type of aliases used: DB - database aliases; UL - usrloc aliases +## - default: none +# ALIASES_TYPE="DB" + +## control engine: RPCFIFO +## - default RPCFIFO +# CTLENGINE="RPCFIFO" + +## path to FIFO file for engine RPCFIFO +# RPCFIFOPATH="/run/kamailio/kamailio_rpc.fifo" + +## check ACL names; default on (1); off (0) +# VERIFY_ACL=1 + +## ACL names - if VERIFY_ACL is set, only the ACL names from below list +## are accepted +# ACL_GROUPS="local ld int voicemail free-pstn" + +## check if user exists (used by some commands such as acl); +## - default on (1); off (0) +# VERIFY_USER=1 + +## verbose - debug purposes - default '0' +# VERBOSE=1 + +## do (1) or don't (0) store plaintext passwords +## in the subscriber table - default '1' +# STORE_PLAINTEXT_PW=0 + +## Kamailio START Options +## PID file path - default is: /run/kamailio/kamailio.pid +# PID_FILE=/run/kamailio/kamailio.pid + +## Kamailio Startup Configuration File +## Default is: kamailio.cfg +# STARTUP_CONFIG_FILE=kamailio.cfg + +## Extra start options - default is: not set +## example: start Kamailio with 64MB shared memory: STARTOPTIONS="-m 64" +# STARTOPTIONS= diff --git a/deploy/kamailio/readme.md b/deploy/kamailio/readme.md new file mode 100644 index 0000000000..b80ea3c23d --- /dev/null +++ b/deploy/kamailio/readme.md @@ -0,0 +1,479 @@ +# Kamailio + +专业的 SIP 代理,处理 SIP 的 Via/Record-Route、rport、NAT 以及会话路由 +使用 Nginx 继续处理 HTTP/WS/WSS 反向代理 + +## 架构说明 + +- **Kamailio**: 专业 SIP 代理服务器,负责 SIP 信令路由、NAT 穿透、会话管理 +- **Nginx**: 反向代理,负责 HTTP/WebSocket(WS/WSS) 的代理和 TLS 终结 +- **FreeSWITCH**: 后端媒体服务器,处理实际的语音/视频通话 + +## 安装 + +### Ubuntu/Debian 系统安装步骤 + +#### 1. 添加 Kamailio 官方仓库 + +```bash +# 更新系统包列表 +sudo apt update + +# 安装必要的工具 +sudo apt install -y gnupg2 wget + +# 添加 Kamailio 官方 GPG 密钥 +wget -O- https://deb.kamailio.org/kamailiodebkey.gpg | sudo apt-key add - + +# 添加 Kamailio 仓库(以 Ubuntu 22.04 为例) +# 注意:根据你的系统版本选择对应的代号(jammy/focal/bullseye等) +echo "deb http://deb.kamailio.org/kamailio57 jammy main" | sudo tee /etc/apt/sources.list.d/kamailio.list + +# 更新包列表 +sudo apt update +``` + +**常见系统代号:** +- Ubuntu 22.04 LTS: `jammy` +- Ubuntu 20.04 LTS: `focal` +- Debian 11: `bullseye` +- Debian 10: `buster` + +#### 2. 安装 Kamailio 及必要模块 + +```bash +# 安装 Kamailio 核心包 +sudo apt install -y kamailio + +# 安装 WebSocket 支持模块 +sudo apt install -y kamailio-websocket-modules + +# 安装 TLS/SSL 支持模块 +sudo apt install -y kamailio-tls-modules + +# 安装 JSON 和 HTTP 模块(可选,用于 API 集成) +sudo apt install -y kamailio-json-modules kamailio-http-modules + +# 安装 MySQL/PostgreSQL 模块(如需数据库支持) +sudo apt install -y kamailio-mysql-modules +# 或 +# sudo apt install -y kamailio-postgres-modules + +# 安装额外的实用模块 +sudo apt install -y kamailio-extra-modules +``` + +#### 3. 验证安装 + +```bash +# 查看 Kamailio 版本 +kamailio -v + +# 检查已安装的模块 +ls /usr/lib/x86_64-linux-gnu/kamailio/modules/ + +# 检查服务状态 +sudo systemctl status kamailio +``` + +#### 4. 启用开机自启 + +```bash +# 启用 Kamailio 开机自启 +sudo systemctl enable kamailio + +# 启动 Kamailio +sudo systemctl start kamailio + +# 重启 Kamailio +sudo systemctl restart kamailio + +# 停止 Kamailio +sudo systemctl stop kamailio +``` + +## 配置 + +### 配置文件位置 + +- **主配置文件**: `/etc/kamailio/kamailio.cfg` +- **本地配置**: `/etc/kamailio/kamailio-local.cfg` (可选,用于本地化配置) +- **TLS 配置**: `/etc/kamailio/tls.cfg` +- **默认配置**: `/etc/default/kamailio` + +### 1. 基础配置 (`/etc/default/kamailio`) + +```bash +# 编辑默认配置 +sudo nano /etc/default/kamailio +``` + +```bash +# 启用 Kamailio +RUN_KAMAILIO=yes + +# 配置文件路径 +CFGFILE=/etc/kamailio/kamailio.cfg + +# 运行用户 +USER=kamailio +GROUP=kamailio + +# SIP UDP 端口 +SIP_UDP_PORT=5060 + +# SIP TCP 端口 +SIP_TCP_PORT=5060 + +# SIP TLS 端口 +SIP_TLS_PORT=5061 + +# 监听地址(留空表示监听所有接口) +SIP_LISTEN_ADDR= + +# 日志级别 (0=ALERT, 1=CRIT, 2=ERR, 3=WARN, 4=NOTICE, 5=INFO, 6=DEBUG) +LOG_LEVEL=3 + +# 内存大小 +MEMORY=64 +``` + +### 2. 主配置文件 (`/etc/kamailio/kamailio.cfg`) + +创建或编辑主配置文件: + +```bash +sudo cp /etc/kamailio/kamailio.cfg /etc/kamailio/kamailio.cfg.bak +sudo nano /etc/kamailio/kamailio.cfg +``` + +```cfg +#!KAMAILIO + +####### Global Parameters ######### + +### 日志配置 +debug=3 +log_stderror=no +memdbg=5 +memlog=5 +log_facility=LOG_LOCAL0 +fork=yes +children=4 + +### 网络配置 +# 替换为你的实际公网 IP +#!define PUBLICIP "14.103.165.199" +#!substdef "!PUBLICIP!14.103.165.199!g" + +# 本地 IP(内网 IP,如果没有 NAT 则与 PUBLICIP 相同) +#!define LOCALIP "127.0.0.1" + +# FreeSWITCH 地址 +#!define FREESWITCH_IP "14.103.165.199" +#!define FREESWITCH_PORT 5080 + +### 监听配置 +# SIP UDP +listen=udp:0.0.0.0:5060 + +# SIP TCP +listen=tcp:0.0.0.0:5060 + +# SIP TLS (如需要) +# listen=tls:0.0.0.0:5061 + +### 协议配置 +disable_tcp=no +enable_tls=no +tcp_connection_lifetime=3605 +tcp_accept_no_cl=yes +tcp_rd_buf_size=16384 + +### DNS 配置 +dns=no +rev_dns=no +dns_try_ipv6=no + +### 别名配置 +# 替换为你的实际域名 +alias="sip.weiyuai.cn" +alias="weiyuai.cn" + +####### 模块加载 ######### + +loadmodule "jsonrpcs.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +loadmodule "nathelper.so" +loadmodule "rtpproxy.so" + +####### 模块参数 ######### + +### jsonrpcs 参数 +modparam("jsonrpcs", "pretty_format", 1) + +### tm 参数 +modparam("tm", "failure_reply_mode", 3) +modparam("tm", "fr_timer", 30000) +modparam("tm", "fr_inv_timer", 120000) + +### rr 参数 +modparam("rr", "enable_full_lr", 1) +modparam("rr", "append_fromtag", 1) + +### nathelper 参数 +modparam("nathelper", "natping_interval", 30) +modparam("nathelper", "ping_nated_only", 1) +modparam("nathelper", "sipping_bflag", 7) +modparam("nathelper", "sipping_from", "sip:pinger@weiyuai.cn") + +### rtpproxy 参数 (如果使用 RTPProxy) +# modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:22222") + +####### 路由逻辑 ######### + +# 主请求路由 +request_route { + # 基本的防洪和安全检查 + route(REQINIT); + + # NAT 检测 + route(NATDETECT); + + # 处理 OPTIONS (心跳检测) + if (is_method("OPTIONS")) { + sl_send_reply("200", "OK"); + exit; + } + + # 记录路由处理 + if (is_method("INVITE|SUBSCRIBE")) { + record_route(); + } + + # 转发到 FreeSWITCH + route(FREESWITCH); +} + +# 初始化检查路由 +route[REQINIT] { + # 检查最大转发次数 + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483", "Too Many Hops"); + exit; + } + + # 基本的 SIP 消息合法性检查 + if (!sanity_check("1511", "7")) { + xlog("L_WARN", "Malformed SIP message from $si:$sp\n"); + exit; + } +} + +# NAT 检测路由 +route[NATDETECT] { + force_rport(); + + if (nat_uac_test("19")) { + if (is_method("REGISTER")) { + fix_nated_register(); + } else { + if (is_first_hop()) { + set_contact_alias(); + } + } + setflag(5); # NAT flag + } +} + +# FreeSWITCH 转发路由 +route[FREESWITCH] { + # 设置目标为 FreeSWITCH + $du = "sip:" + FREESWITCH_IP + ":" + FREESWITCH_PORT; + + # 添加日志 + xlog("L_INFO", "Forwarding $rm from $fu to FreeSWITCH: $du\n"); + + # NAT 处理 + if (isflagset(5)) { + if (is_method("INVITE")) { + # 如果使用 RTPProxy,取消注释下面这行 + # rtpproxy_offer(); + } + } + + # 转发请求 + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# 应答路由 +onreply_route { + # NAT 处理 + if (isflagset(5)) { + if (is_method("INVITE")) { + # 如果使用 RTPProxy,取消注释下面这行 + # rtpproxy_answer(); + } + handle_rport_n_received(); + } + + xlog("L_INFO", "Reply $rs $rr from $si:$sp\n"); +} + +# 失败路由 +failure_route { + if (t_is_canceled()) { + exit; + } + + xlog("L_INFO", "Failure route triggered: $rm from $fu\n"); +} +``` + +### 3. TLS 配置(可选,如需支持 SIPS) + +编辑 `/etc/kamailio/tls.cfg`: + +```bash +sudo nano /etc/kamailio/tls.cfg +``` + +```cfg +[server:default] +method = TLSv1.2+ +verify_certificate = no +require_certificate = no +private_key = /etc/letsencrypt/live/weiyuai.cn/privkey.pem +certificate = /etc/letsencrypt/live/weiyuai.cn/fullchain.pem +``` + +### 4. 配置检查和启动 + +```bash +# 检查配置文件语法 +sudo kamailio -c -f /etc/kamailio/kamailio.cfg + +# 如果没有错误,重启服务 +sudo systemctl restart kamailio + +# 查看日志 +sudo tail -f /var/log/syslog | grep kamailio + +# 或者使用 journalctl +sudo journalctl -u kamailio -f +``` + +### 5. 防火墙配置 + +```bash +# 开放 SIP 端口 +sudo ufw allow 5060/udp comment 'Kamailio SIP UDP' +sudo ufw allow 5060/tcp comment 'Kamailio SIP TCP' +sudo ufw allow 5061/tcp comment 'Kamailio SIP TLS' + +# 如果使用 RTPProxy,还需要开放 RTP 端口范围 +# sudo ufw allow 10000:20000/udp comment 'RTP Media' + +# 重载防火墙 +sudo ufw reload + +# 查看防火墙状态 +sudo ufw status +``` + +## 与 Nginx 的集成架构 + +### 请求流程 + +1. **WebSocket 客户端 (浏览器)** → `wss://sip.weiyuai.cn/ws` +2. **Nginx (443)** → TLS 终结,转发 WebSocket → **FreeSWITCH (7443/5066)** +3. **FreeSWITCH** ← SIP 信令 → **Kamailio (5060)** → NAT 穿透、路由 +4. **Kamailio** ← SIP 信令 → **其他 SIP 端点** (外部 SIP 客户端、运营商等) + +### 工作原理 + +- **WebSocket 流量**: Nginx 处理 WS/WSS,直接转发到 FreeSWITCH +- **SIP 信令流量**: Kamailio 处理 UDP/TCP/TLS SIP,负责路由和 NAT +- **媒体流量 (RTP)**: 直接在 FreeSWITCH 和客户端之间传输,或通过 TURN/coturn + +## 测试和验证 + +### 1. 测试 Kamailio SIP 端口 + +```bash +# 使用 netcat 测试 UDP 端口 +nc -u -v 14.103.165.199 5060 + +# 测试 TCP 端口 +nc -v 14.103.165.199 5060 + +# 使用 sipsak 工具测试(需要安装) +sudo apt install -y sipsak +sipsak -v -s sip:14.103.165.199:5060 +``` + +### 2. 查看 Kamailio 统计信息 + +```bash +# 使用 kamctl 工具 +sudo kamctl stats + +# 查看活动连接 +sudo kamctl fifo get_statistics all + +# 查看内存使用 +sudo kamctl fifo get_statistics shmem: +``` + +### 3. 调试模式 + +```bash +# 临时提高日志级别到 DEBUG +sudo kamcmd cfg.set_now_int core debug 6 + +# 恢复默认级别 +sudo kamcmd cfg.set_now_int core debug 3 +``` + +## 常见问题 + +### 1. Kamailio 无法启动 + +- 检查配置文件语法: `kamailio -c` +- 查看详细错误日志: `journalctl -u kamailio -n 100` +- 确认端口未被占用: `netstat -tuln | grep 5060` + +### 2. NAT 穿透问题 + +- 确保 `nathelper` 模块已加载 +- 配置正确的公网 IP (`PUBLICIP`) +- 考虑使用 RTPProxy 或 TURN 服务器处理 RTP + +### 3. FreeSWITCH 连接问题 + +- 检查 FreeSWITCH 的 ACL 配置,允许 Kamailio IP +- 确认 FreeSWITCH 监听正确的端口 (5080) +- 查看 FreeSWITCH 日志: `fs_cli -x "console loglevel debug"` + +## 参考资源 + +- [Kamailio 官方文档](https://www.kamailio.org/docs/) +- [Kamailio Wiki](https://www.kamailio.org/wiki/) +- [FreeSWITCH + Kamailio 集成指南](https://freeswitch.org/confluence/display/FREESWITCH/Kamailio) +- [NAT 穿透最佳实践](https://www.kamailio.org/docs/modules/stable/modules/nathelper.html)