This site uses cookies for analytics. By continuing to browse this site, you agree to use this.  Learn more

How to distinguish IPv6 and IPv4 traffic with nginx

A simple way to support IPv6 only reachable content

Posted on Jan. 27, 2019

Motivation

We at ungleich are currently establishing some IPv6 only services. Some of our web servers are on IPv6 only networks, some are still on dual stack (IPv6 and IPv4) networks.

Some of the content we create will only be available to IPv6 users in the near future, even if the web server itself is on a dual stack server. For that reason we needed to find a way to distinguish requests that come in by IPv4 and IPv6.

ipv6-bridge-1.jpg

nginx and the geo directive

Many of our web services are using nginx as a proxy/load balancer, which supports the geo directive that lets us map a variable based on the source IP address. In our case we only want to distinguish IPv6 from IPv4 traffic, so we used the following code:

# stays empty if not matched
geo $ipv4 {
    0.0.0.0/0 ipv4;
}
...

server {
    listen 443;
    listen [::]:443;

...

    location / {
        # If empty -> is IPv6
        if ($ipv4) {
                return 302 https://ungleich.ch/en-us/cms/blog/2019/01/27/how-to-distinguish-ipv6-and-ipv4-traffic-with-nginx/;
        }
...
    }
}

feelsgood.jpg

So in this sample configuration, we redirect IPv4 users of that particular web service to this blog article. You could obviously also turn it the other way round and match on IPv6 and then take an action on it:

geo $ipv6 {
   ::0/0 ipv6;
}

Or if you want to be more explicit:

geo $iptype {
   ::0/0 ipv6;
   0.0.0.0/0 ipv4;
}

We hope this blog article is of help for you!

penguin-chat-banner.jpg