openSIPS 4.0 Docker Compose 部署指南

面向用 Docker Compose 托管 SIP 路由服务的运维工程师,基于官方 `opensips/opensips:4.0` 镜像完成 openSIPS 4.0 的容器化部署——覆盖镜像认知、配置文件导出、compose 编排、监听地址与 alias 两次连通性排障、TCP 传输启用、MI 健康检查验证与生命周期运维,全部命令与回显均为实测。

openSIPSopenSIPSSIPVoIPUbuntu 22.042026/10/26

openSIPS 4.0 Docker Compose 部署指南

目标:面向用 Docker Compose 托管 SIP 路由服务的运维工程师,基于官方 opensips/opensips:4.0 镜像完成 openSIPS 4.0 的容器化部署——覆盖镜像认知、配置文件导出、compose 编排、监听地址与 alias 两次连通性排障、TCP 传输启用、MI 健康检查验证与生命周期运维,全部命令与回显均为实测。

一、环境信息

本章列出本次部署实测所用的环境信息,后续章节的全部命令与回显均基于该环境,读者在同等环境下操作应得到一致的输出。

项目取值
宿主机操作系统Ubuntu 26.04.1 LTS
Docker 引擎29.9.2
Docker Composev5.6.1
镜像opensips/opensips:4.0(拉取时对应 4.0.2)
镜像 digestsha256:8cde1548466b3a9f7637c91ff299a8d959c6c6953a8cd68deb391753324f702b
Compose 项目名opensips-4-0-stack
容器名opensips-40-b2-app
自定义网络opensips-b2-net(10.89.66.0/24,容器固定 IP 10.89.66.10)
发布端口5060/udp、5060/tcp
SIP 探测客户端10.89.62.4(预装 sipsak 0.9.8.1,与宿主机同处一个内网)
客户端眼中的宿主机地址10.89.62.1(探测目标,端口经 Docker 发布)

为什么用 Compose 部署 SIP 服务器、openSIPS 4.0 与裸机安装的取舍,已在 《openSIPS 4.0 介绍与选型指南》中展开;裸机(APT 仓库)安装路径见《Ubuntu 22.04 安装 openSIPS 4.0 指南》。本篇专注容器化形态。

二、官方镜像认知

2.1 拉取镜像

官方镜像发布在 Docker Hub 的 opensips/opensips 仓库下,4.0 tag 跟踪 4.0 稳定线的最新小版本:

docker pull opensips/opensips:4.0
5cc1d736fbd1: Pull complete
1a0b9e10e8a6: Pull complete
Digest: sha256:8cde1548466b3a9f7637c91ff299a8d959c6c6953a8cd68deb391753324f702b
Status: Downloaded newer image for opensips/opensips:4.0
docker.io/opensips/opensips:4.0

(输出节选,实测尾部)4.0 是一个浮动 tag,当前指向 4.0.2。生产环境若要求镜像内容不可变,建议在 compose 中按 digest 固定(opensips/opensips@sha256:8cde15…f702b)。

2.2 入口点与前台运行

用 docker inspect 查看镜像的入口点与暴露端口定义:

docker inspect opensips/opensips:4.0 --format 'Entrypoint: {{json .Config.Entrypoint}} | Cmd: {{json .Config.Cmd}} | ExposedPorts: {{json .Config.ExposedPorts}}'
Entrypoint: ["/usr/sbin/opensips","-F"] | Cmd: null | ExposedPorts: {"5060/udp":{}} | Env: ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","DEBIAN_FRONTEND=noninteractive","OPENSIPS_CLI_ENV=true"]

三点解读:

  1. Entrypoint 是 /usr/sbin/opensips -F:-F 表示前台运行,这是容器化服务的标准姿势——进程退了容器就退,Docker 负责守护;
  2. Cmd 为 null:镜像不接受默认参数,所有行为由 /etc/opensips/opensips.cfg 决定;
  3. 声明暴露的端口只有 5060/udp:TCP/TLS 传输需要在配置里另行启用(第六章)。

镜像内二进制与 APT 仓库同源,确认版本:

docker run --rm --entrypoint opensips opensips/opensips:4.0 -V
version: opensips 4.0.2 (x86_64/linux)
flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, F_PARALLEL_MALLOC, DBG_MALLOC, FAST_LOCK-ADAPTIVE_WAIT

