LyleLee / jail

Put a program into networking jail. see what it is doing over the network
MIT License
0 stars 0 forks source link

Temporary failure in name resolution in network namespace and /etc/resolv.conf #1

Open LyleLee opened 4 years ago

LyleLee commented 4 years ago

Inside a network namespace we create, I see DNS resolve error:

user@intel:~/go/src/github.com/Lylelee/jail-program$ sudo ip netns exec jailns bash
root@intel:~/go/src/github.com/Lylelee/jail-program# ping www.baidu.com
ping: www.baidu.com: Temporary failure in name resolution

Because ping tries to talk to DNS server, which locate default at 127.0.0.53, for DNS resolving. Unfortunately, there is no one listen there, since the network namespace is isolate.

strace ping www.baidu.com

socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0

According to man ip-netns link, placing a independent file resolv.conf, at which explicit point to a nameserver, to /etc/netns/{nsName}/resolv.conf solve the problems

But, when I write my own code and execute a command inside the same network namespace seeing problems again. I can't tell the exact cause.

/bin/bash -c ping -c 3 www.baidu.com
exit status 2
ping: www.baidu.com: Temporary failure in name resolution

ip netns could have read /etc/netns/{nsName}/resolv.conf and bind mount it into namespace /etc/resolv.conf. but I can't find related code on ip route2 git repo

Finally, the compromise is replacing host /etc/resolv.conf default setting with my custom nameserver.

nameserver 114.114.114.114

OS&kernel:

VERSION="18.04.2 LTS (Bionic Beaver)"
Linux  4.15.0-106-generic #107-Ubuntu SMP Thu Jun 4 11:27:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Be careful:

/etc/resolv.conf is controlled by systemd-resolved.service. And could be overwritten anytime.

I can verified it by fire:

sudo systemctl restart systemd-resolved.service
LyleLee commented 4 years ago

Some awesome guys have talk about this topic: https://unix.stackexchange.com/questions/471122/namespace-management-with-ip-netns-iproute2/471214#471214

user1@intel:~/go/src/github.com/Lylelee/jail-program$ sudo strace -e open,unshare,setns,mount,umount2 ip netns exec jailns bash
setns(5, CLONE_NEWNET)                  = 0
unshare(CLONE_NEWNS)                    = 0
mount("", "/", 0x55ebdaa45725, MS_REC|MS_SLAVE, NULL) = 0
umount2("/sys", MNT_DETACH)             = 0
mount("jailns", "/sys", "sysfs", 0, NULL) = 0
mount("/etc/netns/jailns/resolv.conf", "/etc/resolv.conf", 0x55ebdaa45725, MS_BIND, NULL) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=66189, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=66194, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=66196, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=66240, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---

Confirm that

ip netns could have read /etc/netns/{nsName}/resolv.conf and bind mount it into namespace /etc/resolv.conf
LyleLee commented 4 years ago

So I add lines of code about bind mount

    if err := syscall.Mount("/etc/netns/jailns/resolv.conf", "/etc/resolv.conf", "", syscall.MS_BIND, ""); err != nil {
        log.Println(err.Error())
    }

It works, but /etc/netns/jailns/resolv.conf propagate to host /etc/resolv.conf even the program exits. we have to manually umount /etc/resolv.conf after that. I think chroot my help.