Detail Breakdown On How to Resolve IP Address Conflict on Linux

IP Address Conflict on Linux Main Logo

Detail Breakdown On How to Resolve IP Address Conflict on Linux

Configuring the network interaction of services is not the easiest task and is often performed without a deep understanding of how to configure the system and any settings that effect.

After transitioning services in Docker containers from centos 6 to Centos 7, we encountered a strange position of the web server: it tried to join the service via IPv6, and the service listened only to the IPv4 address. The standard advice in this situation is to disable IPv6 support. But it does not help in the cities. Which one? In this article, we set a goal to collect and explain in detail how applications solve addresses.

The publication will be useful to novice administrators and developers.SmartSpate

After reading this article, you will learn:

  • What is the Linux algorithm for resolving hostnames;
  • How to redefine the logic for defining hostnames;
  • What functions and libraries the OS uses;
  • What traps exist when configuring and how to prevent them;

The Linux operating system has several sources for determining the address by hostname. All the necessary functions for definition is in the GNU C Library (glibc). glibc is essentially a framework and implements many useful functions for the developer by providing its API for simplifying development. Among other things, glibc implements POSIX. Functions such as open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt, login, exit for Linux systems are provided by glibc.

IP Address Conflict on Linux Photo 1

Known to many utility hosts, dig and nslookup use glibc, but are supplied separately.

Now that the developer has the ability to call the getaddrinfo family function from glibc to determine the address, the need arises to configure the return values. For example, to use first /etc/hosts or a query to the DNS server. In glibc, this configuration is done using a schema called Name Service Switch (NSS).

  • If you explain on your fingers, then NSS allows you to set the databases and the order of search in these databases to provide the service. In our case, the service is a search for hostname, and the database can be /etc/hosts or DNS server. This is not the only service that is customizable through NSS, mail alias services are provided, and the user and group search service. You can see the list in the manuals.

Thanks to NSS, you can configure the mentioned databases without rebuilding the applications, at runtime. It is configured in /etc/nsswitch.conf. Below is an example of a config from the standard /etc/nsswitch.conf in Centos 7.

  • The files, DNS, and my hostname are database aliases for searching. files on most systems imply the use of /etc/hosts, DNS base is the DNS server to which the hostname search query will be executed, and my hostname is the most unusual database, about the existence of which few people know and it is not part of the standard delivery in glibc. In some distributions, the mdns4_minimal database is also present. Below is the analysis of these databases.

Bases are used in the order in which they are declared in /etc/nsswitch.conf and if a record is found in the current database, then the output from the chain is returned and the result is returned. If there is no result, the next database is listed in the list. If no result is found in any database, then such a response is given to the glibc query of getaddrinfo. The behavior of the transition to the next base and the conditions for such a transition can be further configured, for example, if the DNS is not available (not to be confused with the absence of a record), complete the chain. A clear and simple explanation of the principle of setting conditions for /etc/nsswitch.conf is given in this article.

Base files, and in particular /etc/hosts, out of the box in Centos 7 looks like this:

You can note that there are two entries for localhost: IPv4 and IPv6 address. It can play a cruel joke and at the end of the story, I’ll tell you why.

  • The DNS database uses the name server specified in the /etc/resolve.conf configuration file to determine the address. Here is an example of my /etc/resolv.conf on the host system:

Nameserver’a are used also by the chain and in the order of their announcement. In my case, the first is a local DNS server (we use dnsmasq) to set the local .priv zone addresses. If there is a match, then the address is returned from the local network. All other requests are sent to the primary DNS server with the address 192.168.100.1.

