Kamailio 关于 mhomed 的讨论之续集
笔记问AI源码是怎样实现的下面是回答可以从 Kamailio 源码里能找到这套逻辑。重点是Kamailio 并不是自己解析/proc/net/route或 netlink 去读操作系统路由表而是通过 socket API 让内核做一次路由选择然后用getsockname()取出内核选择的本地源地址。也就是说mhomed1时的“查路由表”本质上是创建临时 socket connect() 到目标地址 内核根据路由表选择出口接口和源 IP getsockname() 取到本地源 IP Kamailio 根据这个源 IP 匹配自己的 listen socket1. 源码里主要看哪些文件你可以在src/core目录里重点搜这些关键字grep-Rmhomedsrc/coregrep-Rget_out_socketsrc/coregrep-Rgetsocknamesrc/coregrep-Rconnectsrc/core/socket_info.c src/core/forward.cgrep-Rget_send_socketsrc/core通常相关逻辑主要分布在这些文件中src/core/globals.h src/core/globals.c src/core/cfg.lex src/core/cfg.y src/core/forward.c src/core/socket_info.c src/core/socket_info.h不同 Kamailio 版本代码可能略有移动但核心逻辑基本一致。2.mhomed参数在哪里定义全局变量一般可以在类似位置找到externintmhomed;通常在src/core/globals.h src/core/globals.c配置文件解析部分会把mhomed1解析成全局变量赋值。你可以搜grep-Rmhomedsrc/core/cfg.*大致会看到类似mhomed1;或者配置语法中对mhomed的处理。3. send socket 选择入口Kamailio 发送 SIP 消息时会构造发送目标例如目标 IP、端口、协议然后选择一个本地 socket。核心流程一般在src/core/forward.c里面可以找类似函数get_send_socket(...)或者相关调用。逻辑大致类似if(msg-force_send_socket){returnmsg-force_send_socket;}if(mhomed){returnget_out_socket(destination,proto);}returndefault_socket;这不是精确源码只是简化后的逻辑。也就是说force_send_socket() / $fs 显式指定 优先级最高 mhomed1 根据目标地址自动判断本地 socket 否则 使用默认 send socket 选择逻辑4. 真正“查系统路由”的地方重点看src/core/socket_info.c里面通常会有类似函数get_out_socket(...)这个函数就是mhomed的关键。它的思想大概是socket()connect()getsockname()close()find matching Kamailio listen socket伪代码大致如下structsocket_info*get_out_socket(unionsockaddr_union*to,intproto){ints;unionsockaddr_union local_addr;ssocket(to-s.sa_family,SOCK_DGRAM,0);connect(s,to-s,sockaddru_len(*to));getsockname(s,local_addr.s,len);close(s);returnfind_socket_by_local_ip(local_addr,proto);}关键点是这两步connect(s,destination)getsockname(s,local_addr)5. 为什么connect()可以查路由以 UDP 为例ssocket(AF_INET,SOCK_DGRAM,0);connect(s,dst,dst_len);getsockname(s,local,len);UDP 的connect()不会真的发送 SIP 包也不会像 TCP 那样完成三次握手。它只是告诉内核这个 socket 以后准备发往 dst内核为了完成这个操作会做路由查询目标地址是谁 应该走哪个路由 出口接口是哪一个 本地源地址应该选哪个然后getsockname()可以拿到内核为这个 socket 选择的本地地址。这和你在 Linux 上执行iproute get 目标IP看到的结果非常接近。例如iproute get192.168.10.20输出192.168.10.20 dev eth1 src 192.168.10.10那么 Kamailio 用mhomed1时也会通过类似机制得到local source ip 192.168.10.10然后去匹配listenudp:192.168.10.10:50606. Kamailio 不是直接读路由表这一点很重要。Kamailio 不是这样做的读取 /proc/net/route 解析 ip rule 解析 ip route 自己计算最长前缀匹配 自己判断出口接口而是这样做的让操作系统内核完成路由选择 Kamailio 只读取内核选择后的本地源 IP所以mhomed的行为主要取决于内核路由选择结果。你可以把它理解成iproute getdestination-ip的程序化版本。7. 匹配 Kamailio listen socket 的过程假设服务器配置listenudp:10.0.0.10:5060 listenudp:192.168.1.10:5060 mhomed1系统路由iproute get192.168.1.50返回192.168.1.50 dev eth1 src 192.168.1.10那么 Kamailio 会得到本地源地址192.168.1.10然后在自己的 socket 列表里查找udp:192.168.1.10:5060匹配成功后用这个 socket 发 SIP 消息。源码中这个匹配逻辑通常和这些函数/结构有关struct socket_info find_si(...) grep_sock_info(...) get_sock_info_list(...)你可以搜grep-Rstruct socket_infosrc/coregrep-Rfind_sisrc/coregrep-Rgrep_sock_infosrc/core8. 简化后的完整流程发送一个请求到sip:alice192.168.1.50:5060Kamailio 内部大致流程1. 解析目标地址 dst 192.168.1.50:5060 2. 检查是否强制指定 send socket force_send_socket() $fs 如果有直接使用指定 socket 3. 如果 mhomed1 调用 get_out_socket(dst, proto) 4. get_out_socket() 创建临时 UDP socket 5. connect() 到 192.168.1.50:5060 6. 内核查询路由表 选择出口 eth1 选择源地址 192.168.1.10 7. getsockname() 得到 local ip 192.168.1.10 8. Kamailio 在 listen socket 中查找 udp:192.168.1.10:5060 9. 找到后作为 send socket 10. 用该 socket 发送 SIP 消息9. 可以用命令验证 Kamailio 的选择假设 Kamailio 要发往203.0.113.8你可以在系统上执行iproute get203.0.113.8如果输出是203.0.113.8 via 10.10.10.1 dev eth0 src 10.10.10.20那么mhomed1时Kamailio 大概率会选择udp:10.10.10.20:5060前提是你确实有listenudp:10.10.10.20:5060如果没有对应的listensocketKamailio 可能会 fallback 到默认 socket或者打印相关 warning/error具体行为取决于版本和发送路径。10. 一个实际例子Kamailio 配置listenudp:10.0.0.10:5060 listenudp:172.16.0.10:5060 listenudp:203.0.113.10:5060 mhomed1Linux 路由iproute输出10.0.0.0/24 dev eth0 src 10.0.0.10 172.16.0.0/24 dev eth1 src 172.16.0.10 default via 203.0.113.1 dev eth2 src 203.0.113.10测试iproute get10.0.0.55返回10.0.0.55 dev eth0 src 10.0.0.10Kamailio 选择udp:10.0.0.10:5060测试iproute get172.16.0.55返回172.16.0.55 dev eth1 src 172.16.0.10Kamailio 选择udp:172.16.0.10:5060测试iproute get8.8.8.8返回8.8.8.8 via 203.0.113.1 dev eth2 src 203.0.113.10Kamailio 选择udp:203.0.113.10:506011. 需要注意 policy routing因为 Kamailio 是通过普通 socket 触发内核路由选择所以它通常会遵循ip route ip rule source-based routing routing table但是如果你的系统路由依赖这些特殊条件fwmark SO_MARK cgroup bind-to-device iptables mark VRF network namespace那么需要特别小心。因为 Kamailio 用于mhomed判断的临时 socket未必带有和真实业务包完全相同的 mark 或 bind device 条件。这样可能导致ip route get 目标IP和真实发送路径一致但如果你的生产环境依赖 fwmark结果可能不一致。这种情况下建议显式使用force_send_socket(...)或者$fs udp:1.2.3.4:5060;12. 总结可以在源码里找到。核心位置src/core/forward.c src/core/socket_info.c src/core/socket_info.h核心关键字grep-Rmhomedsrc/coregrep-Rget_out_socketsrc/coregrep-Rgetsocknamesrc/coregrep-Rget_send_socketsrc/core核心机制不是 Kamailio 自己解析路由表而是socket() connect() getsockname()让 Linux/Unix 内核根据当前路由表选择本地源地址然后 Kamailio 用这个源地址去匹配自己的listensocket最终得到 send socket。

