IP_MINTTL 不适用于原始套接字

IP_MINTTL 不适用于原始套接字

我们正在为 OSPF 实施 TTL 安全功能。作为其中的一部分,我们需要根据 ttl 值验证传入的 ospf 数据包。

为此,我们使用 IP_MINTTL 套接字选项来验证传入的数据包。但我们观察到,无论 TTL 值如何,数据包都不会被丢弃。

由于我们使用原始套接字进行 ospf 接收和发送,因此在此套接字上设置此 IP_MINTTL。

但它不起作用,这个选项适用于 RAW 套接字吗?请帮我理解这一点?

我们使用的是linux 4.18内核版本。

问候,拉杰什。

答案1

从今年2010年开始绿网文章(同时,*BSD 的功能可能已经改进或已经完成,但 Linux 显然没有任何变化):

Linux补丁相当简单,实现与BSD内核相同。添加了一个新选项 ( IP_MINTTL),可用于setsockopt()更改套接字的最小 TTL。如果设置, TCP 代码检查值并丢弃具有较小 TTL 的数据包。该补丁未添加对各种其他协议(例如 UDP)或 IPv6 等效协议的支持,即IPV6_MINHOPLIMIT

在 Linux 上该选项似乎仅对 TCP 套接字有效。 RAW 套接字即使接收 TCP 数据包,也不是 TCP 套接字。

可以通过在内核源代码中使用以下命令找到有关内核 5.18 的相关内核代码IP_MINTTL(您必须检查 4.18 的发行版):

$ grep -Ewrl 'IP_MINTTL|min_ttl'  net
net/netrom/sysctl_net_netrom.c
net/mptcp/sockopt.c
net/ipv4/tcp_ipv4.c
net/ipv4/ip_sockglue.c

ip_sockglue.c处理套接字选项本身,但与数据包内容进行实际比较的唯一地方是在tcp_ipv4.c(以下相同的块在此文件中几乎完全相同地出现两次):

  if (static_branch_unlikely(&ip4_min_ttl)) {
      /* min_ttl can be changed concurrently from do_ip_setsockopt() */
      if (unlikely(iph->ttl < READ_ONCE(inet_sk(sk)->min_ttl))) {
          __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
          goto discard_and_relse;
      }
  }

这意味着自 2010 年 LWN 文章以来没有任何变化。

可能的解决方法:防火墙规则。看iptables的 IPv4ttl匹配或nftables的 IPv4ttl表达。 “AF_INET,SOCK_RAW”套接字应该没问题,但“AF_PACKET,SOCK_RAW”则不然,它会在防火墙规则发生之前接收数据(无论如何IP_MINTTL应该仅适用于前者)。

相关内容