add protection against dns-redirection to is_resolvable

In an effort to make the EC2 Datasource's search under ec2.archive.ubuntu.com
resilient against dns redirection, we add some code to is_resolvable.

One future enhancement for this would be to protect against server side
round robin results.  Ie, if 'bogus-entry' returned 10.0.1.1 one time, and then
10.0.1.2 a second time.  We could check if results where within the same 3
octets, and assume invalid if they were.
This commit is contained in:
Scott Moser 2012-08-06 15:59:41 -04:00
parent 4edd171407
commit 84c7720af5
1 changed files with 37 additions and 2 deletions

View File

@ -55,6 +55,7 @@ from cloudinit import url_helper as uhelp
from cloudinit.settings import (CFG_BUILTIN)
_DNS_REDIRECT_IP = None
LOG = logging.getLogger(__name__)
# Helps cleanup filenames to ensure they aren't FS incompatible
@ -825,9 +826,43 @@ def get_cmdline_url(names=('cloud-config-url', 'url'),
def is_resolvable(name):
""" determine if a url is resolvable, return a boolean """
""" determine if a url is resolvable, return a boolean
This also attempts to be resilent against dns redirection.
Note, that normal nsswitch resolution is used here. So in order
to avoid any utilization of 'search' entries in /etc/resolv.conf
we have to append '.'.
The top level 'invalid' domain is invalid per RFC. And example.com
should also not exist. The random entry will be resolved inside
the search list.
"""
global _DNS_REDIRECT_IP # pylint: disable=W0603
if _DNS_REDIRECT_IP is None:
badips = set()
badnames = ("does-not-exist.example.com.", "example.invalid.",
rand_str())
badresults = {}
for iname in badnames:
try:
result = socket.getaddrinfo(iname, None, 0, 0,
socket.SOCK_STREAM, socket.AI_CANONNAME)
badresults[iname] = []
for (_fam, _stype, _proto, cname, sockaddr) in result:
badresults[iname].append("%s: %s" % (cname, sockaddr[0]))
badips.add(sockaddr[0])
except socket.gaierror:
pass
_DNS_REDIRECT_IP = badips
if badresults:
LOG.debug("detected dns redirection: %s" % badresults)
try:
socket.getaddrinfo(name, None)
result = socket.getaddrinfo(name, None)
# check first result's sockaddr field
addr = result[0][4][0]
if addr in _DNS_REDIRECT_IP:
return False
return True
except socket.gaierror:
return False