The base my hostname is present in the delivery of Centos and Ubuntu but is not part of glibc. Without knowing this fact, we spent a lot of time trying to figure out why IPv6 addresses are returned to me to determine the host. It works as follows:

  • When requesting a local hostname (that the hostname command returns), the plugin returns all IP addresses of the public interfaces (ie all except the loopback), in the absence of such interfaces, IPv4 address 127.0.0.2 and IPv6 address:: 1;
  • When requesting a hostname, localhost or localhost.localdomain returns IPv4 address 127.0.0.1 and IPv6 address:: 1;
  • When requesting a hostname ending in .localhost or .localhost.localdomain returns IPv4 address 127.0.0.1 and IPv6 address :: 1;

In the manual, they write about the special logic with the processing of hostname _gateway, but apparently, it’s some kind of patch, since it did not start with Centos 7.

Base mdns4_minimal or mdns_minimal is required for Avahi to work correctly. If necessary, you can refer to the Arch documentation on Avahi, where briefly and clearly given information
on use.

  • Now, when information on the bases and principles of their work is given, it is worth noting the differences in the definition of addresses in different tools, which leads to problems in runtime.

Typically, administrators check hostnames using the host command. This is incorrect, since host, like dig, uses only DNS resolving, but does not use NSS. Nginx, for example, uses the getaddrinfo function, and it uses NSS. This leads to the fact that the hosts hosted in /etc/hosts can work with nginx, but it will not be resolved in other ways. Much worse, when in /etc/hosts are hammered IPv6 address for a hostname, and in DNS settings only IPv4 address is returned. In this case, the administrator can verify that the host command returns only the IPv4 address and calms down, and then the application using getaddrinfo from glibc will start and find the IPv4 address and the IPv6 address for the same host. Error source …

  • To verify the results of each database returned, the documentation recommends using the getent utility.

Below are few examples of working with getent with IPv6 enabled.

The /etc/nsswitch.conf contains the following database chain:


hosts: files dns myhostname

The /etc/hosts contain the following information: 


$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback

The getent ahosts <hostname> command displays a list of all the addresses that you can find. With these settings, it displays the following:


$ getent ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

This command allows you to point to a specific database and find out what the base is. Let’s consider for each base return values:


$ getent -s hosts:files ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

$ getent -s hosts:dns ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

$ getent -s hosts:myhostname ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

If you remove the lines from /etc/hosts for localhost, the output will be modified:


$ getent -s hosts:files ahosts localhost

$ getent -s hosts:dns ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

$ getent -s hosts:myhostname ahosts localhost
::1 STREAM localhost
::1 DGRAM
::1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

Now the base DNS and hostname return the answers, and the files database does not contain data.

For DNS queries, the server is configured in /etc/resolv.conf in my container, for example:


$ cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

On the host machine is installed dnsmasq which proxy and caches the responses of DNS servers. The answer from DNS will depend on the settings of the DNS server to which the request came. RFC 1912 recommends in point 4.1 to configure DNS servers in such a way that localhost points to 127.0.0.1.

Certain zones should always be present in name server configurations:


primary               localhost                                         localhost
primary               0.0.127.in-addr.arpa               127.0
primary              255.in-addr.arpa                         255
primary              0.in-addr.arpa                               0

These are set up to either provide a service for “special”
addresses, or to help eliminate accidental queries for broadcast or
local address to be sent off to the root nameservers. All of these
files will contain NS and SOA records just like the other zone files
you maintain the exception is that you can probably make the SOA
timers very long, with this data, will never change.

The “localhost” address is a “special” address which always refers to the
localhost. It should contain the following line:


localhost.               IN                A                127.0.0.1

In our case, dnsmasq from the box contains entries for localhost, as
RFC recommends.


$ dig +noall +answer localhost ANY @127.0.0.1
localhost.           0             IN               A                       127.0.0.1
localhost.           0             IN              AAAA            ::1

It turns off either by deleting entries from /etc/hosts on the DNS server itself, or by turning on the no-hosts option in /etc/dnsmasq.conf.

After enabling the get option for the base myhostname will return a non-empty result, but as noted above, with the included myhostname, IPv4, and IPv6 address will be returned. On systems with static IP addresses, you can safely turn off the myhostname plugin and configure local hosts using /etc/hosts. An alternative is to disable IPv6.

