def create_txt_record( domain_name, token, name_server_ip, keyring, keyalgorithm=dns.tsig.HMAC_MD5, ttl=300, sleep=5, timeout=10 ): logger.info(' + Creating TXT record "%s" for the domain _acme-challenge.%s' % (token, domain_name)) domain_list = ['_acme-challenge'] + domain_name.split('.') for i in range(1, len(domain_list)): update = dns.update.Update( '.'.join(domain_list[i:]), keyring=keyring, keyalgorithm=keyalgorithm) update.add('.'.join(domain_list[:i]), ttl, 'TXT', token) logger.debug(str(update)) try: response = dns.query.udp(update, name_server_ip, timeout=timeout) rcode = response.rcode() logger.debug(" + Adding TXT record %s -> %s returned %s" % ( '.'.join(domain_list[:i]), '.'.join(domain_list[i:]), dns.rcode.to_text(rcode))) if rcode is dns.rcode.NOERROR: break except DNSException as err: logger.debug("", exc_info=True) logger.error(err) # Wait for DNS record to propagate if (sleep < 0): return microsleep = min(1, sleep/3.) nameservers = query_NS_record('.'.join(domain_list)) if not nameservers: nameservers = [name_server_ip] now = time.time() while (time.time() - now < sleep): try: if verify_record('.'.join(domain_list), nameservers, rtype='TXT', rdata=token, timeout=sleep, invert=False): logger.info(" + TXT record successfully added!") return except Exception: logger.debug("", exc_info=True) logger.fatal( "Unable to check if TXT record was successfully inserted") sys.exit(1) time.sleep(microsleep) logger.fatal(" + TXT record not added.") sys.exit(1)
def _submitDNS(self, entries): keys = entries.keys() keys.sort() update = dns.update.Update( self.zone, keyring=dns.tsigkeyring.from_text(self.tsig_key)) update.delete(self.record, 'TXT') for k in keys: v = entries[k].replace(' ', '\ ') update.add(self.record, self.ttl, 'TXT', "%s=%s" % (k, v)) #print update response = dns.query.tcp(update, self.dns_ip) #print response if response.rcode() != 0: raise ValueError("Unexpected Response Code: %s" % response) return str(response)
def add_txt_record(self, record_name, record_content, record_ttl): """ Add a TXT record using the supplied information. :param str record_name: The record name (typically beginning with '_acme-challenge.'). :param str record_content: The record content (typically the challenge validation). :param int record_ttl: The record TTL (number of seconds that the record may be cached). :raises certbot.errors.PluginError: if an error occurs communicating with the DNS server """ domain = self._find_domain(record_name) n = dns.name.from_text(record_name) o = dns.name.from_text(domain) rel = n.relativize(o) update = dns.update.Update(domain, keyring=self.keyring, keyalgorithm=self.algorithm) update.add(rel, record_ttl, dns.rdatatype.TXT, record_content) try: response = dns.query.tcp(update, self.server, self._default_timeout, self.port) except Exception as e: raise errors.PluginError( 'Encountered error adding TXT record: {0}'.format(e)) rcode = response.rcode() if rcode == dns.rcode.NOERROR: logger.debug('Successfully added TXT record %s', record_name) else: raise errors.PluginError( 'Received response from server: {0}'.format( dns.rcode.to_text(rcode)))
def _manage_record(self, key=None, ttl=None, type=None, zone=None, content=None, action=None): """ add or delete a given record """ keyring = dns.tsigkeyring.from_text({ zone: self.zone_list[zone]['key'] }) update = dns.update.Update( zone + '.', keyring=keyring, keyalgorithm=self._select_algorithm( self.zone_list[zone]['algorithm'] ) ) if action == 'add': ttl = int(ttl) content = str(content) type = str(type) update.add(key, ttl, type, content) elif action == 'del': type = str(type) update.delete(key, type) else: raise WrongDnsUpdateMethod response = dns.query.tcp(update, self.zone_list[zone]['ip'])
def add_txt_record(self, domain_name, record_name, record_content, record_ttl): """ Add a TXT record using the supplied information. :param str domain: The domain to use to find the closest SOA. :param str record_name: The record name (typically beginning with '_acme-challenge.'). :param str record_content: The record content (typically the challenge validation). :param int record_ttl: The record TTL (number of seconds that the record may be cached). :raises certbot.errors.PluginError: if an error occurs communicating with the DNS server """ domain = self._find_domain(domain_name) n = dns.name.from_text(record_name) o = dns.name.from_text(domain) rel = n.relativize(o) update = dns.update.Update( domain, keyring=self.keyring, keyalgorithm=self.algorithm) update.add(rel, record_ttl, dns.rdatatype.TXT, record_content) try: response = dns.query.tcp(update, self.server) except Exception as e: raise errors.PluginError('Encountered error adding TXT record: {0}' .format(e)) rcode = response.rcode() if rcode == dns.rcode.NOERROR: logger.debug('Successfully added TXT record') else: raise errors.PluginError('Received response from server: {0}' .format(dns.rcode.to_text(rcode)))
def is_dynupdate_enabled(domain: str, nameserver: str) -> bool: """ Check if zone updating is enabled. :param domain: Name of the zone to transfer. :param nameserver: IPv4 or 6 to test. """ newrecord = 'newrecord' try: update = dns.update.Update(domain) update.add(newrecord, 3600, dns.rdatatype.A, '10.10.10.10') response = dns.query.tcp(update, nameserver, timeout=5) result = True if response.rcode() > 0: show_close('Zone update not enabled on server', details=dict(domain=domain, nameserver=nameserver)) result = False else: show_open('Zone update enabled on server', details=dict(domain=domain, nameserver=nameserver)) result = True except dns.query.BadResponse: show_close('Zone update not enabled on server', details=dict(domain=domain, nameserver=nameserver)) result = False except (socket.error, dns.exception.Timeout) as exc: show_unknown('Could not connect', details=dict(domain=domain, nameserver=nameserver, error=str(exc).replace(':', ','))) result = False return result
def add_dns_record(new_hostname, domain, new_ipaddress): PRIMARY_DNS_SERVER_IP = '192.168.8.200' TTL = 300 keyring = dns.tsigkeyring.from_text({ "dynamic.vmware.haf.": "jn694IwJ9IP4i5yGtSdIZJTFeFpVEvK2wa78gHVX8PohLNBQVYQd+JyGNX8A3hju8WmsNVo1Oq58YS93HR4HIQ==" }) logging.debug("DNS record A") ### Create A Record # Set the domain name with a trailing dot (to stop auto substitution of zone) dns_domain = '%s.' % (domain) # Prepare the payload for DNS record update in the given zone/domain (dns_domain) logging.debug(" {} ({})".format(new_hostname, new_ipaddress)) update = dns.update.Update(zone=dns_domain, keyname='dynamic.vmware.haf.', keyring=keyring, keyalgorithm=dns.tsig.HMAC_SHA512) # Inject the record details into the dns.update.Update class update.add(new_hostname, TTL, 'A', new_ipaddress) # Submit the new record to the DNS server to apply the update response = dns.query.tcp(update, PRIMARY_DNS_SERVER_IP, timeout=5) flags = dns.flags.to_text(response.flags) logging.debug(" A DNS update response: {} {}".format( dns.rcode.to_text(response.rcode()), flags))
def add_txt(self): try: update = dns.update.Update(self.get_domain_fqdn(), keyring=self.__keyring) update.add(self.__hostname, self.__ttl, 'TXT', self.__txt_value) return dns.query.tcp(update, self.__server_ip).rcode() except Exception, error: raise Exception("Error inserting DNS TXT Entry: %s" % (error))
def _manage_record(self, key=None, ttl=None, type=None, zone=None, content=None, action=None): """ add or delete a given record """ keyring = dns.tsigkeyring.from_text( {zone: self.zone_list[zone]['key']}) update = dns.update.Update(zone + '.', keyring=keyring, keyalgorithm=self._select_algorithm( self.zone_list[zone]['algorithm'])) if action == 'add': ttl = int(ttl) content = str(content) type = str(type) update.add(key, ttl, type, content) elif action == 'del': type = str(type) update.delete(key, type) else: raise WrongDnsUpdateMethod response = dns.query.tcp(update, self.zone_list[zone]['ip'])
def dns_do_command(zone, record_name, record_type, command, ttl=0, rdata=""): """ Helper for dns add, update, delete """ keyring = dns.tsigkeyring.from_text( {zone['connection']['keyName']: VinylDNSTestContext.dns_key}) name_server, name_server_port = dns_server_port(zone) fqdn = record_name + "." + zone['name'] print "updating " + fqdn + " to have data " + rdata update = dns.update.Update(zone['name'], keyring=keyring) if (command == 'add'): update.add(fqdn, ttl, record_type, rdata) elif (command == 'update'): update.replace(fqdn, ttl, record_type, rdata) elif (command == 'delete'): update.delete(fqdn, record_type) response = dns.query.udp(update, name_server, port=name_server_port, ignore_unexpected=True) return response
def _do_create_txt(dn): domain_list = dn.split('.') logger.info(' + Creating TXT record "%s" for the domain %s' % (token, dn)) for i in range(0, len(domain_list)): head = '.'.join(domain_list[:i]) tail = '.'.join(domain_list[i:]) update = dns.update.Update(tail, keyring=keyring, keyalgorithm=keyalgorithm) update.add(head, ttl, 'TXT', token) logger.debug(str(update)) try: response = dns.query.udp(update, name_server_ip, timeout=timeout) rcode = response.rcode() logger.debug(" + Creating TXT record %s -> %s returned %s" % (head, tail, dns.rcode.to_text(rcode))) if rcode is dns.rcode.NOERROR: return dn except DNSException as err: logger.debug("", exc_info=True) logger.error("Error creating TXT record %s %s: %s" % (head, tail, err))
def make_update(action, query): hostname = query.hostname.encode('ascii') D = dns.name.from_text(domain) H = dns.name.from_text(query.hostname) if H.is_subdomain(D): R = H.relativize(D) else: return "400 NOTAUTH %s\n" % H.to_text() keyring, algo = read_session_key("/etc/bind/keys/webapp.key") update = dns.update.Update(D, keyring=keyring, keyalgorithm=algo) if action == 'update': update.present(R, 'a') update.replace(R, 300, 'a', query.ip.encode('ascii')) elif action == 'delete': update.present(R, 'a') update.delete(R, 'a') elif action == 'add': update.absent(R, 'a') update.add(R, 300, 'a', query.ip.encode('ascii')) response = dns.query.tcp(update, '127.0.0.1') if response.rcode() == 0: return "NOERROR %s\n" % H.to_text() else: return "%s %s\n" % (dns.rcode.to_text(response.rcode()), H.to_text())
def _update_record(self, identifier, rtype=None, name=None, content=None): if self._get_lexicon_option("ttl"): ttl = self._get_lexicon_option("ttl") else: ttl = 300 if not identifier: rrset = self._list_records(rtype, name) if len(rrset) == 1: identifier = rrset[0]["id"] elif len(rrset) < 1: raise Exception( "No records found matching type and name - won't update") else: raise Exception( "Multiple records found matching type and name - won't update" ) d_rtype, d_name, d_content = self._resolve_identifier(identifier) if not rtype: rtype = d_rtype if not name: name = d_name d_name = dns.name.from_text(d_name).relativize( dns.name.from_text(self.zone)) name = dns.name.from_text(name).relativize( dns.name.from_text(self.zone)) update = dns.update.Update(self.zone, keyring=self.keyring) update.delete(d_name, d_rtype, d_content) update.add(name, ttl, rtype, content) self._run_query(update) return True
def post(self, request): """ generate an update message for adding record. """ if isinstance(request.DATA, list): for record in request.DATA: #RecordList.post(self, record) update = dns.update.Update(DOMAIN) rdname = str(record['name']) rdttl = int(record['ttl']) rdtype = str(record['type']) rdvalue = str(record['value']) update.add(rdname, rdttl, rdtype, rdvalue) try: response = dns.query.tcp(update, DNS_SERVER) log.info("ADD RDATA %s %d IN %s %s" % (rdname, rdttl, rdtype, rdvalue)) except: log.error("ADD RDATA FAIL.") else: update = dns.update.Update(DOMAIN) rdname = str(request.DATA['name']) rdttl = int(request.DATA['ttl']) rdtype = str(request.DATA['type']) rdvalue = str(request.DATA['value']) update.add(rdname, rdttl, rdtype, rdvalue) try: dns.query.tcp(update, DNS_SERVER) log.info("ADD RDATA %s %d IN %s %s" % (rdname, rdttl, rdtype, rdvalue)) except: log.error("ADD RDATA FAIL.") return Response() #RecordDetail.get()
def dns_do_command(zone, record_name, record_type, command, ttl=0, rdata=""): """ Helper for dns add, update, delete """ # Get the algorithm name from the DNS library (vinylDNS uses "-" in the name and dnspython uses "_") algo_name = getattr(dns.tsig, VinylDNSTestContext.dns_key_algo.replace("-", "_")) keyring = dns.tsigkeyring.from_text({ zone["connection"]["keyName"]: (algo_name, VinylDNSTestContext.dns_key) }) (name_server, name_server_port) = dns_server_port(zone) fqdn = record_name + "." + zone["name"] update = dns.update.Update(zone["name"], keyring=keyring) if command == "add": update.add(fqdn, ttl, record_type, rdata) elif command == "update": update.replace(fqdn, ttl, record_type, rdata) elif command == "delete": update.delete(fqdn, record_type) response = dns.query.udp(update, name_server, port=name_server_port, ignore_unexpected=True) return response
def _update_ns(name, addr): # name = name.replace('-', '') logger.info(f"updating forward zone {name}:{addr} ...") update = dns.update.Update("docker", keyring=KEYRING, keyalgorithm=ALGORITHM) update.delete(name, "A") update.add(name, 60, dns.rdatatype.A, str(addr)) response = dns.query.tcp(update, DDNS_SERVER) if response.rcode() != 0: logger.error(f"Failed: {response}") rv = str(addr).split(".") rv.reverse() parts = ".".join(rv[:2]) zone_name = ".".join(rv[2:]) + ".in-addr.arpa" logger.info(f"updating rev zone {zone_name} for {name}...") update = dns.update.Update(zone_name, keyring=KEYRING, keyalgorithm=ALGORITHM) update.delete(parts, "PTR") update.add(parts, 60, dns.rdatatype.PTR, str(name) + ".docker.") response = dns.query.tcp(update, DDNS_SERVER) if response.rcode() != 0: logger.error(f"Failed: {response}")
def addFWD(name,ttl,ipaddress): ipaddress = str(ipaddress) hostname = splitFQDN(name)[0] log.debug ('[addFWD] - hostname %s' % hostname) log.debug ('[addFWD] - domain %s' % splitFQDN(name)[1]) domain = splitFQDN(name)[1] if domain.endswith("."): domain = domain.rstrip('.') check4TSIG = TSIGSecured(domain) if check4TSIG.isSecure(domain): key = str(check4TSIG.TSIG(domain)) keyname = domain.replace(".","_") keyring = dns.tsigkeyring.from_text({keyname:key}) update = dns.update.Update(splitFQDN(name)[1], keyring=keyring) else: update = dns.update.Update(splitFQDN(name)[1]) address_type = enumIPtype(ipaddress) if address_type == 4: log.debug ('[addFWD] - IPv4') if monitor_replace == "False": update.add(hostname,monitor_ttl,dns.rdatatype.A, ipaddress) else: update.replace(hostname,monitor_ttl,dns.rdatatype.A, ipaddress) elif address_type == 6: log.debug ('[addFWD] - IPv6') if monitor_replace == "False": update.add(hostname,monitor_ttl,dns.rdatatype.AAAA, ipaddress) else: update.replace(hostname,monitor_ttl,dns.rdatatype.AAAA, ipaddress) response = dns.query.udp(update, monitor_nameserver) return response
def add_dns_record(self, domain, txtvalue): zone, nameserverip = self._determine_zone_and_nameserverip(domain) update = dns.update.Update(zone, keyring=self.keyring, keyalgorithm=self.keyalgorithm) update.add(domain, self.dns_ttl, dns.rdatatype.TXT, txtvalue) print('Adding \'{} 60 IN TXT "{}"\' to {}'.format( domain, txtvalue, nameserverip)) dns.query.tcp(update, nameserverip) verified = False retry = 0 while self.dns_verify and not verified and retry < 5: request = dns.message.make_query(domain, dns.rdatatype.TXT) response = dns.query.tcp(request, nameserverip) for rrset in response.answer: for answer in rrset: if answer.to_text().strip('"') == txtvalue: verified = True print('Verified \'{} 60 IN TXT "{}"\' on {}'.format( domain, txtvalue, nameserverip)) break if not verified: time.sleep(1) retry += 1 if not self.dns_verify or verified: return datetime.datetime.now() + datetime.timedelta(seconds=2 * self.dns_ttl) else: raise ValueError( 'Failed to verify \'{} 60 IN TXT "{}"\' on {}'.format( domain, txtvalue, nameserverip))
def delete(self, container_id): LOG.info("Deleting records for container: %s" % container_id) uuid_qname = dns.name.from_text(container_id, self._identity) identity_rrset = self._query(self._identity, dns.rdatatype.SRV) update = dns.update.Update(self._origin, keyring=self._keyring) for srv in identity_rrset.get(dns.rdatatype.SRV, []): if srv.target == uuid_qname: update.delete(self._identity, srv) uuid_rdata = self._query(uuid_qname, dns.rdatatype.CNAME, one_record=True) if not uuid_rdata: LOG.warn("No records found for container: %s" % container_id) return name_qname = uuid_rdata.target name_rrsets = self._query(name_qname, dns.rdatatype.ANY) name_rdata = name_rrsets[dns.rdatatype.A].items[0] service_name_rdata = name_rrsets[dns.rdatatype.SRV].items[0] service_rrsets = self._query(service_name_rdata.target, dns.rdatatype.A) service_rdata = service_rrsets.get(dns.rdatatype.A, []) update.delete(service_name_rdata.target, dns.rdatatype.A) update.delete(uuid_qname, dns.rdatatype.CNAME) update.delete(name_qname, dns.rdatatype.A) update.delete(name_qname, dns.rdatatype.SRV) for rdata in service_rdata: if rdata.address != name_rdata.address: update.add(service_name_rdata.target, self._ttl, rdata) self._update(update)
def _submitDNS(self, entries): keys = entries.keys() keys.sort() update = dns.update.Update(self.zone, keyring=dns.tsigkeyring.from_text( self.tsig_key)) update.delete(self.record, 'TXT') for k in keys: v = entries[k].replace(' ', '\ ') update.add(self.record, self.ttl, 'TXT', "%s=%s" % (k, v)) #print update response = dns.query.tcp(update, self.dns_ip) #print response if response.rcode() != 0: raise ValueError("Unexpected Response Code: %s" % response) return str(response)
def dnsupdates(self, host, mac, addr): """ determine and run needed DNS updates. """ host_s = "%s-%s" % (host, self.suffix) fqdn = "%s.%s" % (host_s, self.domain) msgd("DNS check mac: %s asking for: %s" % (mac, addr)) addr_si = dns_rev_host(addr) if (addr_si != 'AddrNotFound'): # address already known. msgd("mac: %s asking for %s, rev is already %s" % (mac, addr, addr_si)) return if (addr in dns_fwd_addr("%s.%s" % (host, self.domain), self.dnsmaster)): msgd("mac: %s asking for %s, which it already has." % (mac, host, addr)) return if not (addr in dns_fwd_addr(fqdn, self.dnsmaster)): if (addr[0] == 'f') and (addr[1] in ['d', 'e', 'f']): msgd("ignoring link level address %s" % addr) return update = dns.update.Update(self.domain, keyring=self.dnskeyring) update.add(host_s, 300, 'aaaa', addr) response = dns.query.tcp(update, self.dnsmaster) if response.rcode() != 0: msge("forward registration of %s failed" % host) msge(response) else: msgi("fwd of %s for mac: %s as %s succeeded" % (host_s, mac, addr)) else: msgd("skipped fwd of %s for %s, already in DNS OK" % (host_s, mac)) # fwd done, now check reverse... # FIXME: only works for 2 digit netmask /48, /64, etc... zone = str(dns.reversename.from_address(self.prefix[0:-4]))[0:63] pfx = int(self.prefix[-2:]) rzone = "%s.ip6.arpa." % zone[-(pfx / 2) + 1:] msgd("mac: %s DNS Add rev %s -> %s" % (mac, addr, fqdn)) update = dns.update.Update(rzone, keyring=self.dnskeyring) update.add(dns.reversename.from_address(addr), 300, 'ptr', fqdn) response = dns.query.tcp(update, self.dnsmaster) if response.rcode() != 0: msge("reverse registration of %s failed" % host) #msge( response ) else: msgi("rev registration of %s-%s succeeded" % (host, self.suffix)) return
def update_ds(self, name, ds_set): update = self._init_update() name = dns.name.from_text(name) update.delete(name, dns.rdatatype.DS) for ds in ds_set: update.add(name, self._ttl, dns.rdatatype.DS, ds) response = dns.query.tcp(update, self._server, port=self._port) return response.rcode() == 0
def add_address_to_update(self, update: dns.update.Update, hostPart: dns.name.Name, ttl: int, address: IPAddressUnion) -> None: assert isinstance(address, ipaddress.IPv6Address) update.add( hostPart, ttl, dns.rdtypes.IN.AAAA.AAAA(dns.rdataclass.IN, dns.rdatatype.AAAA, str(address)))
def _add_record(self, qtype, fqdn, ip, do_ptr): log.debug('DDNS add for record {}, fqdn: {}'.format(qtype, fqdn)) origin, name = self._parse_name(fqdn) update = dns.update.Update(origin, keyring=self.keyring) update.add(name, self.ttl, qtype, ip) self._do_update(update) if do_ptr: self._add_ptr(fqdn, ip)
def UpdateDnsSrv(self, port, host, domain, dnsip): update = dns.update.Update(domain) update.add('_xmpp-server._tcp', 3600, 'SRV', '0 0 5269 ' + host) try: logging.debug('UpdateDnsSrv: writing to dns server') response = dns.query.tcp(update, dnsip) except: logging.info('Writing SRV failed') logging.exception('')
def _perform_single(self, achall): response, validation = achall.response_and_validation() zone, record = self.zone_and_record(achall.domain, achall.validation_domain_name(achall.domain)) update = dns.update.Update(zone, keyring=self.keyring, keyalgorithm=self.keyalgorithm) update.add(record, 300, 'TXT', validation.encode('ascii')) dns.query.tcp(update, self.conf('nameserver')) return response
def test_dns_unauth_update(Docker, resolver, zone): update = dns.update.Update(zone) update.add('test', 0, 'A', '10.0.0.1') response = dns.query.tcp(update, Docker.get_ip(), timeout=10) try: answers = resolver.query('test.%s' % zone, 'A') except dns.resolver.NXDOMAIN as err: assert err.message == "None of DNS query names exist: test.%s., test.%s." % (zone, zone)
def UpdateDnsSrv(self,port,host,domain,dnsip): update=dns.update.Update(domain) update.add('_xmpp-server._tcp',3600,'SRV','0 0 5269 '+host) try: logging.debug('UpdateDnsSrv: writing to dns server') response = dns.query.tcp(update, dnsip) except: logging.info('Writing SRV failed') logging.exception('')
def add_dns(host, ip): if not ip or not DNS_KEY: return update = dns.update.Update(DNS_DOMAIN, keyring=keyring) if ip_address(ip).version == 6: update.add(host, 86400, 'AAAA', ip) else: update.add(host, 86400, 'A', ip) dns.query.tcp(update, DNS_SERVER)
def add_to_dns(fqdn, ipadd): update = dns.update.Update(domain) update.add(fqdn, 300, 'A', ipadd) response = dns.query.tcp(update, dnsserver) response = str(response) if 'noerror' in response.lower(): return ("Successful") else: return ("Unsuccessful")
def add_ns_record(server, zone, key, nameserver, ttl=300): # make input zones absolute #zone = zone + '.' if not zone.endswith('.') keyring = dns.tsigkeyring.from_text({'update-key': key}) update = dns.update.Update(zone, keyring=keyring) update.add(zone, ttl, 'ns', nameserver) response = dns.query.tcp(update, server) return response
def dnsupdates( self, host, mac, addr ): """ determine and run needed DNS updates. """ host_s= "%s-%s" % ( host, self.suffix ) fqdn= "%s.%s" % ( host_s, self.domain) msgd( "DNS check mac: %s asking for: %s" % ( mac, addr ) ) addr_si = dns_rev_host(addr) if ( addr_si != 'AddrNotFound' ) : # address already known. msgd( "mac: %s asking for %s, rev is already %s" % ( mac, addr, addr_si ) ) return if ( addr in dns_fwd_addr( "%s.%s" % (host, self.domain) , self.dnsmaster)) : msgd( "mac: %s asking for %s, which it already has." % ( mac, host, addr ) ) return if not ( addr in dns_fwd_addr(fqdn,self.dnsmaster) ) : if ( addr[0] == 'f' ) and ( addr[1] in [ 'd', 'e', 'f' ] ): msgd( "ignoring link level address %s" % addr ) return update = dns.update.Update( self.domain, keyring=self.dnskeyring ) update.add( host_s, 300, 'aaaa', addr ) response = dns.query.tcp(update,self.dnsmaster) if response.rcode() != 0: msge( "forward registration of %s failed" % host ) msge( response ) else: msgi( "fwd of %s for mac: %s as %s succeeded" % ( host_s, mac, addr ) ) else: msgd( "skipped fwd of %s for %s, already in DNS OK" % ( host_s, mac ) ) # fwd done, now check reverse... # FIXME: only works for 2 digit netmask /48, /64, etc... zone = str(dns.reversename.from_address( self.prefix[0:-4] ))[0:63] pfx= int(self.prefix[-2:]) rzone="%s.ip6.arpa." % zone[-(pfx/2)+1:] msgd( "mac: %s DNS Add rev %s -> %s" % ( mac, addr, fqdn ) ) update = dns.update.Update( rzone, keyring=self.dnskeyring ) update.add( dns.reversename.from_address(addr), 300, 'ptr', fqdn ) response = dns.query.tcp(update,self.dnsmaster) if response.rcode() != 0: msge( "reverse registration of %s failed" % host ) #msge( response ) else: msgi( "rev registration of %s-%s succeeded" % ( host, self.suffix )) return
def add_record(self, domain_zone, domain_name, ttl, record_type, record_value): if self.search_record(domain_name + '.' + domain_zone, record_type): return {'code': '1', 'message': 'record aleady exit'} else: update = dns.update.Update(domain_zone, keyring=self.keyring, keyalgorithm=self.sha_type) update.add(domain_name, ttl, record_type, record_value) dns.query.tcp(update, self.name_server_addr) return {'code': 0, 'message': 'ok'}
def fx_agent_dynrec(self, operation, domain, nssrv, selector, ttl, payload_b64, **tsig): """ Manage Agent Dynamic DNS Record: CRUD""" self.flogger.debug( "Accepted for record: {0}, {1}, {2}, {3}, {4}, {5}, {6}".format( operation, domain, nssrv, selector, ttl, payload_b64, tsig)) keyring = dns.tsigkeyring.from_text(tsig) self.flogger.debug("DNS TSIG Keyring: " + str(keyring)) update = dns.update.Update(domain, keyring=keyring, keyalgorithm=HMAC_SHA256) self.flogger.debug("DNS TXT Update: " + str(update)) # Make DKIM record look normal dkim_record = '"v=DKIM1; h=sha256; k=rsa; t=y; s=email; p={0}"'.format( payload_b64) # From http://www.dnspython.org/docs/1.14.0/dns.update.Update-class.html#add if operation == 'add': self.flogger.debug("DNS: Adding TXT record") update.add(selector, ttl, dns.rdatatype.TXT, dkim_record) else: if operation == 'update': self.flogger.debug("DNS: Updating TXT record") update.replace(selector, ttl, dns.rdatatype.TXT, dkim_record) else: if operation == 'delete': self.flogger.debug("DNS: Deleting TXT record") update.delete(selector) else: self.flogger.error("DNS: Invalid record action: " + operation) raise ValueError( "Operation must be one of <add|update|delete>") try: response = dns.query.tcp(update, nssrv, timeout=10) if response.rcode() == 0: self.flogger.debug("DynDNS: Update Successful") return True else: self.flogger.error("DynDNS: Update failed: code: {0}".format( response.rcode())) self.flogger.error("Response: {0}".format(response)) return False except dns.tsig.PeerBadKey as peerkey: self.flogger.error("DNS TSIG: Bad Peer key {0}".format(peerkey)) return False except Exception as e: self.flogger.error("DNS: General Exception {0}".format(e)) return False
def _create_record(self, rtype, name, content): if self._get_lexicon_option("ttl"): ttl = self._get_lexicon_option("ttl") else: ttl = 300 name = dns.name.from_text(name).relativize( dns.name.from_text(self.zone)) update = dns.update.Update(self.zone, keyring=self.keyring) update.add(name, ttl, rtype, content) self._run_query(update) return True
def create_record(self): update = dns.update.Update(self.zone, keyring=self.keyring) update.add(self.record, self.ttl, self.type, self.value) try: response = dns.query.tcp(update, self.server, timeout=10) if dns.message.Message.rcode(response) == 0: return True else: return False except: self.module.fail_json(msg="Connection to DNS server failed")
def create_record(self): update = dns.update.Update(self.zone, keyring=self.keyring) update.add(self.record, self.ttl, self.type, self.value) try: response = dns.query.tcp(update, self.server, timeout=10) if dns.message.Message.rcode(response) == 0: return True else: return False except: self.module.fail_json(msg='Connection to DNS server failed')
def doUpdate(args): # Sanity check the data and get the action and record type action, _type = verify_input(my_input) ttl = is_valid_TTL(TimeToLive) # Get the hostname and the origin Origin, name = parse_name(Origin, my_input[1]) # Validate and setup the Key keyring, keyalgo = get_key(KeyFile) # Start constructing the DDNS Query update = dns.update.Update(Origin, keyring=keyring, keyalgorithm=getattr(dns.tsig, keyalgo)) # Put the payload together. my_payload = '' # Start with an empty payload. do_ptr = doPTR if _type == 'A' or _type == 'AAAA': my_payload = my_input[3] if doPTR == True: ptr_target = name.to_text() + '.' + Origin.to_text() ptr_origin, ptr_name = parse_name(None, genPTR(my_payload).to_text()) ptr_update = dns.update.Update(ptr_origin, keyring=keyring) if action != 'del' and _type == 'CNAME' or _type == 'NS' or _type == 'TXT' or _type == 'PTR': my_payload = my_input[3] do_ptr = False elif type == 'SRV': my_payload = my_input[3] + ' ' + my_input[4] + ' ' + my_input[5] + ' ' + my_input[6] do_ptr = False elif type == 'MX': my_payload = my_input[3]+' '+my_input[4] do_ptr = False elif type == 'CNAME': do_ptr = False # Build the update if action == 'add': update.add(name, ttl, _type, my_payload) if do_ptr is True and _type: ptr_update.add(ptr_name, ttl, 'PTR', ptr_target) elif action == 'delete' or action == 'del': if my_payload != '': update.delete(name, _type, my_payload) else: update.delete(name) if do_ptr is True and (_type == 'A' or _type == 'AAAA'): ptr_update.delete(ptr_name, 'PTR', ptr_target) else: do_ptr = False elif action == 'update': update.replace(name, ttl, _type, my_payload) if doPTR is True: ptr_update.replace(ptr_name, ttl, 'PTR', ptr_target)
def test_to_wire1(self): # type: () -> None update = dns.update.Update('example') update.id = 1 update.present('foo') update.present('foo', 'a') update.present('bar', 'a', '10.0.0.5') update.absent('blaz2') update.absent('blaz2', 'a') update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') update.add('bar', 300, 'a', '10.0.0.3') update.delete('bar', 'a', '10.0.0.4') update.delete('blaz', 'a') update.delete('blaz2') self.failUnless(update.to_wire() == goodwire)
def test_to_wire2(self): # type: () -> None update = dns.update.Update('example') update.id = 1 update.present('foo') update.present('foo', 'a') update.present('bar', 'a', '10.0.0.5') update.absent('blaz2') update.absent('blaz2', 'a') update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') update.add('bar', 300, dns.rdata.from_text(1, 1, '10.0.0.3')) update.delete('bar', 'a', '10.0.0.4') update.delete('blaz', 'a') update.delete('blaz2') self.failUnless(update.to_wire() == goodwire)
def test_to_wire3(self): # type: () -> None update = dns.update.Update("example") update.id = 1 update.present("foo") update.present("foo", "a") update.present("bar", "a", "10.0.0.5") update.absent("blaz2") update.absent("blaz2", "a") update.replace("foo", 300, "a", "10.0.0.1", "10.0.0.2") update.add("bar", dns.rdataset.from_text(1, 1, 300, "10.0.0.3")) update.delete("bar", "a", "10.0.0.4") update.delete("blaz", "a") update.delete("blaz2") self.assertEqual(update.to_wire(), goodwire)
def main(): nameserver = sys.argv[1] zone = sys.argv[2] name = sys.argv[3] interface = sys.argv[4] keyfn = sys.argv[5] actual = [] for d in ifaddresses(interface).setdefault(AF_INET, []): addr = d['addr'] actual.append(addr) actual.sort() if not actual: print("no known addresses, giving up") return indns = [] host = dns.name.from_text('%s.%s' % (name, zone)) request = dns.message.make_query(host, dns.rdatatype.A) response = dns.query.tcp(request, nameserver) for entry in response.answer: for item in entry.items: indns.append(str(item)) indns.sort() if actual == indns: if not force: return print("address not changed, updating anyway") else: print("IP address address for %s on %s.%s changed" % ( interface, name, zone)) print("actual: %s" % actual) print("in dns: %s" % indns) with open(keyfn) as f: key = f.readline().strip() keyring = dns.tsigkeyring.from_text({ zone + '.' : key }) update = dns.update.Update(zone, keyring = keyring) update.replace(name, 300, 'A', actual[0]) for a in actual[1:]: update.add(name, 300, 'A', a) response = dns.query.tcp(update, nameserver)
def test_to_wire3(self): # type: () -> None update = dns.update.Update('example') update.id = 1 update.present('foo') update.present('foo', 'a') update.present('bar', 'a', '10.0.0.5') update.absent('blaz2') update.absent('blaz2', 'a') update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3')) update.delete('bar', 'a', '10.0.0.4') update.delete('blaz', 'a') update.delete('blaz2') self.assertEqual(update.to_wire(), goodwire)
def test_to_wire3(self): update = dns.update.Update('example') update.id = 1 update.present('foo') update.present('foo', 'a') update.present('bar', 'a', '10.0.0.5') update.absent('blaz2') update.absent('blaz2', 'a') update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3')) update.delete('bar', 'a', '10.0.0.4') update.delete('blaz', 'a') update.delete('blaz2') self.failUnless(update.to_wire() == goodwire)
def create_record(self): update = dns.update.Update(self.zone, keyring=self.keyring, keyalgorithm=self.algorithm) try: update.add(self.module.params['record'], self.module.params['ttl'], self.module.params['type'], self.module.params['value']) except AttributeError: self.module.fail_json(msg='value needed when state=present') except dns.exception.SyntaxError: self.module.fail_json(msg='Invalid/malformed value') response = self.__do_update(update) return dns.message.Message.rcode(response)
def test_dns_auth_update(Docker, resolver, zone): update_keys = Docker.args['tsig_update'] i = len(Docker.args.get('tsig_slave', [])) + 1 for update_key in update_keys: keyring = dns.tsigkeyring.from_text({ "key_%s" % i : update_key.split(':')[1] }) update = dns.update.Update(zone, keyring=keyring, keyalgorithm=update_key.split(':')[0], keyname='key_%s' % i) update.add('test', 0, 'A', '10.0.0.1') response = dns.query.tcp(update, Docker.get_ip(), timeout=10) answers = resolver.query('test.%s' % zone, 'A') assert (answers[0].address == '10.0.0.1') i += 1
def add(self, container_id, service, name, ip): LOG.info("Adding records for container: %s name: %s, ip: %s" % (container_id, name, ip)) uuid_qname = dns.name.from_text(container_id, self._identity) service_qname = dns.name.from_text(service, self._origin) name_qname = dns.name.from_text(name, self._identity) update = dns.update.Update(self._origin, keyring=self._keyring) update.add(self._identity, self._ttl, dns.rdatatype.SRV, "10 10 0 %s" % uuid_qname) update.add(name_qname, self._ttl, dns.rdatatype.SRV, "10 10 0 %s" % service_qname) update.add(uuid_qname, self._ttl, dns.rdatatype.CNAME, str(name_qname)) update.add(service_qname, self._ttl, dns.rdatatype.A, ip) update.add(name_qname, self._ttl, dns.rdatatype.A, ip) self._update(update)
def update_dns_value(self, sqlobject, delete=False): """Update dns value if delete is true, delete value instead of adding""" self.create_keyring() domain = self.get_domain(sqlobject.t_domains_id) if not domain: if delete: # domain already deleted return True self.log.error('Cannot get domain for t_domains_id %s' % sqlobject.t_domains_id) return False if self.parse_inetlist(domain.masters): # this server is not master return True if not self.conf.bind_master: # this server is not master return True value = str(sqlobject.value).split('/')[0] update = dns.update.Update(str(domain.name), keyring=self.keyring, keyalgorithm=str(self.conf.bind_secret_algorithm).lower()) if delete: update.delete(str(sqlobject.key), str(sqlobject.type), value) else: if not self.check_record(sqlobject.key, sqlobject.type, sqlobject.value, domain.name): update.add(str(sqlobject.key), int(sqlobject.ttl), str(sqlobject.type), value) else: self.log.debug('Record %s %d IN %s %s already exists' % ( str(sqlobject.key), int(sqlobject.ttl), str(sqlobject.type), value)) return True try: response = dns.query.tcp(update, '127.0.0.1') except PeerBadKey or PeerBadSignature: self.log.error('Cannot update dns entry, secret invalid') return False if response.rcode() != 0: self.log.error('DNS update failed, got error %s on domain %s' % ( dns.rcode.to_text(response.rcode()), domain.name)) return False if delete: self.log.info('Successfully deleted dns-record %s %d IN %s %s' % ( str(sqlobject.key), int(sqlobject.ttl), str(sqlobject.type), value)) else: self.log.info('Successfully added dns-record %s %d IN %s %s' % ( str(sqlobject.key), int(sqlobject.ttl), str(sqlobject.type), value)) return True
def _prepare_dns_updates(add_rrsets, delete_rrsets, my_zones): """Prepare a set of DNS updates for the specified rrset additions and deletions. One update will be created for each zone mentioned in the rrsets. Constrints will be added to the DNS update message: * when deleting the record, ensure that it existed * when adding a record, ensure that it did not exist * when modifying (deleting and readding) a record, ensure that it existed Returns a dict mapping zone names to dnspython Update objects. """ updates = {} for rrset in delete_rrsets: zone = _get_zone(rrset.name, my_zones) # Create a new update for this zone if necessary if zone not in updates: updates[zone] = dns.update.Update(zone, keyring=_create_keyring(zone)) update = updates[zone] # Require the record exist before deleting it. update.present(rrset.name, *rrset.items) # Delete the record. update.delete(rrset.name, rrset) for rrset in add_rrsets: zone = _get_zone(rrset.name, my_zones) # Create a new update for this zone if necessary if zone not in updates: updates[zone] = dns.update.Update(zone, keyring=_create_keyring(zone)) update = updates[zone] # For additions only, require that the record not exist before adding # it. We're processing each modification as a delete/add pair, so # it will exist before the update (and we ensure this above). if rrset.name not in [delete.name for delete in delete_rrsets]: update.absent(rrset.name, rrset.rdtype) update.add(rrset.name, rrset) return updates
def create_record(self): update = dns.update.Update(self.zone, keyring=self.keyring, keyalgorithm=self.algorithm) for entry in self.module.params['value']: try: update.add(self.module.params['record'], self.module.params['ttl'], self.module.params['type'], entry) except AttributeError: self.module.fail_json(msg='value needed when state=present') except dns.exception.SyntaxError: self.module.fail_json(msg='Invalid/malformed value') response = self.__do_update(update) return dns.message.Message.rcode(response)
def dns_register_wildcard_cname(name): '''Creates a DNS wildcard CNAME entry '*.{name}' pointing to '{name}' ''' assert name, 'Invalid parameters to DNS UPDATE: name={name}'.format(name=name) dns_params = _dns_init() cname = '*.{name}'.format(name=name) af, addr, port = [ dns_params.pop(attr) for attr in ('af', 'addr', 'port') ] print 'Registering DNS wildcard CNAME: {cname} -> {name}.{zone}'.format(cname=cname, name=name, zone=dns_params['zone']) update = dns.update.Update(**dns_params) #update = dns.update.Update(zone, keyring=keyring, keyname=zone, keyalgorithm=dns.tsig.HMAC_MD5) update.add(cname, 60, 'cname', name) response = dns.query.udp(update, where=addr, port=port, timeout=60, af=af)
def _submitDNS(self, value): update = dns.update.Update( self.zone, keyring=dns.tsigkeyring.from_text(self.tsig_key)) update.delete(self.record, self.type) update.add(self.record, self.ttl, self.type, "%s" % value) #print update response = dns.query.tcp(update, self.dns_ip) #print response #if response.rcode() != 0: #raise ValueError("Unexpected Response Code") return str(response)
def update(): if 'hostname' not in request.args: abort(400) if 'myip' not in request.args: abort(400) hostname = dns.name.from_text(request.args['hostname']) domain = dns.name.from_text(DOMAIN) particle = hostname.relativize(domain) if not hostname.is_subdomain(domain): return 'nohost' update = dns.update.Update(DOMAIN, keyring=KEYRING) update.delete(str(particle)) update.add(str(particle), 600, 'a', str(request.args['myip'])) response = dns.query.tcp(update, DNSHOST) if response.rcode() == 0: return "good "+str(request.args['myip']) else: return "dnserr"
def generate_update_from_diff(zonename, original_zone, updated_zone, keyring, keyalgo, force_conflicts): update = dns.update.Update(zonename, keyring = keyring, keyalgorithm = keyalgo) if (not force_conflicts): # Require the old SOA to still be present # (Essentially requires that the zone hasn't changed while editing) oldsoa = get_single_record(original_zone.iterate_rdatas(), dns.rdatatype.SOA) update.present(oldsoa[0], oldsoa[2]) added, removed = get_zone_diff(original_zone, updated_zone) for (name, ttl, rdata) in removed: update.delete(name, rdata) for (name, ttl, rdata) in added: update.add(name, ttl, rdata) return [update, len(added), len(removed)]
def configure(self): cfg = self.ud.getSection('dnsupdate') for key in ('tsighost', 'tsigkey', 'host', 'domain', 'server'): if key not in cfg: return instanceid = self.id.getInstanceId() ipaddr = self.id.getPublicIPv4() template = True for key in ('prefix', 'domain', 'start'): if key not in cfg: template = False break if template: index = int(self.id.getAMILaunchIndex()) start = int(cfg['start']) clusterid = '%02d' % (start + index) cfg['host'] = '%s%s' % (cfg['prefix'], clusterid) # Set keyring using TSIG variables from User Data keyring = dns.tsigkeyring.from_text({ cfg['tsighost'] : cfg['tsigkey'] }) update = dns.update.Update(cfg['domain'], keyring=keyring) # Clear all TXT and A entries for domain update.delete(cfg['host'], 'a') dns.query.tcp(update, cfg['server']) update.delete(cfg['host'], 'txt') dns.query.tcp(update, cfg['server']) # Create A entry with public IP address update.add(cfg['host'], 300, 'a', ipaddr) dns.query.tcp(update, cfg['server']) # Create TXT entry with instanceID update.add(cfg['host'], 300, 'txt', instanceid) dns.query.tcp(update, cfg['server'])
def modify_zone_record(domain_name, domain_ip, key_file): """modify DNS zone record from dns server and return rcode. Args: String domain_name String domain_ip Returns: String rcode issue #1: when update the forward record, also need update the reserve record issue #2: before update the forward record, u need validate if the record is exist,if not exist, return fail, if exist ,return success,and update the record """ KeyRing = getKey(key_file) ttl = 3600 record_type = "A" domain = dns.name.from_text(DOMAIN) update = dns.update.Update(DOMAIN, keyring = KeyRing) update.delete(str(domain_name)) update.add(str(domain_name), ttl, record_type, str(domain_ip)) response = dns.query.tcp(update, DNSHOST) rcode = response.rcode() return rcode
def dns_push(self, logid, fqdn, v4_addrs = [], v6_addrs = [], cname = None): """ Push a set of A and AAAA records to the DNS, but only if they've changed. """ # check if there are any changes, sort the addresses first so that # scoring order changes do not cause cache misses v4_addrs = sorted(v4_addrs) v6_addrs = sorted(v6_addrs) if cname != None: cache_key = "CNAME " + cname v4_addrs = v6_addrs = [] else: cache_key = ' '.join(v4_addrs) + ' ' + ' '.join(v6_addrs) if self.dns_update_cache.get(fqdn) == cache_key: #self.log.info("DNS push [%s]: %s - no changes", logid, fqdn) return self.dns_update_cache[fqdn] = cache_key # look up the zone file to update zone = self.dns_pick_zone(fqdn) if zone == None: self.log.info("DNS push [%s]: %s is not in a managed zone, not updating", logid, fqdn) return # add a dot to make sure bind doesn't add the zone name in the end fqdn = fqdn + '.' self.log.info("DNS pushing [%s]: %s: %s", logid, fqdn, cache_key) update = dns.update.Update(zone, keyring=self.dns_keyring, keyalgorithm="hmac-sha256") update.delete(fqdn) if cname != None: update.add(fqdn, self.dns_ttl, 'cname', cname + '.') else: for a in v4_addrs: update.add(fqdn, self.dns_ttl, 'a', a.encode('ascii')) for a in v6_addrs: update.add(fqdn, self.dns_ttl, 'aaaa', a.encode('ascii')) try: response = dns.query.tcp(update, self.dns_master) except socket.error as e: self.log.error("DNS push [%s]: update error, cannot connect to DNS master: %r", logid, e) return except dns.tsig.PeerBadKey as e: self.log.error("DNS push [%s]: update error, DNS master does not accept our key: %r", logid, e) return except Exception as e: self.log.error("DNS push [%s]: update error: %r", logid, e) return self.log.info("DNS push [%s]: Sent %s: %s - response: %s / %s", logid, zone, fqdn, dns.opcode.to_text(dns.opcode.from_flags(response.flags)), dns.rcode.to_text(dns.rcode.from_flags(response.flags, response.ednsflags)) )
if __name__ == '__main__': options, args = parse_options() print options.remove, options.add if not (options.remove or options.add): print "figure out how to print usage" sys.exit(1) config = load_config(options.config) tsig = config['domain']['tsig'] domain_name = config['domain']['name'] name_server = config['domain']['server'] ttl = config['domain']['ttl'] keyring = dns.tsigkeyring.from_text({ "%s." % (domain_name) : tsig }) update = dns.update.Update(domain_name, keyring=keyring) if options.remove: update.delete(options.name, 'A', options.ipaddress) elif options.add: update.add(options.name, ttl, 'A', options.ipaddress) try: response = dns.query.tcp(update, name_server) except Exception, e: print e