Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WSL 2 DNS resolver is completely confused, reports addresses of zone nameservers, not just addresses of destination host #6051

Closed
mirabilos opened this issue Oct 7, 2020 · 4 comments
Labels

Comments

@mirabilos
Copy link

Environment

Windows build number: `Microsoft Windows [Version 10.0.19041.508]`
Your Distribution version: Debian 10
Whether the issue is on WSL 2 and/or WSL 1: `Linux version 4.19.128-microsoft-standard (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 SMP Tue Jun 23 12:58:10 UTC 2020`

Steps to reproduce

I’m trying to use the built-in DNS resolver to connect to all (ip,port) tuples of a destination host/port. I’ve built a reduced example that just prints them and then exits:

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

static int
do_resolve(const char *host, const char *service)
{
        int i, rv = 1;
        struct addrinfo *ai, *ap;
        char nh[INET6_ADDRSTRLEN];
        char np[/* 0‥65535 + NUL */ 6];

        if (!(ap = calloc(1, sizeof(struct addrinfo))))
                err(1, "calloc");
        ap->ai_family = AF_UNSPEC;
        ap->ai_socktype = SOCK_DGRAM;
        ap->ai_flags = AI_ADDRCONFIG; /* note lack of AI_V4MAPPED */
        switch ((i = getaddrinfo(host, service, ap, &ai))) {
        case EAI_SYSTEM:
                err(1, "getaddrinfo");
        default:
                errx(1, "%s returned %s", "getaddrinfo", gai_strerror(i));
        case 0:
                break;
        }
        free(ap);

        for (ap = ai; ap != NULL; ap = ap->ai_next) {
                switch ((i = getnameinfo(ap->ai_addr, ap->ai_addrlen,
                    nh, sizeof(nh), np, sizeof(np),
                    NI_NUMERICHOST | NI_NUMERICSERV))) {
                case EAI_SYSTEM:
                        warn("getnameinfo");
                        if (0)
                                /* FALLTHROUGH */
                default:
                          warnx("%s returned %s", "getnameinfo",
                            gai_strerror(i));
                        fprintf(stderr, "Trying (unknown)...\n");
                        break;
                case 0:
                        fprintf(stderr, "Trying [%s]:%s...\n", nh, np);
                        rv = 0;
                        break;
                }

        }

        freeaddrinfo(ai);
        return (rv);
}


int
main(int argc, char *argv[])
{
        if (argc != 3)
                errx(1, "Usage: %s servername port", argv[0]);
        if (do_resolve(argv[1], argv[2]))
                errx(1, "Could not connect to server or received no response");
        return (0);
}

After compiling this, on a normal GNU/Linux system (ignore the port, just use 1 for this purpose) I get:

$ ./a.out www.heise.de 1                                                                                        
Trying [2a02:2e0:3fe:1001:7777:772e:2:85]:1...
Trying [193.99.144.85]:1...

On WSL 1, I get the same output, for what it’s worth.

On WSL 2, I get spammed with:

$ ./a.out www.heise.de 1
Trying [193.99.144.85]:1...
Trying [212.19.40.14]:1...
Trying [193.99.145.37]:1...
Trying [212.19.48.14]:1...
Trying [193.98.1.200]:1...
Trying [212.19.40.14]:1...
Trying [193.99.145.37]:1...
Trying [212.19.48.14]:1...
Trying [193.98.1.200]:1...
Trying [2a02:2e0:a:b:c:d:e:f]:1...
Trying [2a00:e68:14:800::d1ce]:1...
Trying [2a02:2e0:1:2:3:4:5:6]:1...
Trying [2a02:2e0:3fe:1001:7777:772e:2:85]:1...
Trying [2a02:2e0:a:b:c:d:e:f]:1...
Trying [2a00:e68:14:800::d1ce]:1...
Trying [2a02:2e0:1:2:3:4:5:6]:1...

These are completely wrong; for example 193.99.145.37 is one of the nameservers for heise.de. and not one of the A and AAAA RRs for the hostname www.heise.de.

Using external nameservers fixes this…

$ echo nameserver 8.8.8.8 | sudo dd of=/etc/resolv.conf 2>/dev/null
$ ./a.out www.heise.de 1
Trying [193.99.144.85]:1...
Trying [2a02:2e0:3fe:1001:7777:772e:2:85]:1...

… so this is clearly an issue in the WSL-provided nameservers.

WSL logs:

These are apparently uploaded separately.

Expected behavior

The nameserver gives the results it is asked for.

Actual behavior

The nameserver also lists completely unrelated results, such as the zone’s NS records’ addresses.

@mirabilos
Copy link
Author

I tried this step…

Get a link to your feedback item by clicking on 'Share my Feedback' and post that link to the Github thread so we can easily get to your feedback!

… from the documentation, but it just brought me back to the beginning to report another feedback. Sorry, no idea how to get the link.

@maketsi
Copy link

maketsi commented Oct 13, 2020

Duplicate of #5806 and probably few others.

I also have this problem, and on my case it's caused by VPN client being active on the host. Happens both with PaloAlto GlobalProtect and Pulse Secure clients. The issue is visible in all Hyper-V clients, including Windows Sandbox, so not limited to WSL2. Whenever VPN is active, Hyper-V DNS returns all NS records mixed with A records. The only workaround is to use external nameserver addresses directly, which obviously causes some headache both in WSL2 and windows sandbox.

@mirabilos
Copy link
Author

I don’t even have any VPN running… the physical box is just a laptop on a company LAN (which I access over RDP due to WFH).

@mirabilos
Copy link
Author

Oooooh, fucking autoclose bots… way NOT to deal with your users!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants
@mirabilos @maketsi @therealkenc and others