The status of IPv6 on the server can be obtained from the kernel parameters. The value 0 is returned when IPv6 is on, and 1 is turned off.


$ sysctl net.ipv6.conf.all.disable_ipv6 net.ipv6.conf.default.disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0

In the ifconfig output, the IPv6 listening interfaces contain the inet6 line. Below is an example of output with IPv6 turned off and on, respectively:


# diabled
$ ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.101.5 netmask 255.255.255.0 broadcast 0.0.0.0
ether 02:42:c0:a8:65:05 txqueuelen 0 (Ethernet)
RX packets 15789549 bytes 2553533549 (2.3 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9783999 bytes 1318627420 (1.2 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1 (Local Loopback)
RX packets 606047 bytes 67810892 (64.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 606047 bytes 67810892 (64.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

# enabled
$ ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.101.5 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::42:c0ff:fea8:6505 prefixlen 64 scopeid 0x20<link>
ether 02:42:c0:a8:65:05 txqueuelen 0 (Ethernet)
RX packets 15787641 bytes 2553216408 (2.3 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9782965 bytes 1318487919 (1.2 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 605949 bytes 67799887 (64.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 605949 bytes 67799887 (64.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Disable IPv6 by calling it:


$ sysctl -w net.ipv6.conf.all.disable_ipv6=1
$ sysctl -w net.ipv6.conf.default.disable_ipv6=1

What will change after shutdown? I rolled back all configs to standard ones: in /etc/hosts there is localhost with IPv4 and IPv6 addresses, in dnsmasq option no-hosts is turned off.

Disconnected IPv6 commands above and the output of intent is as follows:


$ getent -s hosts:files ahosts localhost
127.0.0.1 STREAM localhost
127.0.0.1 DGRAM
127.0.0.1 RAW
127.0.0.1 STREAM
127.0.0.1 DGRAM
127.0.0.1 RAW

$ getent -s hosts:dns ahosts localhost
127.0.0.1 STREAM localhost
127.0.0.1 DGRAM
127.0.0.1 RAW

$ getent -s hosts:myhostname ahosts localhost
127.0.0.1 STREAM localhost
127.0.0.1 DGRAM
127.0.0.1 RAW

Wow, in the first conclusion, we have duplicated the address 127.0.0.1. To understand why this happens, it’s worth looking at the source code glibc and the utility code getent.

Below is a piece of the getent utility code.


/* This is for hosts, but using getaddrinfo */
static int
ahosts_keys_int (int af, int xflags, int number, char *key[])
{
// ...
hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME
| idn_flags | xflags);
hint.ai_family = af;

for (i = 0; i < number; ++i)
{
struct addrinfo *res;

if (getaddrinfo (key[i], NULL, &hint, &res) != 0)
result = 2;
else
{
struct addrinfo *runp = res;

while (runp != NULL)
{
// printf goes here
}

freeaddrinfo (res);
}
}

return result;

The AI_V4MAPPED flag of the getaddrinfo function maps IPv6 addresses to IPv4 if IPv6 addresses were not found as a result of polling the database. The AI_ADDRCONFIG flag will force getaddrinfo to check for the presence of IPv6/IPv4 addresses configured on the system and in the absence of at least one IPv6/IPv4 address, IPv6/IPv4 will not be returned regardless of what the particular database will respond.

  • Since getent has both flags enabled, and in /etc/hosts the addresses 127.0.0.1 and :: 1 are assigned to localhost, getaddrinfo will get hosts from NSS (in the example above we discussed this database), addresses 127.0.0.1 and :: 1, then without detecting any IPv6 addresses in the system (they are turned off by kernel parameters) and will make the mapping :: 1 -> 127.0.0.1.

To better understand this concept, I’ll give examples with the output of getaddrinfo on the same system, with different settings for ai_flags and ai_family. In /etc/hosts, localhost IPv4, and IPv6 addresses are enabled.

The source code:


#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];

if (argc != 2) {
fprintf(stderr,"usage: getaddrinfo <hostname>\n");
return 1;
}

printf("IP addresses for %s:\n\n", argv[1]);

int AI_FLAGS_TO_CHECK[5] = { AI_V4MAPPED, AI_V4MAPPED | AI_ALL, AI_ADDRCONFIG, AI_V4MAPPED | AI_ADDRCONFIG, AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG };
int AI_FAMILY_TO_CHECK[3] = { AF_INET, AF_INET6, AF_UNSPEC };
int ai_flags, flag_no, ai_family, family_no;

for (family_no = 0; family_no < sizeof(AI_FAMILY_TO_CHECK) / sizeof(int); family_no++) {
for (flag_no = 0; flag_no < sizeof(AI_FLAGS_TO_CHECK) / sizeof(int); flag_no++) {
ai_family = AI_FAMILY_TO_CHECK[family_no];
if (ai_family == AF_INET) {
printf("[AF_INET] ");
} else if (ai_family == AF_INET6) {
printf("[AF_INET6] ");
} else if (ai_family == AF_UNSPEC) {
printf("[AF_UNSPEC] ");
} else {
fprintf(stderr, "Unknown family\n");
return 2;
}
ai_flags = AI_FLAGS_TO_CHECK[flag_no];
if (ai_flags & AI_V4MAPPED) {
printf("AI_V4MAPPED ");
}

if (ai_flags & AI_ALL) {
printf("AI_ALL ");
}

if (ai_flags & AI_ADDRCONFIG) {
printf("AI_ADDRCONFIG ");
}

printf("\n");

memset(&hints, 0, sizeof hints);
hints.ai_flags = ai_flags;
hints.ai_family = ai_family;
hints.ai_socktype = SOCK_STREAM;

if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
continue;
//return 3;
}

for (p = res; p != NULL; p = p->ai_next) {
void *addr;
char *ipver;

if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else if (p->ai_family == AF_INET6) {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
} else {
continue;
}

inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}

freeaddrinfo(res);
}

printf("--------------\n\n");
}
return 0;
}


# ./getaddrinfo localhost
IP addresses for localhost:

[AF_INET] AI_V4MAPPED
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_INET] AI_V4MAPPED AI_ALL
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_INET] AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_INET] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_INET] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
--------------

[AF_INET6] AI_V4MAPPED
IPv6: ::1
[AF_INET6] AI_V4MAPPED AI_ALL
IPv6: ::ffff:127.0.0.1
IPv6: ::ffff:127.0.0.1
IPv6: ::1
[AF_INET6] AI_ADDRCONFIG
getaddrinfo: Name or service not known
[AF_INET6] AI_V4MAPPED AI_ADDRCONFIG
getaddrinfo: Name or service not known
[AF_INET6] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
getaddrinfo: Name or service not known
--------------

[AF_UNSPEC] AI_V4MAPPED
IPv4: 127.0.0.1
IPv6: ::1
[AF_UNSPEC] AI_V4MAPPED AI_ALL
IPv4: 127.0.0.1
IPv6: ::1
[AF_UNSPEC] AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_UNSPEC] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
[AF_UNSPEC] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 127.0.0.1
IPv4: 127.0.0.1
--------------

The output shows that with _aifamily equal to _AIUNSPEC (return both IPv4 and IPv6) and without the AI_ADDRCONFIG flag getaddrinfo returns two addresses, IPv4 and IPv6, which many administrators are not obese to see. This happens regardless of whether IPv6 is disabled in the kernel parameters. If you remove the address :: 1 in /etc/hosts, then IPv6 addresses completely disappear from the getaddrinfo output (with the AF_UNSPEC flag).

  • With IPv6 enabled and the presence of :: 1 in /etc/hosts, IPv4 and IPv6 will be returned. To resolve them, the IPv6 address needs to comment out the IPv6 address in /etc/hosts. If the addresses are found in /etc/hosts, the base glibc will not get into DNS and myhostname.

It remains to check how getaddrinfo behaves for the DNS database. To do this, we will leave /etc/nsswitch.conf for hosts only DNS database and resolve google.com.

The output is below with IPv6 enabled.


$ sysctl -w net.ipv6.conf.default.disable_ipv6=0
$ sysctl -w net.ipv6.conf.all.disable_ipv6=0

$ ./getaddrinfo google.com
IP addresses for google.com:

[AF_INET] AI_V4MAPPED
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ALL
IPv4: 216.58.215.78
[AF_INET] AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 216.58.215.78
--------------

[AF_INET6] AI_V4MAPPED
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_V4MAPPED AI_ALL
IPv6: ::ffff:216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_ADDRCONFIG
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_V4MAPPED AI_ADDRCONFIG
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv6: ::ffff:216.58.215.78
IPv6: 2a00:1450:401b:806::200e
--------------

[AF_UNSPEC] AI_V4MAPPED
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_V4MAPPED AI_ALL
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_ADDRCONFIG
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
--------------

Here is the output with turned IPv6 off :


$ sysctl -w net.ipv6.conf.all.disable_ipv6=1
$ sysctl -w net.ipv6.conf.default.disable_ipv6=1

$ ./getaddrinfo google.com
IP addresses for google.com:

[AF_INET] AI_V4MAPPED
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ALL
IPv4: 216.58.215.78
[AF_INET] AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_INET] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 216.58.215.78
--------------

