23

在 IPv6 网络中,IPV6_V6ONLY 标志用于确保套接字仅使用 IPv6,特别是 IPv4 到 IPv6 的映射不会用于该套接字。在许多操作系统上,默认情况下不设置 IPV6_V6ONLY,但在某些操作系统(例如 Windows 7)上,默认设置。

我的问题是:引入这个标志的动机是什么?IPv4 到 IPv6 映射是否存在导致问题的问题,因此人们需要一种方法来禁用它?在我看来,如果有人不想使用 IPv4 到 IPv6 的映射,他们根本无法指定 IPv4 映射的 IPv6 地址。我在这里想念什么?

4

7 回答 7

12

并非所有支持 IPv6 的平台都支持双栈套接字,因此问题变成了需要最大限度地提高 IPv6 兼容性的应用程序如何知道支持双栈,或者在不支持双栈时单独绑定?唯一通用的答案是 IPV6_V6ONLY。

忽略 IPV6_V6ONLY 或在支持双栈的 IP 栈存在之前编写的应用程序可能会发现在双栈环境中单独绑定到 V4 失败,因为 IPv6 双栈套接字绑定到 IPv4 阻止了 IPv4 套接字绑定。由于协议或应用程序级别的寻址问题或 IP 访问控制,该应用程序也可能不会期望 IPv4 over IPv6。

即使 RFC3493 声明 0 为默认值,这种情况或类似情况也很可能促使 MS 等人默认为 1。1 理论上最大化向后兼容性。特别是 Windows XP/2003 不支持双栈套接字。

不幸的是,不乏需要传递较低层信息才能正确运行的应用程序,因此此选项对于规划最适合需求和现有代码库的 IPv4/IPv6 兼容性策略非常有用。

于 2010-05-10T16:41:39.990 回答
4

最常提到的原因是服务器具有某种形式的 ACL(访问控制列表)的情况。例如,想象一个具有如下规则的服务器:

Allow 192.0.2.4
Deny all

它在 IPv4 上运行。现在,有人在具有 IPv6 的机器上运行它,并且根据某些参数,IPv4 请求在 IPv6 套接字上被接受,映射为 ::192.0.2.4,然后不再与第一个 ACL 匹配。突然,访问将被拒绝。

在您的应用程序中显式(使用 IPV6_V6ONLY)可以解决问题,无论操作系统的默认设置如何。

于 2010-05-09T17:04:16.830 回答
3

我不知道为什么会默认;但无论默认值是什么,我总是会明确表示这种标志。

关于它首先存在的原因,我想它允许您保留现有的仅限 IPv4 的服务器,并在同一端口上运行新的服务器,但仅用于 IPv6 连接。或者,也许新服务器可以简单地将客户端代理到旧服务器,从而使 IPv6 功能可以轻松轻松地添加到旧服务中。

于 2010-04-22T19:32:24.700 回答
3

对于 Linux,当在同一个服务端口(例如端口 2001)上编写侦听 IPv4 和 IPv6 套接字的服务时,您必须调用 setsockopt(s, SOL_IPV6, IPV6_V6ONLY, &one, sizeof(one)); 在 IPv6 套接字上。如果不这样做,IPv4 套接字的 bind() 操作将失败,并显示“地址已在使用中”。

于 2013-03-28T16:16:38.403 回答
1

有一些合理的方法可以使用(名称不佳的)“IPv4 映射”地址来规避配置不当的系统或不良堆栈,甚至在配置良好的系统中也可能只需要大量的错误防护。开发人员可能希望通过不使用 API 的这一部分来使用此标志来使他们的应用程序更安全。

见:http: //ipv6samurais.com/ipv6samurais/openbsd-audit/draft-cmetz-v6ops-v4mapped-api-harmful-01.txt

于 2012-04-25T00:50:36.813 回答
0

想象一个在会话中包含网络地址的协议,例如 FTP 的数据通道。使用 IPv6 时,您将发送 IPv6 地址,如果收件人恰好是 IPv4 映射地址,它将无法连接到该地址。

于 2010-05-02T10:18:51.953 回答
0

有一个非常常见的例子,行为的二元性是一个问题。带有标志的标准getaddrinfo()调用AI_PASSIVE提供了传递节点名参数并返回要监听的地址列表的可能性。nodename接受 NULL 字符串形式的特殊值,这意味着侦听通配符地址。

在某些系统上0.0.0.0::按此顺序返回。当默认启用双栈套接字并且您未设置套接字IPV6_V6ONLY时,服务器连接到0.0.0.0双栈然后无法连接到双栈::,因此(1)仅适用于 IPv4 并且(2)报告错误。

我认为这个顺序是错误的,因为 IPv6 应该是首选。但是,即使您第一次尝试使用 dual-stack::然后尝试 IPv4-only 0.0.0.0,服务器仍然会报告第二次调用的错误。

我个人认为双栈插座的整个想法是错误的。在我的项目中,我宁愿始终明确设置IPV6_V6ONLY以避免这种情况。有些人显然认为这是一个好主意,但在这种情况下,我可能会明确取消设置IPV6_V6ONLYNULL直接转换为0.0.0.0绕过该getaddrinfo()机制。

于 2015-10-12T10:25:31.673 回答