def configure_dns(self): """Generates BIND configuration files for DNS Can check configs eg: Forward:: bash-3.2$ named-checkzone -d AS3 ank_lab/netkit_lab/AS3_l3_3_dns_1/etc/bind/db.AS3 loading "AS3" from "ank_lab/netkit_lab/AS3_l3_3_dns_1/etc/bind/db.AS3" class "IN" zone AS3/IN: loaded serial 2008080101 OK Reverse:: bash-3.2$ named-checkzone -d 0.10.in-addr.arpa ank_lab/netkit_lab/AS3_l3_3_dns_1/etc/bind/db.0.10.in-addr.arpa. loading "0.10.in-addr.arpa" from "ank_lab/netkit_lab/AS3_l3_3_dns_1/etc/bind/db.0.10.in-addr.arpa." class "IN" zone 0.10.in-addr.arpa/IN: loaded serial 2008080101 OK named:: bash-3.2$ named-checkconf ank_lab/netkit_lab/AS3_l3_3_dns_1/etc/bind/named.conf """ import netaddr ip_localhost = netaddr.IPAddress("127.0.0.1") linux_bind_dir = "/etc/bind" resolve_template = lookup.get_template("linux/resolv.mako") forward_template = lookup.get_template("bind/forward.mako") named_template = lookup.get_template("bind/named.mako") reverse_template = lookup.get_template("bind/reverse.mako") root_template = lookup.get_template("bind/root.mako") root_dns_template = lookup.get_template("bind/root_dns.mako") root_dns_named_template = lookup.get_template("bind/root_dns_named.mako") ip_as_allocs = ank.get_ip_as_allocs(self.network) dns_servers = ank.dns_servers(self.network) root_servers = list(ank.root_dns_servers(self.network)) auth_servers = ank.dns.dns_auth_servers(self.network) caching_servers = ank.dns.dns_cache_servers(self.network) clients = ank.dns.dns_clients(self.network) routers = set(self.network.routers()) #TODO: use with for opening files for server in root_servers: children = ank.dns.dns_hiearchy_children(server) child_servers = [] for child in children: advertise_block = ip_as_allocs[child.asn] reverse_identifier = ank.rev_dns_identifier(advertise_block) child_servers.append( (child.domain, reverse_identifier, ank.server_ip(child))) f_root_db = open(os.path.join(bind_dir(self.network, server), "db.root"), 'wb') f_root_db.write( root_dns_template.render( dns_servers = child_servers, server = server, )) f_named = open( os.path.join(bind_dir(self.network, server), "named.conf"), 'wb') f_named.write(root_dns_named_template.render( logging = False, )) for server in caching_servers: #root_db_hint = ( ("ns.AS%s" % n.asn, ank.server_ip(n)) for n in ank.dns_hiearchy_parents(server)) root_db_hint = ( ("ROOT-SERVER", ank.server_ip(n)) for n in root_servers) root_db_hint = list(root_db_hint) #TODO: make caching use parent rather than global root f_root = open( os.path.join(bind_dir(self.network, server), "db.root"), 'wb') f_root.write( root_template.render( root_servers = root_db_hint)) f_named = open( os.path.join(bind_dir(self.network, server), "named.conf"), 'wb') f_named.write(named_template.render( entry_list = [], bind_dir = linux_bind_dir, logging = False, )) f_named.close() for server in auth_servers: named_list = [] advertise_links = list(ank.advertise_links(server)) advertise_hosts = list(ank.dns_auth_children(server)) LOG.debug("DNS server %s advertises %s" % (server, advertise_links)) #TODO: make reverse dns handle domains other than /8 /16 /24 advertise_block = ip_as_allocs[server.asn] # remove trailing fullstop reverse_identifier = ank.rev_dns_identifier(advertise_block).rstrip(".") #TODO: look at using advertise_block.network.reverse_dns - check what Bind needs named_list.append(reverse_identifier) f_named = open( os.path.join(bind_dir(self.network, server), "named.conf"), 'wb') f_named.write(named_template.render( domain = server.domain, entry_list = named_list, bind_dir = linux_bind_dir, logging = False, )) f_named.close() for_entry_list = list( (self.interface_id(link.id), link.local_host.dns_host_portion_only, link.ip) for link in advertise_links) # Add loopbacks for routers for_entry_list += ( (self.lo_interface(0), host.dns_host_portion_only, host.lo_ip.ip) #TODO: make thise check l3 group rather than asn (generalise) for host in advertise_hosts if host.is_router and host.asn == server.asn) rev_entry_list = list( (ank.reverse_subnet(link.ip, advertise_block.prefixlen), self.interface_id(link.id), link.local_host.dns_hostname) for link in advertise_links) # Add loopbacks for routers rev_entry_list += ( (ank.reverse_subnet(host.lo_ip.ip, advertise_block.prefixlen), self.lo_interface(0), host.dns_host_portion_only) #TODO: make thise check l3 group rather than asn (generalise) for host in advertise_hosts if host.is_router and host.asn == server.asn) #TODO: provide better way to get eg eth0.host than string concat inside the template host_cname_list = [] for host in advertise_hosts: if host.asn != server.asn: # host is from another asn, skip. #TODO: extend this to make sure matches same asn, l3group and l2group continue if host.is_router: # has lo_ip cname = "%s.%s" % (self.lo_interface(), host.dns_host_portion_only) else: # choose an interface - arbitrary choice, choose first host link interface = self.interface_id(ank.server_interface_id(host)) cname = "%s.%s" % (interface, host.dns_host_portion_only) host_cname_list.append( (host.dns_host_portion_only, cname)) #Sort to make format nicer host_cname_list = sorted(host_cname_list, key = lambda x: x[1]) for_entry_list = sorted(for_entry_list) for_entry_list = sorted(for_entry_list, key = lambda x: x[1]) f_forward = open ( os.path.join(bind_dir(self.network, server), "db.%s" % server.domain), 'wb') f_forward.write(forward_template.render( domain = server.domain, entry_list = for_entry_list, host_cname_list = host_cname_list, dns_server = server.dns_hostname, dns_server_ip = ank.server_ip(server), )) f_reverse = open(os.path.join(bind_dir(self.network, server), "db.%s" % reverse_identifier), 'wb') f_reverse.write(reverse_template.render( domain = server.domain, identifier = reverse_identifier, entry_list = rev_entry_list, dns_server= server.dns_hostname, )) #TODO: make l2 use l3 for caching #TODO: ROOT-SERVER can't be part of a domain... - need to correctly handle case of multiple root servers # and also need to handle this for case of single root server (ie no hiearchy) probably ok as /etc/resolv.conf points to server itself, not through dns hints root_db_hint = ( ("ROOT-SERVER", ank.server_ip(n)) for n in ank.dns_hiearchy_parents(server)) f_root = open( os.path.join(bind_dir(self.network, server), "db.root"), 'wb') f_root.write( root_template.render( root_servers = root_db_hint)) for server in dns_servers: f_resolv = open( os.path.join(etc_dir(self.network, server), "resolv.conf"), 'wb') f_resolv.write ( resolve_template.render( nameservers = [ank.server_ip(server)], domain = server.domain)) # Configure clients for client in clients: server_ips = (ank.server_ip(server) for server in ank.dns_hiearchy_parents(client)) server_ips = list(server_ips) f_resolv = open( os.path.join(etc_dir(self.network, client), "resolv.conf"), 'wb') f_resolv.write ( resolve_template.render( nameservers = server_ips, domain = client.domain)) return