[AF_INET6] AI_V4MAPPED
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_V4MAPPED AI_ALL
IPv6: ::ffff:216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_INET6] AI_ADDRCONFIG
getaddrinfo: Name or service not known
[AF_INET6] AI_V4MAPPED AI_ADDRCONFIG
getaddrinfo: Name or service not known
[AF_INET6] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
getaddrinfo: Name or service not known
--------------

[AF_UNSPEC] AI_V4MAPPED
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_V4MAPPED AI_ALL
IPv4: 216.58.215.78
IPv6: 2a00:1450:401b:806::200e
[AF_UNSPEC] AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_UNSPEC] AI_V4MAPPED AI_ADDRCONFIG
IPv4: 216.58.215.78
[AF_UNSPEC] AI_V4MAPPED AI_ALL AI_ADDRCONFIG
IPv4: 216.58.215.78
--------------

As you can see, the situation with AI_ADDRCONFIG is very similar.

Finally, we will give an example of how not to take into account all of the above to get into trouble.

IPv6 is enabled, /etc/nsswitch.conf is standard one.


$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback

$ grep hosts /etc/nsswitch.conf
hosts: files dns myhostname

$ cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

$ sysctl net.ipv6.conf.all.disable_ipv6 net.ipv6.conf.default.disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0

  • What will return host localhost or dig ANY localhost?
  • What will return getaddrinfo, for example, with flags like nginx?

$ dig +noall +answer ANY localhost @127.0.0.11
localhost. 0 IN A 127.0.0.1

$ host localhost
localhost has address 127.0.0.1

$ ./getaddrinfo localhost
IP addresses for localhost:

[AF_UNSPEC] AI_ADDRCONFIG
IPv6: ::1
IPv4: 127.0.0.1

The nginx will try to connect to two addresses: 127.0.0.1 and :: 1, and the application may not expect this. Source for errors.

What can be inferred from all written?

  • If you are developing an application that works with the network, then consider that IPv6 can be disabled;
  • When configuring the server, consider the presence of NSS and the order of the checks, use getent or my code for verification;
  • If you do not know how the application works, then if you have the source code, you can see what flags are resolving
    address and check the system settings;
  • If there are no source codes, then it’s possible to make an assumption about the flags used in the output of strace.