Opened 6 years ago

Closed 5 years ago

#523 closed Bug / Defect (fixed)

OpenVPN doesn't pickup changes to /etc/resolv.conf

Reported by: ngharo Owned by:
Priority: minor Milestone: release 2.3.7
Component: Generic / unclassified Version: OpenVPN git master branch (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: dns resolv res_init glibc
Cc: plaisthos

Description

OpenVPN appears to only call res_init() once per entry of function call openvpn_getaddrinfo().

When resolv-retry is infinite, it appears that the loop in openvpn_getaddrinfo() is never broken and thus any changes to /etc/resolv.conf to correct the problem is never picked up.

This is a well documented bug across other OSS projects:
https://sourceware.org/bugzilla/show_bug.cgi?id=3675
https://bugzilla.mozilla.org/show_bug.cgi?id=166479
https://code.google.com/p/chromium/issues/detail?id=12740

To reproduce:
Prereq: Make sure no glibc (nscd) or other DNS caching is enabled
1) Stop openvpn
2) Insert bogus nameservers into /etc/resolv.conf
3) Start openvpn with resolv-retry infinite
4) Observe repeating name resolution failures in openvpn logs
5) Insert legitimate nameservers into /etc/resolv.conf
6) Verify name resolution now works by pinging remote hostname
7) Observe how OpenVPN never recovers from name resolution failures

Attachments (1)

0001-Fix-autotools-check-for-res_init.patch (1.7 KB) - added by ngharo 6 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 Changed 6 years ago by ngharo

Upon further investigation, x64 ./configure against Debian 8 and LFS 7.4 fail to find support for res_init. I think the symbol is called __res_init and a macro defines res_init in libresolve... Possibly the autotools check for res_init is suspect.

Changed 6 years ago by ngharo

comment:2 in reply to:  1 Changed 6 years ago by ngharo

This patch fixes the autotools check for res_init support.

This fixes the original problem described. I think it looks good but I'm a novice at autotools so there's that :)

comment:3 Changed 5 years ago by Gert Döring

I'm truly not an autotools expert, but decided to google around and use something similar to what the cups people do - just find the different variants (_ _res_init, res_9_init, res_init) in the usual places (nothing, -lresolv, -lbind) and link that - and the code now assumes "it is always there!" so if configure fails to find it, we'll notice, instead of silently assuming "this platform doesn't have it".

Patch on http://article.gmane.org/gmane.network.openvpn.devel/9614

Last edited 5 years ago by Gert Döring (previous) (diff)

comment:4 Changed 5 years ago by Gert Döring

#303 is likely a duplicate of this one ("getaddrinfo() not picking up new resolvers after network change, on Linux"). Closing the other one, keeping this one until the patch is merged.

comment:5 Changed 5 years ago by Gert Döring

Milestone: release 2.3.7

Uh. If I read this right, it's actually two bugs - res_init() not being found by configure, and openvpn_getaddrinfo() looping forever without calling res_init(), even *if* it was found?

How annoying, and needs to be fixed for 2.3.7

comment:6 Changed 5 years ago by Gert Döring

Cc: plaisthos added

Arne, can you have a quick look at openvpn_getaddrinfo() in 2.3 and git master, and tell me whether "just move the res_init() right after the "while(true) {" bit would be the right fix?

comment:7 Changed 5 years ago by Gert Döring

So, the first bit (configure not finding res_init()) has been merged into git master and release/2.3, per

commit 0d4091298f3644ff4187aa1ec54d1c440a056875 (master)
commit b230eef98a2cc571d725fc19ff5f2d5093d643ca (release/2.3)

Author: Gert Doering
Date: Mon Apr 27 21:27:21 2015 +0200

assume res_init() is always there.

now we just need to move the res_init() to the right place. Arne?

comment:8 Changed 5 years ago by Gert Döring

OK, testing this was more complicated than expected, because master has changed the interpretation of --resolv-retry infinite (leading to "exactly one retry inside openvpn_getaddrinfo()") *and* Linux has changed glibc to always call stat("/etc/resolv.conf")...

So, tested on FreeBSD 9.1, and using "--resolv-retry 50" to give me 10 retries in the inner loop, and a resolver that really wants us to call res_init() to re-read stuff.

With that, the problem manifests (read: if I break resolv.conf, then call openvpn, and while running, fix resolv.conf, it will not pick up the changes) - and the assumed fix "move res_init() just inside the while(true) { ...} loop" also works.

Totally trivial patch sent to list: http://article.gmane.org/gmane.network.openvpn.devel/9763

comment:9 Changed 5 years ago by Gert Döring

Resolution: fixed
Status: newclosed

Patch has been applied to the master and release/2.3 branch.

commit 288a819af7d3a6fab9e0b69ae8dbaac74b36307b (master)
commit 4e7eb95e43f0daed79e25e0ad6a9a20705b57376 (release/2.3)

Author: Gert Doering
Date: Sun May 31 15:59:09 2015 +0200

Move res_init() call to inner openvpn_getaddrinfo() loop

Signed-off-by: Gert Doering <gert@…>
Acked-by: Arne Schwabe <arne@…>
Message-Id: <1433080749-6892-1-git-send-email-gert@…>
URL: http://article.gmane.org/gmane.network.openvpn.devel/9763

Note: See TracTickets for help on using tickets.