相关新闻

【我的第一篇博客】

【我的第一篇博客】

我是一名四川轻化工大学物联网工程专业的学生,我目前大三,感觉没学到什么东西。我知道这是我自己的原因,所以我想做出改变,我报名了鹏哥训练营,希望能有收获。我的学习目标是:能看懂代码,会写一些代码。怎么…

2026/7/23 21:55:07 阅读更多 →
网安必备的基础小知识

网安必备的基础小知识

一、网络 这里显示的有四个网络: 1.以太网:自己电脑的真是网线网卡,负责电脑正常的上网 2.VMnet1(仅主机):只让你的电脑和虚拟机相互通信,虚拟机不上网 3.VMnet8(NAT)…

2026/7/23 21:55:07 阅读更多 →
个人笔记:实用机器学习(b站李沐)

个人笔记:实用机器学习(b站李沐)

1.1课程介绍 背景:机器学习已经从少数科技巨头的"玩具"变成了各行各业驱动商业营收的核心工具,而新冠疫情进一步加速了这一商业化进程。五大行业典型的ML的应用: 制造业(Manufacturing):预测性维护、质量控制零售业 (Re…

2026/7/23 21:55:07 阅读更多 →

最新新闻

八大排序代码

八大排序代码

冒泡排序交换排序希尔排序堆排序基数排序归并排序快速排序

2026/7/23 22:03:10 阅读更多 →
模型评估和模型选择

模型评估和模型选择

1、损失函数对于模型一次预测结果的好坏,需要有一个度量标准。对于监督学习而言,给定一个输入X,选取的模型就相当于一个“决策函数”f,它可以输出一个预测结果f(X),而真实的结果(标签)记为Y。f(…

2026/7/23 22:03:10 阅读更多 →
集团企业必看!国内知名ERP厂商精选榜单发布

集团企业必看!国内知名ERP厂商精选榜单发布

一、引言 2026年上半年国内企业数字化管理软件市场持续迭代,赛迪顾问最新行业数据显示,国内ERP市场整体规模达326.8亿元,国产厂商市场占比提升至76.2%,本土软件的技术适配性、落地实用性已全面适配国内企业经营管理需求。在企业管…

2026/7/23 22:03:10 阅读更多 →
51单片机从零到实战(13)——毕设常用ADC模块

51单片机从零到实战(13)——毕设常用ADC模块

第 13 篇:ADC 模数转换——让单片机"感知"模拟世界 温度、光线、声音、电压——这些是连续的"模拟量"。ADC 把它们变成单片机懂的"数字量"。STC89C52 没有内置 ADC,我们用 PCF8591 模块(I2C 接口,5…

2026/7/23 22:02:09 阅读更多 →
Recruiter初筛到底在判断什么?|蒸汽求职分享

Recruiter初筛到底在判断什么?|蒸汽求职分享

**摘要:**招聘人员初筛时间通常不长,却不只是核对简历。候选人与岗位是否基本匹配、求职方向是否清楚、表达是否容易理解,以及入职时间、地点、工作资格和薪资等现实条件,都可能影响是否进入下一轮。 不少留学生准备面试时&#x…

2026/7/23 22:02:09 阅读更多 →
招聘网站之外,留学生还能去哪找岗位?|蒸汽求职分享

招聘网站之外,留学生还能去哪找岗位?|蒸汽求职分享

**摘要:**长期刷新同一个招聘网站,容易反复看到重复岗位。企业官网、学校职业系统、招聘活动、校友网络和实习团队,也可能提供更早或更适合学生的招聘信息。 每天打开招聘网站,输入相同的岗位名称,再按照“最新发布”排…

2026/7/23 22:02:09 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