1. Introduction

NGINX is a widely-used cross-platform multipurpose server. Due to its many possible roles in a networking environment, it also supports IPv6 as a network layer protocol choice. However, not all networks and systems are configured for this Internet Protocol (IP) version.

In this tutorial, we’ll explore how to disable IPv6 in NGINX. First, we create a basic NGINX example setup. Next, we discuss IPv6 connectivity in NGINX. Finally, we discuss disabling the use of IPv6 for inbound and outbound queries.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.

2. Example NGINX Setup

For our scenario, let’s use a minimal configuration:

server {
  listen 6660;

  location / {
    resolver   1.1.1.1;
    proxy_pass http://gerganov.com;
  }
}

**This server [listen]s to port 6660 and redirects any requests as a proxy_pass to http://gerganov.com, using 1.1.1.1 as the DNS resolver**.

There are several ways to include such a configuration in NGINX.

2.1. Separate Configuration File

On the one hand, we can create a new forward.conf file in the current working directory:

$ cat forward.conf
events { }

http {
  server {
    listen 6660;

    location / {
      resolver   1.1.1.1;
      proxy_pass http://gerganov.com;
    }
  }
}

Then, we simply use this file path after the -c option:

$ nginx -c forward.conf

If we don’t want to start NGINX and point to the file manually, we can copy the forward.conf file to /etc/nginx/conf.d and restart NGINX:

$ cp forward.conf /etc/nginx/conf.d/forward.conf
$ systemctl restart nginx

In this case, we control NGINX with systemctl.

2.2. Site File

Alternatively, we can create a new file at /etc/nginx/sites-available/forward:

$ cat /etc/nginx/sites-available/forward
server {
  listen 6660;

  location / {
    resolver              1.1.1.1;
    proxy_pass            http://gerganov.com;
  }
}

Notably, we strip the events and http sections. Finally, we link /etc/nginx/sites-available/forward to /etc/nginx/sites-enabled/forward with ln and start NGINX:

$ ln --symbolic /etc/nginx/sites-enabled/forward /etc/nginx/sites-available/forward
$ systemctl start nginx

At this point, in either case above, if our local server name hostname and IP address are xost and 192.168.6.66, respectively, querying http://localhost:6660 or http://xost:6660 would forward the requests to http://gerganov.com, resolving the DNS name with DNS server 1.1.1.1.

3. NGINX IPv6 Connectivity

With the previous setup, we should be all set on the NGINX side. However, the functionality also depends on our network interface configuration.

Specifically, we might not have an IPv6 address when our proxy destination does. In our case, if the DNS server resolves gerganov.com to an IPv6 address, NGINX may send a request with that IP version. If we don’t have the appropriate configuration, an error might occur:

2023/06/06 00:06:56 [error] 10666#0: *1010 connect() to 2001:db8:dead:beef::::666 failed
  (101: Network is unreachable) while connecting to upstream,
  client: 192.168.6.66, server: gerganov.com,
  request: "GET / HTTP/1.1",
  upstream: "https://2001:db8:dead:beef::::666/", host: "gerganov.com"

Here, we see the 2001:db8:dead:beef::::666 IPv6 address for the server while our client tries to connect from an interface with only the aforementioned 192.168.6.66 IPv4 address. Let’s confirm this with ip and its address category for eth0, the name of the interface in question:

$ ip address show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 01:00:00:66:60:10 brd ff:ff:ff:ff:ff:ff
    inet 192.168.6.66/24 brd 192.168.6.255 scope global eth0
       valid_lft forever preferred_lft forever

Now, let’s see how to tell NGINX to avoid IPv6 addresses when performing requests.

4. Disable NGINX IPv6

There are several ways to stop IPv6 resolutions and queries. Let’s explore them.

4.1. Default Site

Depending on our setup, the /etc/nginx/sites-enabled/default file might cause trouble:

$ cat /etc/nginx/sites-enabled/default
[...]
server {
        listen 80 default_server;
        listen [::]:80 default_server;
[...]

With its default listen [::]:80 default_server statement, this setup accepts IPv6 requests. Although the inbound queries alone can be a problem to process, we also open the possibility of forwarding IPv6.

To correct that, we can comment or remove the line.

4.2. Prevent Resolver IPv6

In our particular case and others that involve a DNS resolver statement, we can also leverage another approach:

server {
  listen 6660;

  location / {
    resolver              1.1.1.1 ipv6=off;
    set $empty "";
    proxy_pass            http://gerganov.com$empty;
  }
}

The ipv6=off statement disables IPv6 resolutions, but there are important considerations:

  • the option is only available in NGINX versions after 1.5.8
  • internal resolution is only used for proxy_pass with variables
  • we introduce an $empty variable to force dynamic resolution

Sometimes, especially when not using proxy_pass, this option may not be enough.

4.3. System Settings

In general, although a heavy-handed approach, preventing the system from using IPv6 should also stop NGINX from doing so.

For example, we can configure the related general and interface-specific settings and write them to /etc/sysctl.conf:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
net.ipv6.conf.eth1.disable_ipv6 = 1
net.ipv6.conf.eth2.disable_ipv6 = 1
net.ipv6.conf.eth3.disable_ipv6 = 1

To ensure these settings take effect, it’s best to not only run sysctl -p and reload NGINX but also reboot the system.

4.4. Other Servers

In NGINX configurations like fastcgi_pass and others that refer to the local machine, we can have a row that uses localhost:

fastcgi_pass localhost:6660

In such cases, we can replace localhost with 127.0.0.1 to avoid IP address version discrepancies:

fastcgi_pass 127.0.0.1:6660

Again, removing the need for resolving names prevents the possibility of using an IPv6 instead of an IPv4 address.

5. Summary

In this article, we explored several methods to limit or prevent the use of IPv6 in NGINX.

In conclusion, even if some NGINX features don’t stop inbound or outbound IPv6 queries, we should always be able to disable the IP address version globally.