UDP套接字:recvfrom和接收地址

UDP sockets: recvfrom and receive address

BSD/POSIX 套接字 API recvfrom() 调用(通过 <sys/socket.h> 头文件可供 C 或 C++ 程序员使用)提供源地址 "out"参数 struct sockaddr *src_addr,它存储发送接收到的数据报的远程服务器的 IP 地址。

对于任何 向某个远程端点发送 UDP 数据报,然后接收响应(例如 DNS 解析器)的应用程序,它是否被认为是必要的安全措施始终确保任何接收到的数据报都来自与最后一个 发送的 数据报相同的 IP 地址(即在前一个 sendto 调用中使用的地址?)

换句话说,如果我们调用 sendto 并将数据报发送到某个地址,我们是否应该始终确保相应的 recvfrom 调用来自 相同的地址?

考虑到如果远程服务器位于防火墙后面或某些具有多个 IP 地址的分布式系统的一部分,响应数据报可能合法地源自不同的 IP,这似乎不可行。

但是,如果我们不验证接收到的数据报来自 与上次 sendto 调用的地址相同的 IP 地址,那么如何防止一些攻击者拦截数据报,然后向客户端发送恶意数据报?

一些 NAT 支持 UDP 打洞,也能准确地完成您提到的 IP 验证,因此在应用程序中没有必要这样做。

对于自定义协议,您可能希望在有效负载中实现某种序列号,以进一步提高安全级别。

你怎么知道收到的数据包是回复?通常这是使用接收到的数据包中的源地址和端口完成的。

但是,无法验证 UDP 数据包中的源地址。发件人可以放置他们想要的任何源地址。所以只有当你信任所有在互联网上流动的数据包时,检查才足够,这显然是不可行的。

因此您需要一些额外的机制:随机 cookie、序列号等。

在一般情况下,任意接收到的数据报并不是对先前请求的响应。你必须过滤,例如通过 connect(), 以确保您只处理属于响应的响应。

For any application that sends UDP datagrams to some remote endpoint, and then receives a response (such as, for example, a DNS resolver),

您可以使用随机出站端口号。这就是 DNS can mitigate spoofing attacks.

is it considered a necessary security precaution to always make sure that any received datagram is from the same IP address as the last sent datagram (i.e. the address used in the previous sendto call?)

In other words, if we call sendto and send a datagram to some address, should we always make sure that a corresponding recvfrom call is from the same address?

不仅是为了安全,也是为了功能。如果您有多个出站连接,您需要知道每个连接对应哪个 UDP 回复。这可以通过远程端的 IP 地址和端口组合来实现。

It seems that this might not be feasible, considering that a response datagram might legitimately originate from a different IP if the remote server is behind a firewall, or part of some distributed system with multiple IP addresses.

远程系统应通过接收回复的同一界面发送回复。如果不是,它将是“非标准的”,并且不能与您的应用程序一起使用,也不能与需要接收和回复 UDP 数据包的其他应用程序一起使用。

But, if we don't verify that a received datagram is from the same IP address as the address from the last sendto call, what's to prevent some attacker from intercepting datagrams, and then sending malicious datagrams to the client?

没有。如果攻击者可以对 UDP 连接进行 MITM,那么他们就可以拦截和更改他们想要的任何内容。他们可以将带有欺骗性 IP 地址的 UDP 数据包发送到您的服务。

如果您需要保持数据包的完整性和机密性,则需要实施某种加密。例如。如果您需要支持数据报,请查看 DTLS