使用AF_UNSPEC会有哪些缺点/风险?

时间:2011-11-16 09:49:31

标签: c++ c sockets unix network-programming

来自Beej's Guide to Network programming

  

您可以强制它在ai_family字段中使用IPv4或IPv6,或将其保留为AF_UNSPEC以使用任何内容。这很酷,因为您的代码可以与IP版本无关。

正如标题所说 - 总是使用AF_UNSPEC而不是指定IPv4或IPv6会有什么缺点(或风险,如果有的话)?

或者只是出于一个原因 - 如果指定了版本,这将保证只支持此版本吗?


一点背景 - 我考虑在客户端 - 服务器(C ++)应用程序中添加对IPv6的支持,并且应该支持这两个版本。所以我想知道使用AF_UNSPEC是否合适,或者最好“识别”字符串中的地址并使用AF_INET6AF_INET,具体取决于地址。

3 个答案:

答案 0 :(得分:3)

应该是这样的:

应用程序应该是第3层不可知的。应该通过名称连接到另一个系统。该名称应解析为一个或多个地址,应用程序应连接到它们,而不查看正在使用的实际协议。这样,网络配置是网络和系统管理员的责任。如果在网络中引入了IPv6,那么应用程序将继续工作,甚至不会注意到差异。

一些现实问题:

有时IPv6配置错误,防火墙不知道如何处理IPv6,IPv6只在本地网络中使用而没有连接到互联网等。这应该不是问题,但有时你会遇到糟糕的实施或配置。为了解决这个问题,IETF正在制定一个名为happy-eyeballs的草案。它确保用户不会注意到这些问题。看看那个草案。使用该草案中指定的技术将确保您的应用程序适用于所有用户。

答案 1 :(得分:3)

您必须区分客户端和服务器应用程序。

在客户端上,这很简单:只需拨打getaddrinfo()并按顺序尝试每个答案,直到获得连接为止。

在服务器上,事情有点困难:

  • 有些系统的IPv4和v6堆栈是互连的,只需要监听IPv6即可。也许必须启用套接字来监听两者。
  • 其他系统(如Windows XP)在无法进行此连接的情况下分离了堆栈。在那里你必须同时使用几个套接字。让我集中讨论下面的内容。

即使在服务器上,也可以使用getaddrinfo()。在那里你使用提示中的标志AI_PASSIVE。然后你得到结果。在这些所有你必须听,也许启用IPV6_V6ONLY标志。

accept()应该是非阻止的,或者是select()poll()(不确定后者是否可行)。

答案 2 :(得分:-1)

使用AF_UNSPEC的一个风险是您将客户端暴露给来自恶意DNS服务器的较大响应,恶意DNS服务器可能正在尝试使用CVE-2015-7547导致堆栈缓冲区溢出,并导致恶意代码被执行客户端。事实上,getaddrinfo中已知缺陷的一个建议解决方法是防止在错误报告中使用AF_UNSPEC作为详细的here。 DNS响应大于2K的溢出缺陷会影响glibc从2.9,并在2.23中修复。这会影响大多数当前安装的Linux发行版。