gpt4 book ai didi

erlang - Elixir/Erlang :gen_udp pseudo header

转载 作者:行者123 更新时间:2023-12-03 18:52:56 26 4
gpt4 key购买 nike

我想在 Elixir 中接收 UDP 消息,并且需要获取数据包发送到的目标 IP。
在 iex 中,我可以使用以下命令打开一个套接字:

{:ok, socket} = :gen_udp.open(19_999, [{:active, true}])
当我收到一条消息时,我会以以下格式收到它:
{:udp, port, source_ip, source_port, data}
目标 IP 不是消息的一部分。根据 UDP 规范,源 IP 不是 UDP 数据包的一部分,而是 IP 伪 header 的一部分。当我使用 tcpdump 时,我可以看到数据包的目标 IP。
有什么方法/参数可以获取UDP数据包的IP或伪 header 吗?

最佳答案

目的端口是 19_999当然。
要确定哪个 IP 正在接收当前数据包,您需要知道所有网络适配器的配置,包括虚拟适配器。之后,您可以从源 IP 和网络配置中获取目标 IP,因为只有同一网络中的设备才能相互通信。您只需要在所有网络适配器中找到与源 IP 位于同一网络中的 IP。您可以通过将网络掩码应用于2个IP地址来判断2个设备是否在同一网络中,并查看结果是否相同。
顺便说一句,如果您的服务器在 NAT 之后,如果它与服务器不在同一网络中,您将无法获得客户端的真实源 IP 地址。您只能获得最后一跳的源 IP 地址(通常是您网络网关的 IP 地址)。
获取网络配置

{:ok, ifaddrs} = :inet.getifaddrs()
你会得到一个看起来像的列表
[
{'lo', [addr: {127, 0, 0, 1}, netmask: {255, 0, 0, 0}, ...]},
{'eth0', [addr: {192, 168, 0, 10}, netmask: {255, 255, 255, 0}, ...]},
{'docker_gwbridge', [addr: {172, 18, 0, 1}, netmask: {255, 255, 0, 0}, ...]}
]
因为我们只需要 addrnetmask ,我们可以做进一步的 Enum.map在名单上:
ifaddrs = Enum.map(ifaddrs, fn{_, opts}-> {opts[:addr], opts[:netmask]} end)
将网络掩码应用于 IP 地址
只是按位和他们在一起。
defp apply_netmask({a1, b1, c1, d1} = _ip, {a2, b2, c2, d2} = _netmask) do
# Don't forget `use Bitwise`
{
a1 &&& a2,
b1 &&& b2,
c1 &&& c2,
d1 &&& d2
}
end
找到目的IP
dest_ip = ifaddrs
|> Enum.find(fn{addr, netmask}->
apply_netmask(addr, netmask) == apply_netmask(source_ip, netmask)
end)
|> elem(0)
更新
如果可能,我建议您仅在其中一个网络适配器上打开 UDP 套接字。您可以使用 {ifaddr, inet:socket_address()}实现这一目标的选项,例如:
{:ok, socket} = :gen_udp.open(19_999, [active: true, ifaddr: {192, 168, 0, 10}])
这样,您就可以 100% 确定目标 IP 是 192.168.0.10。此外,它还增加了一点安全性。

关于erlang - Elixir/Erlang :gen_udp pseudo header,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66572540/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com