我已经看过各种用于在nginx上处理双栈IPv4和IPv6虚拟主机的配置示例。许多人建议使用这种模式:据我所见,这实现了与以下内容完全相同的功能:

listen 80;
listen [::]:80 ipv6only=on;


您为什么要使用前者?我能想到的唯一原因是,您是否需要特定于每种协议的其他参数,例如,如果您只想在IPv4上设置deferred

评论

推迟与IP堆栈版本无关,它是TCP选项。

可以,但是您可以在listen指令中进行设置,并且该选项适用于每个host:port对。

哼,我真的无法想象您会想要这样做的情况。我认为唯一的原因是历史,而迈克尔·汉普顿(Michael Hampton)则将其钉牢。

#1 楼

这些天可能是您使用前一种构造的唯一原因。
您看到的原因可能是nginx 1.3.4中ipv6only的默认值已更改。在此之前,它默认为off;在较新的版本中,其默认值为on。这恰好与Linux上的IPV6_V6ONLY套接字选项以及其他操作系统上的类似选项(默认值不一定可预测)交互。因此,1.3.4之前的版本需要使用之前的构造,以确保您实际上正在侦听IPv4和IPv6上的连接。

ipv6only的nginx默认更改可确保操作系统默认为Dual堆栈套接字无关紧要。现在,nginx要么显式绑定到IPv4,IPv6或两者都绑定,从不依赖于操作系统默认情况下不会创建双堆栈套接字。

实际上,我在1.3.4之前的标准nginx配置具有第一个配置和1.3.4之后的版本都具有第二个配置。

尽管绑定双堆栈套接字是仅Linux的事情,所以我当前的配置现在看起来更像第一个示例,但是不带ipv6only套装,用于:

listen [::]:80;
listen 80;


评论


像OpenBSD一样,某些操作系统根本不使用双ipv4和ipv6套接字,因此您将不得不收听两次。

–贾斯汀·柯马克(Justin Cormack)
2015年3月9日在20:47

@JustinCormack是的,您是对的,并且我已经考虑了一段时间。直到现在才更新此帖子。

–迈克尔·汉普顿
17年2月2日,下午1:59

听本地主机:8080;似乎同时听(1.12.2)和使用proxy_pass http:// localhost:8080会在:: 1和127.0.0.1之间进行负载平衡-我必须为ipv6添加一行以在日志set_real_ip_from 127.0.0.1中获取真实ip ; set_real_ip_from :: 1; real_ip_header X-Forwarded-For;

– Antony Gibbs
18年2月6日在17:02

#2 楼

如果使用单个Nginx实例托管多个vhost域,则不能对每个域使用单个组合的listen指令

listen [::]:80 ipv6only=off;


。 Nginx有一个奇怪的怪癖,您只能为每个端口指定一次ipv6only参数,否则它将无法启动。这意味着您不能为每个虚拟主机域服务器块指定它。

正如Michael所述,从Nginx 1.3.4开始,ipv6only参数默认为on

因此,如果要在IPv4和IPv6上同时托管多个域,单个Nginx服务器,您必须为每个域服务器块使用两个侦听指令:

listen 80;
listen [::]:80; 


另外,如Sander所述,使用ipv6only=off的缺点是IPv4地址是转换为IPv6。如果您的应用程序针对Akismet或StopForumSpam之类的黑名单进行IP检查,这可能会导致问题,因为除非您在反向转换层中进行构建,否则您的应用程序将检查垃圾邮件发送者的IPv4地址的IPv6转换,该IPv6地址与该地址中的任何IPv4地址都不匹配黑名单。

评论


是的,这与我提到的递延指令和其他按协议指令相同。如果由于您说的原因而可以将它们与listen指令分开指定,这将很有用。

–同步
15年4月24日在10:22

问题的核心是,您需要为每个域分别指定listen指令。否则会发生什么?该站点可以通过ipv4和ipv6正常运行,它将显示nginx欢迎页面。劳氏

–银月
2015年12月9日下午6:57

感谢您的详尽解释!当我为同一端口两次指定ipv6only = off时,我得到一个令人困惑的错误。您的答案解决了问题!

–user243345
16年4月24日在14:38

另外,如果您要同时使用2个虚拟主机,则都可以监听443:监听443;听[::]:443; 。使用监听[::]:80 ipv6only = off;将抛出一个nginx错误,表明该端口已被使用

–lukeaus
16 Jul 20'6:37



#3 楼

使用ipv6only=off配置样式时,在日志文件,环境变量(REMOTE_ADDR)等中,IPv4地址可能会使用(仅限软件)IPv4映射的IPv6地址显示为IPv6地址。

评论


是的,它们以这种方式显示。

–迈克尔·汉普顿
2014年10月20日在17:11

#4 楼

据我了解(根据http://nginx.org/en/docs/http/ngx_http_core_module.html#listen上的文档),仅使用

listen 80;


...足以在同一端口上同时传输IPv4和IPv6流量。

评论


这已经建立,并在问题中提到。请查看其他答案以了解区别。

–同步
17 Mar 9 '17 at 7:46

它不适合我,我两个都需要。 wget和curl在使用ipv6时失败,直到我添加了“ listen [::]:80 ipv6only = on;”行。

–罗勒A
17 Mar 30 '17 at 14:55

这对我不起作用,而且我在文档中找不到它说会起作用的地方。

–gsingh2011
20年7月23日在7:15

#5 楼

在向带有listen [::]:80 ipv6only=off;片段的站点添加IPv6支持时遇到的一个令人讨厌的问题是,当我将其添加到虚拟主机中并且default_server已配置为侦听80[::]:80时。

nginx拒绝启动,抱怨地址已在使用中!

用两条传统的listen [::]:80 ipv6only=off;替换魔术listen可以使nginx正常启动。

在手动配置中,尽可能方便地使用listen [::]:80 ipv6only=off;,在自动配置系统中使用时可能会造成麻烦。