您是否需要在 nginx 中使用单独的 IPv4 和 IPv6 侦听指令?

Syn*_*hro 86 nginx ipv6 ipv4

我看过各种配置示例,用于在 nginx 上处理双栈 IPv4 和 IPv6 虚拟主机。许多人建议这种模式:

listen 80;
listen [::]:80 ipv6only=on;
Run Code Online (Sandbox Code Playgroud)

据我所知,这与以下内容完全相同:

listen [::]:80 ipv6only=off;
Run Code Online (Sandbox Code Playgroud)

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

Jef*_*man 78

如果您使用单个 Nginx 实例托管多个 vhost 域,则不能使用单个组合监听指令

listen [::]:80 ipv6only=off;
Run Code Online (Sandbox Code Playgroud)

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

正如迈克尔所说,从 Nginx 1.3.4 开始,ipv6only参数默认为on.

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

listen 80;
listen [::]:80; 
Run Code Online (Sandbox Code Playgroud)

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

  • 是的,这与我提到的关于 `deferred` 和其他每协议指令相同。如果出于您所说的原因,可以将它们与 listen 指令分开指定,那将会很有用。 (2认同)
  • 谢谢你的详尽解释!当我两次为同一个端口指定 `ipv6only=off` 时,我遇到了一个令人困惑的错误。你的回答解决了问题! (2认同)
  • 此外,如果您想使用 2 个虚拟主机都监听 443:```监听 443;听 [::]:443;``` . 使用 ```listen [::]:80 ipv6only=off;``` 会抛出端口已经在使用中的 nginx 错误 (2认同)

Mic*_*ton 60

这可能您现在使用前一种构造的唯一原因。

您看到这种情况的原因可能ipv6onlynginx 1.3.4中更改了默认值。在此之前,它默认为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;
Run Code Online (Sandbox Code Playgroud)

  • 某些操作系统根本不支持双 ipv4 和 ipv6 套接字,例如 OpenBSD,因此您将不得不听两次。 (5认同)

San*_*ann 17

使用ipv6only=off配置样式,IPv4 地址可能会使用(纯软件)IPv4 映射 IPv6 地址显示为IPv6 地址,例如日志文件、环境变量 (REMOTE_ADDR) 等。

  • 是的,它们以这种方式显示。 (3认同)

fev*_*lou 9

据我了解(并根据http://nginx.org/en/docs/http/ngx_http_core_module.html#listen上的文档),listen 80;如果您希望在同一端口传输 IPv4 和 IPv6 流量,则使用 just 就足够了。

截至 2021 年 11 月的修订答案

截至 2021 年 11 月,使用最新的 Nginx(来自官方存储库),例如在 Ubuntu 18.04 或 20.04 上,我可以确认对于常规(=非默认)Nginx 虚拟主机,这适用于 IPv4 和 IPv6 流量:

listen [::]:80;

...如果您对 HTTPS 流量使用单独的块:

listen [::]:443 ssl http2;

ipv6only=off标志只能在 Nginx 的“默认”虚拟主机中引用一次(当没有域可以映射到虚拟主机时 Nginx 使用的虚拟主机)。

例如:

server {
    listen [::]:80 default_server ipv6only=off;

    # rest of your Nginx vhost config goes here...
}

server {
    listen [::]:443 default_server ssl http2 ipv6only=off;

    # rest of your Nginx vhost config goes here...
}
Run Code Online (Sandbox Code Playgroud)

显然,如果您的 Nginx 设置使用单个虚拟主机,那么您只需要后一个配置。

  • 它不适合我,我两者都需要。使用 ipv6 时 wget 和 curl 会失败,直到我添加了“listen [::]:80 ipv6only=on;”行 (4认同)