2.3 镜像内置工具与默认配置

由于入口点占用,进入镜像执行其他命令必须显式覆盖入口点:

docker run --rm --entrypoint sh opensips/opensips:4.0 -c 'which opensipsctl opensips-cli opensips-mi osipsconfig'
/usr/bin/opensips-cli
/usr/bin/opensips-mi
/usr/sbin/osipsconfig

注意 which 对不存在的命令无输出——镜像里没有 opensipsctl(传统管理脚本未随镜像分发),但带有三个管理工具:opensips-cli(新版 Python CLI)、opensips-mi(轻量 MI 客户端,健康检查同款)、osipsconfig(配置模板生成器)。管理工具的用法详见本专栏 CLI 篇。

再看默认配置文件与模块:

docker run --rm --entrypoint sh opensips/opensips:4.0 -c 'ls -la /etc/opensips/ && ls /usr/lib/x86_64-linux-gnu/opensips/modules/ | wc -l'
total 20
drwxr-xr-x 1 root root 4096 Sep 18 10:41 .
drwxr-xr-x 1 root root 4096 Oct 26 10:43 ..
-rw-r--r-- 1 root root 5456 Sep 18 10:41 opensips.cfg
-rw-r--r-- 1 root root  353 Sep  8 14:34 scenario_callcenter.xml
102

默认 /etc/opensips/opensips.cfg 是官方 residential(住宅/PBX 场景)模板,与 APT 包安装后的默认配置同源(逐行解析见《Ubuntu 22.04 安装 openSIPS 4.0 指南》)。镜像内置 102 个功能模块。配置中有两处决定本篇走向的关键行:

36:socket=udp:127.0.0.1:5060   # CUSTOMIZE ME
73:modparam("mi_fifo", "fifo_name", "/run/opensips/opensips_fifo")

socket=udp:127.0.0.1:5060 就是第五章第一个故障的根源,官方留了 # CUSTOMIZE ME 注释提醒必改。

2.4 内置健康检查

镜像自带健康检查定义,直接读出来:

docker inspect opensips/opensips:4.0 --format '{{json .Config.Healthcheck}}'
{"Test":["CMD-SHELL","if [ \"$OPENSIPS_CLI_ENV\" != \"true\" ]; then             exit 0;         fi;         opensips-mi uptime 2>/dev/null | grep -q \"Up since\" || exit 1"],"Interval":15000000000,"Timeout":5000000000}

解读:每 15 秒(Interval=15000000000 纳秒)在容器内执行一次 opensips-mi uptime,能从 MI 接口读到 Up since 字样即判活,单次超时 5 秒。也就是说容器健康状态 = MI 接口应答正常,这个机制在第七章验证。

三、准备配置文件

Docker 化部署的最佳实践是:配置文件留在宿主机,以只读方式挂载进容器。这样改配置不进容器、重建容器不丢配置、配置文件可以纳入 git 管理。

第一步,把镜像内置的默认配置导出到宿主机(在部署目录 /opt/opensips-b2 下操作,读者自选目录即可):

docker run --rm --entrypoint cat opensips/opensips:4.0 /etc/opensips/opensips.cfg > opensips.cfg
grep -n 'socket=udp' opensips.cfg
36:socket=udp:127.0.0.1:5060   # CUSTOMIZE ME

导出的文件与镜像内逐字节一致(5456 字节)。本篇暂不改动它——先原样启动,让第一个故障自然暴露(5.3 节),修改动作放在故障修复的上下文里做,每处改动都有验证。

四、编写 docker-compose.yml

在部署目录新建 docker-compose.yml,内容如下(全文):

name: opensips-4-0-stack

services:
  opensips:
    image: opensips/opensips:4.0
    container_name: opensips-40-b2-app
    restart: unless-stopped
    volumes:
      - ./opensips.cfg:/etc/opensips/opensips.cfg:ro
    ports:
      - "5060:5060/udp"
      - "5060:5060/tcp"
    networks:
      sipnet:
        ipv4_address: 10.89.66.10

networks:
  sipnet:
    name: opensips-b2-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.66.0/24

逐段解读:

