我见过各种用于在 nginx 上处理双栈 IPv4 和 IPv6 虚拟主机的配置示例。许多都建议采用这种模式:
listen 80;
listen [::]:80 ipv6only=on;
据我所知,这与以下操作完全相同:
listen [::]:80 ipv6only=off;
为什么要使用前者?我能想到的唯一原因是,如果您需要特定于每个协议的附加参数,例如,如果您只想deferred
在 IPv4 上设置。
答案1
那可能是如今,这是您使用前一种构造的唯一原因。
你看到这个的原因是大概nginx 1.3.4 中 的默认值ipv6only
已更改。在此之前,其默认为off
;在较新的版本中,其默认为on
。
这恰好与 Linux 上的 IPV6_V6ONLY 套接字选项以及其他操作系统上的类似选项交互,这些选项的默认值不一定是可预测的。因此,在 1.3.4 之前,需要前一种构造来确保您实际上在监听 IPv4 和 IPv6 上的连接。
对 nginx 默认设置的更改ipv6only
确保了双栈套接字的操作系统默认设置无关紧要。现在,nginx 可以明确绑定到 IPv4、IPv6 或两者,从不依赖操作系统默认创建双栈套接字。
确实,我的 1.3.4 之前的标准 nginx 配置都有第一个配置,而 1.3.4 之后的版本都具有第二个配置。
不过,由于绑定双栈套接字是 Linux 独有的功能,所以我当前的配置现在看起来更像第一个例子,但没有ipv6only
设置,即:
listen [::]:80;
listen 80;
答案2
如果你使用单个 Nginx 实例托管多个 vhost 域,则不能使用单个组合 listen 指令
listen [::]:80 ipv6only=off;
为每个端口指定该参数。Nginx 有一个奇怪的特点,您只能ipv6only
为每个端口指定一次该参数,否则它将无法启动。这意味着您无法为每个 vhost 域服务器块指定该参数。
正如 Michael 提到的,从 Nginx 1.3.4 开始,该ipv6only
参数默认为on
。
因此,如果您想使用单个 Nginx 服务器在 IPv4 和 IPv6 上托管多个域,则必须对每个域服务器块使用两个 listen 指令:
listen 80;
listen [::]:80;
此外,正如 Sander 提到的,使用ipv6only=off
IPv4 地址会转换为 IPv6,这是个缺点。如果您的应用根据 Akismet 或 StopForumSpam 等黑名单进行 IP 检查,则这可能会导致问题,因为除非您构建了反向转换层,否则您的应用将检查垃圾邮件发送者的 IPv4 地址的 IPv6 转换,而该地址与黑名单中的任何 IPv4 地址都不匹配。
答案3
使用ipv6only=off
配置样式,IPv4 地址可能会显示为 IPv6 地址(仅限软件)IPv4 映射的 IPv6 地址例如日志文件、环境变量(REMOTE_ADDR)等等。
答案4
我在使用该代码片段向站点添加 IPv6 支持时遇到一个棘手的问题listen [::]:80 ipv6only=off;
是,当我将其添加到 vhost 时,default_server 已配置为监听 80
和[::]:80
。
nginx
拒绝启动,抱怨该地址已被使用!
listen [::]:80 ipv6only=off;
用两条传统的listen
线代替魔法nginx
就可以顺利开始。
尽管listen [::]:80 ipv6only=off;
手动配置可能很方便,但在自动配置系统中使用时可能会引起严重的麻烦。