IPv6 in Practice


IPv6 for Cloud Servers

Frankly speaking, the Internet lion’s share operates on IPv4. There are some living islands of IPv6 in Asia, plus several big sites, (such as google.com, facebook.com) respond via IPv6.

But it’s better to use IPv6. The more websites will be ready to operate using IPv6, the easier and simpler conversion will be. Thus, it’s a relevant investment in the future.

What does IPv6 mean for a particular cloud server from a practical point of view?

  • IPv4 users will keep visiting websites that use IPv4
  • IPv6 users will be able to go to IPv6 server address only if this address is specified in DNS (AAAA record)
  • Outgoing connections from a server to IPv4-only nodes will use IPv4
  • Outgoing connections from a server to the nodes with IPv6 and IPv4 addresses will use IPv6 addresses

There’s an unofficial competition between Cloud server services and the Сloud storage as for having bigger IPv6 traffic. Until today the Cloud storage has been winning. But there’s a chance for Cloud servers to leave it behind.

IPv6 traffic will mainly go to:

  • Google services
  • If you setup an AAAA record for the domain, the Google robot will come via IPv6. If you have a web-crawler or fetch to other websites, it will also prefer IPv6.

IPv6 in Real Life

There’s a popular opinion that all modern OS support IPv6 out-of-the-box, that everything is so simple and operating. But other people say that it will have a great number of bugs. Experience has proven that there will be plenty of them anyway, but IPv6 will still work.

For instance, dual stack means that we should think each time IPv6 appears (e.g. outgoing connections). As soon as you have dual stack, all of your utilities (from wget to ssh) will start using IPv6 instead of IPv4. Some companies register an AAAA for the domain, but forget to setup a web server. It turns weirdness.

Postgresql and IPv6

PostgreSQL has always been famous for its great set of data types, ranging from geometric objects to money. IP addresses are also in the set. There are two types: inet and cidr. Both of them store an IP address and a mask. inet stores a node address (i.e. there can be non-zero bits in the null zone under a mask), while cidr stores networks (i.e. host addresses in the null zone are not permitted). It’s actually the same, but if we try to write a host address into cidr, it will return an error.

There’s the same type for IPv4 and IPv6. As for, dimension, it is defined automatically.

The following operations are feasible: scalar addition, scalar subtraction, in, not in comparisons of all kind, overlaying ranges, equalities, etc. As for IPv4, it allowed to implement everything you want. For instance, to make IPv4 distribution, we should just take max_ipv4 and make +1. Then check, whether it’s in the permitted range for allocation.

As for IPv6, either /64 addresses are allocated, or /48 in case of allocating routable networks. In order to get the next /48, we should take the last allocated one and execute max_ipv6 + 1208925819614629174706176 (2128-48=280). All is fine, but bigint in Postgres is just a 64-bit number that can not even store 264, let alone 280. In other words, such a “plus” try will lead to an error due to way too big size of the added scalar. Thus, the mechanism of IPv6 network control is absolutely broken. Our workaround is implementing inet/cidr in persist (Haskell library for working with DBMS) and self-contained mathematics. The problem has been reported to the upstream, and there’s no solution (as for 9.2) found yet.

Multiple IPv6. Interface, DAD and nginx.

The only way of writing multiple IPv6 addresses on the interface is using post and pre sections with the help of ifconfig. An address appears on the interface but not at once, as DAD (Duplicate address detection) starts operating. Put simply, the computer asks, whether anyone has its address and waits for a respond. This protocol allows avoiding repeated addresses. However, ifconfig finishes its work on the interface configuration without waiting in DAD is completed.

As a result, if nginx (or any other server) has a setting for an appropriate address, but not an “asterisk”, when we try to make listen, the server gets an error and does not listen. It’s a race condition, which you can notice during the server load (as in other cases DAD will finish before the server start/restart happened). Debugging this problem has been quite annoying.

Periods in IPv6 Address

Don’t believe it? Think there are colons only?

:: is a valid IPv6 address, though it’s not used in the Internet.

So to say, congrats, if you’ve hoped that regular expressions for IPv6 addresses in the interface would be simple…

routing advertisement && forwarding

If we tell Linux that it is a router now, it will stop trusting routing advertisement. In particular, if a node receives routes from RA only, after the routing is turned on it stops trusting RA. Thus, IPv6 network stops operating. If you want to have both RA and forwarding, specify RA value as 2 (net.ipv6.conf.eth0.accept_ra=2). If the advertisements service (radvd) is started, chose carefully the advertisements to trust. Trusting your own advertisements is ridiculous and is not working.



Ropes — Fast Strings

Most of us work with strings one way or another. There’s no way to avoid them — when writing code, you’re doomed to concatinate strings every day, split them into parts and access certain characters by index. We are used to the fact that strings are fixed-length arrays of characters, which leads to certain limitations when working with them. For instance, we cannot quickly concatenate two strings. To do this, we will at first need to allocate the required amount of memory, and then copy there the data from the concatenated strings.