配置项说明
name: opensips-4-0-stack显式声明 Compose 项目名。不写的话项目名取自目录名,多套环境共用一个部署目录规范时极易互相干扰,down 会误删同项目名的其他栈
container_name固定容器名,docker logs / docker exec 不用查 ID
restart: unless-stopped宿主机重启或进程崩溃后自动拉起;手动 stop 后不自动重启
volumes 的 :ro配置文件只读挂载,容器内改不了,改动必须回到宿主机,避免配置漂移
ports把容器的 5060/udp 与 5060/tcp 发布到宿主机同名端口;UDP 是 SIP 信令主传输,TCP 为第六章启用 TCP 后预留
networks + ipam自定义 bridge 网络并固定子网 10.89.66.0/24,容器固定 IP 10.89.66.10——SIP 场景固定 IP 便于对端做 ACL

⚠️ 子网选型提示:自定义网络子网不要拍脑袋写。Docker 的默认地址池覆盖 172.17–172.31 等常见段,多项目宿主机上还可能已有其他网络占用 10.89.x.0/24 段——本实验最初写的 10.89.63.0/24 就与宿主机上既有网络冲突(实录见 9.1 节)。先用 docker network ls 加 docker network inspect 摸清已占网段再定。

五、启动与连通性验证

5.1 启动

docker compose up -d
 Network opensips-b2-net Creating
 Network opensips-b2-net Created
 Container opensips-40-b2-app Creating
 Container opensips-40-b2-app Created
 Container opensips-40-b2-app Starting
 Container opensips-40-b2-app Started
docker compose ps
NAME                 IMAGE                   COMMAND                  SERVICE    CREATED                  STATUS                                     PORTS
opensips-40-b2-app   opensips/opensips:4.0   "/usr/sbin/opensips …"   opensips   Less than a second ago   Up Less than a second (health: starting)   0.0.0.0:5060->5060/tcp, 0.0.0.0:5060->5060/udp, [::]:5060->5060/udp

STATUS 列的 (health: starting) 就是 2.4 节那个内置健康检查在工作,启动 15–30 秒后应翻转为 (healthy)。

5.2 看启动日志

docker logs opensips-40-b2-app
Oct 26 10:46:07 [1] INFO:core:fix_poll_method: using epoll as the IO watch method (auto detected)
Listening on
             udp: 127.0.0.1 [127.0.0.1]:5060
Aliases:

Oct 26 10:46:07 [1] NOTICE:core:main: version: opensips 4.0.2 (x86_64/linux)
Oct 26 10:46:07 [1] NOTICE:core:main: using 32 MB of shared memory, allocator: F_MALLOC
Oct 26 10:46:07 [1] NOTICE:core:main: using 16 MB of private process memory, allocator: F_MALLOC

(输出节选,实测首部)Listening on 块是 openSIPS 启动时打印的实际监听清单——判定监听状态以这里为准。此刻它监听的是 127.0.0.1:5060:镜像默认配置原样生效了。容器内日志直达 stdout/stderr(默认配置 stderror_enabled=yes),docker logs 即可全量查看,无需进容器翻文件。

容器内共享内存 32 MB、私有内存 16 MB 是镜像默认值,调优方法(-M/-m 启动参数与 compose 的 command 覆盖)属于进阶配置,本篇不展开。

5.3 第一次探测:Connection refused

从内网客户端 10.89.62.4 上用 sipsak 向宿主机发布地址发一个 OPTIONS 探测:

timeout 30 sipsak -v -s sip:10.89.62.1; echo "exit=$?"

send failure: Connection refused
exit=3

失败原因链:客户端 → 宿主机 5060/udp(端口已发布,NAT 正常)→ DNAT 到容器 10.89.66.10:5060 → 容器里 openSIPS 只监听 127.0.0.1,eth0 上没有进程 → 内核回 ICMP port unreachable → sipsak 报 Connection refused。

修复:把配置第 36 行改为监听所有接口,并在其后加一行 alias(为什么需要 alias 见 5.4 节,这里先一并改掉,避免两次重启):

36:socket=udp:0.0.0.0:5060
37:alias=10.89.62.1

改的是宿主机文件,docker compose restart opensips 让进程重读配置:

docker compose restart opensips
 Container opensips-40-b2-app Restarting
 Container opensips-40-b2-app Started
docker logs --since 60s opensips-40-b2-app
Listening on
             udp: 0.0.0.0 [0.0.0.0]:5060
