【问题标题】:How can I determine the source address before sending a message based on the destination address?在发送消息之前如何根据目标地址确定源地址?
【发布时间】:2014-04-03 17:59:01
【问题描述】:

这有点难以解释,所以请耐心等待。

在python中,我想发送一个UDP消息:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 5011))
dest = ('foo.horse', 5011)
# attact the source address to the message
...

sock.sendto(msg, dest)

但是在我发送该消息之前,我想根据目标地址确定将要发送的接口的地址,以便我可以将其包含在消息中。

例如,如果目标是 WAN 地址,则它将是 LAN 接口的地址(因为我在 NAT 后面)。如果目的地是“localhost”,那么地址就是“127.0.0.1”。如果它是 VPN 上的地址,那么它将是我的 VPN 地址。

更新:

看起来我可以使用:$ ip route get <destination>,它会告诉我源地址
https://stackoverflow.com/a/5557459/334632

我最终深入研究了 iproute2 源代码,但我看不到它在使用什么我可以快捷方式。 https://git.kernel.org/cgit/linux/kernel/git/shemminger/iproute2.git/tree/ip/iproute.c#n1376

我最终可能只是创建一个子进程并解析结果,但如果可能的话,我想避免这种情况。

【问题讨论】:

  • 为什么?您无需将其放入消息中。无论如何,它对接收者都是可用的。
  • @EJP SIP Via header。似乎某些 SIP 应用程序能够做到这一点,但我不知道他们是如何做到的。

标签: python linux sockets networking udp


【解决方案1】:

如果你不关心 linux 以外的任何东西,你可以使用pyroute2 模块。例如,要获取特定 IP 地址的路由信息​​:

>>> import pprint
>>> import pyroute2
>>> import socket
>>> ip = pyroute2.IPRoute()
>>> pprint.pprint(ip.get_routes(family=socket.AF_INET, dst='127.0.0.6'))
[{'attrs': [['RTA_TABLE', 254],
            ['RTA_DST', '127.0.0.6'],
            ['RTA_OIF', 1],
            ['RTA_PREFSRC', '127.0.0.1'],
            ['RTA_CACHEINFO',
             {'rta_clntref': 1,
              'rta_error': 0,
              'rta_expires': 0,
              'rta_id': 0,
              'rta_lastuse': 0,
              'rta_ts': 0,
              'rta_tsage': 0,
              'rta_used': 1}]],
  'dst_len': 32,
  'event': 'RTM_NEWROUTE',
  'family': 2,
  'flags': 2147484160,
  'proto': 0,
  'scope': 0,
  'src_len': 0,
  'table': 254,
  'tos': 0,
  'type': 2}]

不幸的是,这不适用于 pypi 上最新版本的pyroute2;我必须从源代码安装才能获得这些结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2021-06-21
    • 2010-10-09
    相关资源
    最近更新 更多