Today, 6th of June we celebrate World IPv6 day. Ipv6 is the new standard for IP protocols. IPv6 is important because, as everyone by now should know, the public IPv4 address space is running out. In fact all IPv4 address blocks have already been mostly consumed by registrars and the resource problem is being avoided by recycling old addresses and using NAT-techniques, which cause problems for many VoIP and P2P services. IPv6 also offers better network security (IPsec) built in.
We already wrote about taking IPv6 in use on a workstation earlier. Now we’ll explain how to add it to a web server.
Note, we are deliberately not using old school commands (ifconfig, route, netstat) below, but instead the modern versions (ip and ss). It is time to move on with modern utilities too.
First you need to add a IPv6 address to your network interface. On a Linux server to add a static address edit the file /etc/network/interfaces like this:
auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 83.143.220.158 netmask 255.255.255.224 network 83.143.220.128 broadcast 83.143.220.159 gateway 83.143.220.129 # dns-* options are implemented by the resolvconf package, if installed #dns-nameservers 83.143.216.18 91.90.49.195 8.8.8.8 iface eth0 inet6 static address 2a00:14c0:1:307:aa51::158 netmask 64 gateway 2a00:14c0:1:307::1
The restart the network so that changes take effect:
$ sudo /etc/init.d/networking restart
The interface configuration should show something in the lines of:
$ ip addr show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 52:54:00:87:05:3c brd ff:ff:ff:ff:ff:ff inet 83.143.220.158/27 brd 83.143.220.159 scope global eth0 inet6 2a00:14c0:1:307:aa51::158/64 scope global inet6 fe80::5054:ff:fe87:53c/64 scope link
You may test from another machine running:
$ ping6 2a00:14c0:1:307:aa51::158
You can verify that the routes are sensible using using the -6 option:
$ ip -6 route 2a00:14c0:1:307::/64 dev eth0 proto kernel metric 256 expires 2592027sec fe80::/64 dev eth0 proto kernel metric 256 default via fe80::20c:86ff:fe14:d038 dev eth0 proto kernel metric 1024 expires 1665sec hoplimit 64 default via 2a00:14c0:1:307::1 dev eth0 metric 1024
For route testing you can use the tool traceroute6
. To check that the traffic really flows correctly, try logging in remotely using ssh -6
.
Domain name records for IPv6
Now open in your browser http://[2a00:14c0:1:307:aa51::158]/ to see if you web server servers anything for the IPv6 address. Alternatively you can use the website ipv6proxy.net if you don’t yet have IPv6 configured on your workstation.
Now when the service has a IPv6 address, you can start advertising it by adding a DNS AAAA record after your normal A record:
wp.seravo.fi. A 83.143.220.158 wp.seravo.fi. AAAA 2a00:14c0:1:307:aa51::158
If you want to be extra cool, add a subdomain ipv6 (e.g. ipv6.seravo.fi, ipv6.google.com). With this address it is very visual to test if IPv6 works or not on any browser anywhere.
Configuring web servers Apache or Nginx
Next you need to configure you web server to listen for port 80 on both IPv4 and IPv6.
In Apache you don’t need to configure anything special, as long as the Listen and NameVirtualHost directives don’t specify an IP-address but just port 80 in a generic way:
NameVirtualHost *:80 Listen 80
For Nginx, add inside the server { }
section the following line:
server { listen [::]:80 default_server; listen [::]:443 default_server ssl;
If you are missing a listen line altogether or it looks like listen 80; it means Nginx was listening only for the IPv4 address port 80.
After the change, restart the server (reload is not enough) with:
$ sudo service nginx reload
Confirm with netstat that there indeed are servers listening:
$ sudo ss -6lp State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 :::http :::* users:(("nginx",25706,28),("nginx",25705,28),("nginx",1826,28))
You can test the result with:
curl -I -6 -v ipv6.seravo.fi * About to connect() to ipv6.seravo.fi port 80 (#0) * Trying 2a00:14c0:1:307:aa51::158... connected HTTP/1.1 302 Moved Temporarily Server: nginx