Aliases:

0.0.0.0 生效,网络层通了。

5.4 第二次探测:403 Relay Forbidden 与 alias

再次探测,这次收到了 SIP 应答,但内容出乎意料:

sipsak -v -s sip:10.89.62.1
SIP/2.0 403 Relay Forbidden
Via: SIP/2.0/UDP 10.89.62.4:50853;received=10.89.66.1;branch=z9hG4bK.271d8ce7;rport=47929;alias
To: sip:10.89.62.1;tag=60f6.6275d1179c2080782df294167dab8ea7
From: sip:sipsak@10.89.62.4:50853;tag=20106f33
Call-ID: 537947955@10.89.62.4
CSeq: 1 OPTIONS
Server: OpenSIPS (4.0.2 (x86_64/linux))
Content-Length: 0

403 Relay Forbidden 是 residential 模板的路由逻辑在拒绝:非 REGISTER 请求进来后,脚本检查 R-URI 主机($rd,此处是 10.89.62.1)是否"属于自己",不是就拒绝中继。10.89.62.1 是宿主机地址,容器内的 openSIPS 并不知道它属于自己——裸机安装时服务 IP 与请求目标天然一致,而端口发布把这一层对等关系拆开了。

alias=10.89.62.1 的作用正是把宿主机发布地址登记为本地别名,is_myself() 检查即通过。这就是 5.3 节把它与 socket 一起改掉的原因。

💡 实操要点:alias 应填客户端请求实际指向的地址——这里是经端口发布后请求 R-URI 里的宿主机 IP。若你的服务有域名(如 sip.example.com),同样加进 alias:alias="sip.example.com" alias=10.89.62.1。

第三次探测,收到预期应答:

sipsak -v -s sip:10.89.62.1
SIP/2.0 484 Address Incomplete
Via: SIP/2.0/UDP 10.89.62.4:53854;received=10.89.66.1;branch=z9hG4bK.0d2ce196;rport=40781;alias
To: sip:10.89.62.1;tag=60f6.e9cf4a22229a8ad5cf44e86d76870a8f
From: sip:sipsak@10.89.62.4:53854;tag=41c41581
Call-ID: 1103369601@10.89.62.4
CSeq: 1 OPTIONS
Server: OpenSIPS (4.0.2 (x86_64/linux))
Content-Length: 0

484 Address Incomplete 是正常的业务应答:OPTIONS 请求的 R-URI 没带用户名部分($rU 为空),模板脚本按设计回 484。判定部署成功的依据有两个——

  1. 应答头 Server: OpenSIPS (4.0.2 (x86_64/linux)) 证明应答来自容器内的 openSIPS 4.0.2;
  2. Via 行的 received=10.89.66.1 暴露了一个值得知道的细节:跨网络的端口发布路径上 Docker 做了源地址改写(SNAT),容器看到的客户端源 IP 是网关 10.89.66.1 而非真实的 10.89.62.4。依赖源 IP 做 ACL 的场景(如 set_adr_port、防攻击策略)要把这个改写考虑进去。

六、启用 TCP 传输

默认配置只加载了 UDP 传输。生产中 TCP 常用于大消息体(如带大授权头的 REGISTER)与 TLS 的前置形态。启用两步:加载传输模块、声明 TCP socket。

编辑宿主机的 opensips.cfg,在 loadmodule "proto_udp.so" 之后加一行:

97:loadmodule "proto_udp.so"
98:loadmodule "proto_tcp.so"

再在 socket 区加一行:

36:socket=udp:0.0.0.0:5060
37:socket=tcp:0.0.0.0:5060
38:alias=10.89.62.1

重启并确认监听清单:

docker compose restart opensips && docker logs --since 30s opensips-40-b2-app
Listening on
             udp: 0.0.0.0 [0.0.0.0]:5060
             tcp: 0.0.0.0 [0.0.0.0]:5060
Aliases:
             *: 10.89.62.1:*

UDP/TCP 双 socket 就绪,alias 也出现在别名列表。

6.1 验证 TCP 传输

常用探测工具 sipsak 0.9.8.1 不支持 TCP 传输(其 -T 是 traceroute 模式,不是 TCP,见 9.4 节实录)。用 bash 内建的 /dev/tcp 手工发一个完整的 SIP OPTIONS 报文:

