我正在实现一个 SIP 代理,该代理应该能够重定向两个无法互相访问的客户端之间的所有 RTP 流量。为了实现这一点,我决定操纵 SIP/SDP 消息中的协商地址并使用 iptables 规则重定向 RTP 流量。
如果发送 RTP 数据包的源发生变化,就会出现问题。在这种情况下,iptables 需要 30 秒才能开始重定向来自新源的流量。
为了详细解释我正在尝试做的事情,假设我有两个 SIP 客户端和我的代理:
- Bob 的 SIP 客户端正在 192.168.1.1 上运行
- Alice 的 SIP 客户端正在 192.168.2.1 上运行
- 代理在 192.168.3.1 上运行。
- Bob 和 Alice 的网络无法互相访问。代理知道 Bob 和 Alice 的网络。
Bob 呼叫 Alice,在其 SIP/SDP 消息中告知他将在 192.168.1.1:8000 监听 RTP 流量。然后代理将此地址更改为 192.168.3.1:15000,并将新的 SIP/SDP 消息转发给 Alice。现在,来自 Alice 的所有 RTP 流量都将发送到代理。为了将此流量重定向回 Bob,代理将以下规则添加到 iptables:
iptables -t nat -A OUTPUT -d 192.168.3.1 -p UDP --dport 15000 -j DNAT --to 192.168.1.1:8000
iptables -t nat -A PREROUTING -d 192.168.3.1 -p UDP --dport 15000 -j DNAT --to 192.168.1.1:8000
iptables -t nat -A POSTROUTING -d 192.168.1.1 -p UDP --dport 8000 -j SNAT --to 192.168.3.1:15000
现在,假设源 RTP 流发生变化。由于某种原因,现在运行代理的机器正在生成 RTP 流量,而不是 Alice。
iptables 规则无需更改。iptables 应该能够使用上面的 OUTPUT 规则重定向此新 RTP 流量。但是,iptables 需要 30 秒才能开始将流量重定向到 Bob。
经过一番研究,我发现这个问题可能是由 conntrack 表引起的,该表必须等待其条目“Alice->Bob”过期才能添加新条目“Proxy->Bob”。当我查看 /proc/net/ip_conntrack 时,我可以确认这一点。
我的规则没有指定源,因为我并不总是有它,而且它可能会在不通知代理的情况下动态更改。因此,我无法使用 conntrack-tools 手动删除 conntrack 条目,就像我在其他帖子中读到的那样。
关于如何处理这个问题有什么想法吗?
答案1
对 SIP+RTP 进行 NAT 并非易事。(当源/目标 IP 发生变化时,情况会更加复杂)除了源地址和目标地址之外,还有更多需要调整的内容。在实际的 SIP 会话中,也有一些位必须被修改(conntrack 模块就是这么做的)。SIP 用于协商每个对等体必须连接到的源和目标,以便交换 RTP 数据。由于所有流量都是 UDP(无连接),conntrack 模块必须等待超时或呼叫结束,然后连接才会被视为断开并从表中删除。
要解决您的问题,您需要一个合适的 SIP 代理……而不是 iptables。在这种情况下,电话将连接到代理,代理将连接到远程对等体的代理,远程代理将连接到远程对等体。在此示例中,将有 3 个单独的连接,如果其中一个路由器的 IP 发生变化,它只需重新邀请远程代理,然后连接就会恢复。您也不再需要 iptables 来处理数据包。