docker exec opensips-40-sipp bash -c 'exec 3<>/dev/tcp/10.89.62.1/5060 && printf "OPTIONS sip:10.89.62.1 SIP/2.0\r\nVia: SIP/2.0/TCP 10.89.62.4:50999;branch=z9hG4bK.tcp1\r\nFrom: <sip:probe@10.89.62.4>;tag=tcp1\r\nTo: <sip:10.89.62.1>\r\nCall-ID: tcp-probe-1@10.89.62.4\r\nCSeq: 1 OPTIONS\r\nMax-Forwards: 10\r\nContent-Length: 0\r\n\r\n" >&3 && timeout 4 cat <&3'
SIP/2.0 484 Address Incomplete
Via: SIP/2.0/TCP 10.89.62.4:50999;received=10.89.66.1;branch=z9hG4bK.tcp1
To: <sip:10.89.62.1>;tag=60f6.36b1f214c8ab32eac5bcb3833280bed0
From: <sip:probe@10.89.62.4>;tag=tcp1
Call-ID: tcp-probe-1@10.89.62.4
CSeq: 1 OPTIONS
Server: OpenSIPS (4.0.2 (x86_64/linux))
Content-Length: 0

Via: SIP/2.0/TCP 证实请求走的是 TCP 传输并得到正常应答。TCP 链路端到端打通:客户端 → 宿主机 5060/tcp → DNAT → 容器 TCP socket。

七、MI 管理接口与健康检查

MI(Management Interface)是 openSIPS 的管理命令通道,默认配置已通过 mi_fifo.so 在容器内启用。镜像自带的 opensips-mi 是配套的轻量客户端,直接在容器内执行:

docker exec opensips-40-b2-app opensips-mi uptime
{
    "Now": "Mon Oct 26 10:50:44 2026",
    "Up since": "Mon Oct 26 10:48:44 2026",
    "Up time": "120 [sec]"
}

Up since/Up time 与最近一次 docker compose restart 的时间吻合,MI 通道工作正常。这正是 2.4 节健康检查用的同一条命令——验证一下健康状态是否已翻绿:

docker compose ps
NAME                 IMAGE                   COMMAND                  SERVICE    CREATED         STATUS                     PORTS
opensips-40-b2-app   opensips/opensips:4.0   "/usr/sbin/opensips …"   opensips   4 minutes ago   Up 2 minutes (healthy)   0.0.0.0:5060->5060/tcp, 0.0.0.0:5060->5060/udp, [::]:5060->5060/tcp, [::]:5060->5060/udp

(healthy) 确认健康检查闭环。在 Docker 编排体系里,这个状态可直接用于依赖排序(depends_on: condition: service_healthy)与负载均衡摘流。

⚠️ 提示:镜像里同时带有功能更全的 opensips-cli,但其 MI 命令按 <模块>:<命令> 命名空间语法调用(如 opensips-cli -x mi core:uptime),直接传裸 MI 命令名会报 ERROR: no command 'uptime' in module 'mi'。轻量起见,容器内日常管理用 opensips-mi 即可;opensips-cli 的完整用法见本专栏 CLI 篇。

八、日常运维:修改配置、停止与清理

8.1 修改配置的标准流程

配置以只读方式挂载,改配置的标准流程是三步:改宿主机文件 → docker compose restart opensips → 看 docker logs 的 Listening on 与探测验证。前文的 5.3、5.4、6 章实际演示了完整的三轮。两点注意:

  • SIP 配置改动没有热加载:restart 会重建 openSIPS 进程,进行中的 SIP 事务与在途注册会中断,生产环境在维护窗口操作;
  • 注册数据不落盘:默认模板的 usrloc 是内存模式(working_mode_preset 为 single-instance-no-db),重启后终端注册全部丢失,终端会自动重新注册;需要注册持久化的场景要给 usrloc 配数据库后端。

8.2 停止与再启动

docker compose stop
 Container opensips-40-b2-app Stopping
 Container opensips-40-b2-app Stopped

stop 保留容器与网络,再启动用:

docker compose start
 Container opensips-40-b2-app Starting
 Container opensips-40-b2-app Started

8.3 彻底清理

docker compose down
 Container opensips-40-b2-app Stopping
 Container opensips-40-b2-app Stopped
 Container opensips-40-b2-app Removing
 Container opensips-40-b2-app Removed
 Network opensips-b2-net Removing
 Network opensips-b2-net Removed

down 连网络一并删除(本篇的网络是 compose 内声明创建的,所以会跟着删)。配置文件 opensips.cfg 与 docker-compose.yml 都在宿主机目录里,down 之后 up -d 即完整重建——这正是配置外置的价值。

九、排障实录

本章汇总本次部署实测中真实踩到的四个坑,按"现象 → 原因 → 解法"沉淀。

9.1 自定义子网与既有网络冲突

现象:docker compose up -d 报错:

 Network opensips-b2-net Error
Error response from daemon: invalid pool request: Pool overlaps with other one on this address space
network:sipnet failed to create network opensips-b2-net: Error response from daemon: invalid pool request: Pool overlaps with other one on this address space
Command failed with exit code 1

原因:最初写的子网 10.89.63.0/24 已被宿主机上另一个 Compose 项目占用。Docker 的地址池分配是全局的,任意网络间子网重叠都会被拒绝。

解法:先盘点已占网段再选槽:

docker network ls --format '{{.Name}}' | while read n; do s=$(docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}} {{end}}' 2>/dev/null); echo "$n -> $s"; done
opensips-net -> 10.89.62.0/24
postorius-1-3-13-net -> 10.89.63.0/24
plugnmeet-net -> 10.89.64.0/24

(输出节选,实测多行中摘录 10.89 段)确认 10.89.63.0/24 被占后,本实验改用空闲的 10.89.66.0/24,并同步修改 compose 中 subnet 与 ipv4_address 两处——只改 subnet 不改静态 IP 会撞上下一个坑。

9.2 静态 IP 与子网不同步

现象:只改了 subnet、忘了改 ipv4_address 时,docker compose up -d 报错:

 service:opensips:1 Error response from daemon: invalid config for network opensips-b2-net: invalid endpoint settings:
no configured subnet contains IP address 10.89.63.10

原因:ipv4_address 静态 IP 必须落在该网络某个已配置的子网内,报错信息会把不匹配的 IP 原样列出。

解法:两个值一起改(10.89.63.10 → 10.89.66.10)。排查此类报错先看 compose 里的 ipam.config.subnet 与服务级 ipv4_address 是否同一网段。

9.3 docker run 传参被入口点吞掉

现象:想看镜像里有哪些工具,直接在镜像名后面跟命令:

docker run --rm opensips/opensips:4.0 sh -c 'which opensipsctl opensips-cli osipsconfig; ls /etc/opensips/'

结果没有任何 which/ls 的输出,反而打印了 openSIPS 的监听清单与:

Listening on
             udp: 127.0.0.1 [127.0.0.1]:5060
Aliases:

Oct 26 10:43:19 [1] INFO:core:fix_poll_method: using epoll as the IO watch method (auto detected)
Oct 26 10:43:19 [1] NOTICE:core:main: config file ok, exiting...

原因:该镜像的 Entrypoint 是 /usr/sbin/opensips -F(见 2.2 节)。docker run 镜像 命令 中你写的命令会被追加为 opensips 进程的参数而不是替代入口点——-c 等字符被 opensips 解析成了自身参数(-c 恰好是"仅检查配置"),于是跑了配置检查就退出。

解法:显式覆盖入口点:

docker run --rm --entrypoint sh opensips/opensips:4.0 -c 'which opensipsctl opensips-cli osipsconfig'

凡是需要进入该镜像执行非 opensips 命令(查看配置、装调试包、进 shell),一律带 --entrypoint。

9.4 sipsak 的 -T 不是 TCP

现象:验证 TCP 传输时执行 sipsak -T -v -s sip:10.89.62.1,报错:

error: for trace mode without a file the SIPURI have to contain a username

原因:查 -h 帮助可知 -T 是 traceroute(SIP 路由追踪)模式:

  -T                activates the traceroute mode

sipsak 0.9.8.1 根本没有 TCP 传输能力。

解法:TCP 探测换用 bash /dev/tcp 手工构造 SIP 报文(完整命令与回显见 6.1 节),或使用支持 TCP 的测试工具(如 sipp)。

十、参考链接