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 main(): if (len(sys.argv) != 7): usage() return cmd = sys.argv[1] print "cmd", cmd hostname = sys.argv[2] print "hostname", hostname dns_ip = sys.argv[3] print "hostname", dns_ip domainname = sys.argv[4] print "Domain name", domainname ip = sys.argv[5] print "ip", ip prt = sys.argv[6] print "ip", prt # replace example with the domainname # replace host w/ the hostame update = dns.update.Update(domainname, keyring=keyring) update.replace(hostname, 300, prt, ip) # replace 10.0.0.1 with the dns server ip response = dns.query.tcp(update, dns_ip) print response
def addREV(ipaddress, ttl, name): reversedomain = dns.reversename.from_address(str(ipaddress)) reversedomain = str(reversedomain).rstrip('.') log.debug('[addREV] - reversedomain %s' % reversedomain) authdomain = getrevzone_auth(str(reversedomain)).rstrip('.') log.debug('[addREV] - authdomain %s' % authdomain) label = stripptr(authdomain, reversedomain) log.debug('[addREV] - label %s' % label) name = name if name.endswith("."): return else: name = name + '.' log.debug('[addREV] - name %s' % name) check4TSIG = TSIGSecured(authdomain) if check4TSIG.isSecure(authdomain): key = str(check4TSIG.TSIG(authdomain)) keyname = authdomain.replace(".", "_") keyring = dns.tsigkeyring.from_text({keyname: key}) update = dns.update.Update(authdomain, keyring=keyring) else: update = dns.update.Update(authdomain) update.replace(label, monitor_ttl, dns.rdatatype.PTR, name) response = dns.query.tcp(update, monitor_nameserver) return response
def AddDNS(ip, rev_address, trap, host, sender, value='127.0.0.1'): print('Adding type A record "%s" for %s.%s :' % (value, rev_address, DNSBL_ZONE)), timestamp = int(time.time()) date = datetime.datetime.fromtimestamp( timestamp, tz=pytz.utc).strftime('%Y-%m-%dZ%H:%M:%S') keyring = dns.tsigkeyring.from_text(RNDC_KEY) update = dns.update.Update(DNSBL_ZONE, keyring=keyring, keyalgorithm='hmac-md5.sig-alg.reg.int') update.replace(rev_address, 8600, 'A', value) update.replace(rev_address, 8600, 'TXT', '"Address %s added at %d (%s)"' % (ip, timestamp, date)) response = dns.query.tcp(update, DNS_HOSTNAME) if response.rcode() == dns.rcode.NOERROR: print('NOERROR, Adding to log file') # write to log file with open("/var/log/dnsbl_spamtrap.log", "a") as log: log.write( '{},IP-BANNED={},TRAP={},SENDER-HOST={},SENDER-EMAIL={}\n'. format(date, ip, trap, host, sender)) return 0 elif response.rcode() == dns.rcode.REFUSED: print('REFUSED') return 1 else: print('Response: %s' % (response, )) return 2
def on_post(self, req, resp): update = dns.update.Update( CONFIG.get('server', 'zone'), keyring=KEYRING, keyalgorithm=CONFIG.get('key', 'algo') ) body = req.context['json']['data'] LOGGER.info("Received %d byte long paste" % len(body)) try: base64.b64decode(body.decode("ascii")) except Exception: raise falcon.HTTPBadRequest("Wrong encoding", "Your data is not base64 encoded !") uid = str(uuid.uuid4()) i = 0 for chunk in chunks(body, 255): i += 1 LOGGER.info("Registering chunk %d of paste %s : %s" % (i, uid, chunk)) update.replace("%d.%s" % (i, uid), 10, 'TXT', str(chunk)) response = dns.query.tcp(update, CONFIG.get('server', 'address')) LOGGER.info("Registering chunk number of paste %s" % uid) update.replace("%s" % uid, 10, 'TXT', "%d" % i) response = dns.query.tcp(update, CONFIG.get('server', 'address')) req.context['result'] = {"paste": uid} LOGGER.info("Paste %s registered !" % uid)
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 update_a_record(hostname, ip, domain, domain_ip, keyring, algorithm): """Update the DNS record :Returns: None :param hostname: The name to give the DNS record :type hostname: String :param ip: The IP the hostname should map to :type ip: String :param domain: The FQDN of the vLab server :type domain: String :param domain_ip: The IPv4 address of the DNS server to send the udpate to :type domain_ip: String :param keyring: The dnssec creds required for making an update :type keyring: dns.tsigkeyring.from_text :type algorithm: The encryption method used for the keyring creds :type algorithm: String """ update = dns.update.Update(domain, keyring=keyring, keyalgorithm=algorithm) update.replace(hostname, 300, 'a', ip) # 'a' means A-record, 300 is the TTL dns.query.udp(update, domain_ip)
def update_zone(self): keyring = dns.tsigkeyring.from_text({ self.key_name: self.key }) update = dns.update.Update(self.domain, keyring=keyring) update.replace(self.host, 300, 'A', self.local_ip) try: response = dns.query.tcp(update, master_dns_server, timeout=10) logging.info(response) except EOFError as e: logging.error('Can not connect to DNS server, check your ' 'connection, exiting') sys.exit(1) except dns.tsig.PeerBadKey as e: logging.error('Can not read authenticate with DNS server, ' 'check credentials, exiting') logging.error(e) sys.exit(1) except dns.tsig.PeerBadTime as e: logging.error('Time on local sever is not in sync with time' ' on the remote server, exiting') logging.error(e) sys.exit(1)
def _generate_update(self, zone): update = dns.update.Update( zone, keyring=self.keyring, keyalgorithm=self.keyalgorithm, ) z = dns.zone.from_xfr(dns.query.xfr(self.server, zone)) changed = False if self.ipv4addr: for name, ttl, rdata in z.iterate_rdatas('A'): if ttl != self.ttl: continue if self.ipv4addr == IPv4Address(rdata.address): continue update.replace(name, self.ttl, 'A', str(self.ipv4addr)) changed = True if self.ipv6net: for name, ttl, rdata in z.iterate_rdatas('AAAA'): if ttl != self.ttl: continue ipv6addr = self._relocate_ipv6_host(IPv6Address(rdata.address)) if ipv6addr == IPv6Address(rdata.address): continue update.replace(name, self.ttl, 'AAAA', str(ipv6addr)) changed = True return update if changed else None
def update_txt( nserver: str, key_name: str, secret: str, hmac_algo: str, zone: str, records: Mapping[str, str], ttl: int, ) -> None: """ Upsert TXT records through TSIG authenticated dns update request. nserver: DNS server to send update to. key_name: Name of shared key secret: Shared secret (b64 string) hmac_algo: hmac algorithm to use for signing zone: DNS zone to update records: Map from domain names (fully qualified) to TXT record values. ttl: time to live """ update = dns.update.Update( zone, keyring=dns.tsigkeyring.from_text({ key_name: secret, }), keyalgorithm=dns.name.from_text(hmac_algo), ) for fqdn, value in records.items(): update.replace(strip_zone(fqdn, zone), ttl, 'txt', f'"{value}"') dns.query.tcp(update, nserver, timeout=10)
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 dockerddns(action, event, dnsserver=config['dockerddns']['dnsserver'], ttl=60): update = dns.update.Update(config['dockerddns']['zonename'], keyring=keyring, keyname=config['dockerddns']['keyname']) if (action == 'start' and event['ip'] != '0.0.0.0' ): logging.debug('[%s] Updating dns %s , setting %s.%s to %s' % (event['name'], dnsserver, event['hostname'], config['dockerddns']['zonename'],event['ip'])) update.replace(event['hostname'], ttl, 'A', event['ip']) elif (action == 'die' ): logging.debug('[%s] Removing entry for %s.%s in %s' % (event['name'], event['hostname'], config['dockerddns']['zonename'], dnsserver)) update.delete(event['hostname']) try: response = dns.query.tcp(update, dnsserver, timeout=10) except (socket.error, dns.exception.Timeout): logging.debug('Timeout updating DNS') response = 'Timeout Socket' pass except dns.query.UnexpectedSource: logging.debug('Unexpected Source') response = 'UnexpectedSource' pass except dns.tsig.PeerBadKey: logging.debug('Bad Key for DNS, Check your config files') response = "BadKey" pass if response.rcode() != 0: logging.error("[%s] Error Reported while updating %s (%s/%s)" % (event['name'],event['hostname'],dns.rcode.to_text(response.rcode()), response.rcode()))
def domain_add(domain, ip): try: dns.resolver.query(domain + ".lan", "a") except dns.resolver.NXDOMAIN: update = dns.update.Update("lan") update.replace(domain, 300, "a", ip) dns.query.tcp(update, "127.0.0.1")
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_dns(zone, record, dns_update_host, new_ip, key): record = record.split('.')[0] # we use just the non-fqdn record, not the full record. print "Updating zone [%s] record [%s] on dns host [%s] with new ip [%s]" % (zone, record, dns_update_host, new_ip) keyring = dns.tsigkeyring.from_text({zone : key}) update = dns.update.Update(zone, keyring = keyring, keyname = zone, keyalgorithm = 'hmac-sha512') update.replace(record, 60, 'A', new_ip) response = dns.query.tcp(update, dns_update_host) sys.exit(0)
def test_TSIG(self): keyring = dns.tsigkeyring.from_text( {"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="}) update = dns.update.Update("example.", keyring=keyring) update.replace("host.example.", 300, "A", "1.2.3.4") wire = update.to_wire() update2 = dns.message.from_wire(wire, keyring) self.assertEqual(update, update2)
def test_TSIG(self): keyring = dns.tsigkeyring.from_text( {'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ=='}) update = dns.update.Update('example.', keyring=keyring) update.replace('host.example.', 300, 'A', '1.2.3.4') wire = update.to_wire() update2 = dns.message.from_wire(wire, keyring) self.assertEqual(update, update2)
def _update_record(self, qtype, fqdn, data, do_ptr): log.debug('DDNS update for record {}, fqdn: {}'.format(qtype, fqdn)) origin, name = self._parse_name(fqdn) update = dns.update.Update(origin, keyring=self.keyring) update.replace(name, self.ttl, qtype, data) self._do_update(update) if do_ptr: self._update_ptr(fqdn, data)
def ddns(dns_ip, domain, ip, tsigkey_name, tsigkey): keyring = dns.tsigkeyring.from_text({ tsigkey_name : tsigkey }) update = dns.update.Update('example.', keyring=keyring) update.replace(ip, 300, 'A', sys.argv[1]) response = dns.query.tcp(update, dns_ip, timeout=10)
def modify_record(self): update = dns.update.Update(self.zone, keyring=self.keyring, keyalgorithm=self.algorithm) update.replace(self.module.params['record'], self.module.params['ttl'], self.module.params['type'], self.module.params['value']) response = self.__do_update(update) return dns.message.Message.rcode(response)
def add_a_record(server, zone, key, name, address, 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.replace(name, ttl, 'a', address) response = dns.query.tcp(update, server) return response
def create_ptr(self, ptr): if not isinstance(ptr, Ptr): raise ValueError("Argument must be of Ptr class.") update = dns.update.Update(ptr.get_ptr_zone(), keyring=self.keyring, keyalgorithm=HMAC_MD5) update.replace(ptr.get_ptr_zone_name(), 300, 'PTR', ptr.ptr) self.logger.debug("Updating %s" % self.dns_hostname) dns.query.tcp(update, self.dns_hostname)
def update_a(self): try: update = dns.update.Update(self.get_domain_fqdn(), keyring=self.__keyring) # Só realiza o update se tiver uma entrada TXT e o valor dela bater com o calculado pelo servidor update.present(self.__hostname, 'TXT', self.__txt_value) update.replace(self.__hostname, self.__ttl, 'A', self.__ip) return dns.query.tcp(update, self.__server_ip).rcode() except Exception, error: raise Exception("Error updating DNS A Entry: %s" % (error))
def update(domain, host, ip): keyring = dns.tsigkeyring.from_text({'rndc-key': 'myRNDCkey=='}) update = dns.update.Update('{0}.'.format(domain), keyring=keyring) update.replace(host, 300, 'A', ip) response = dns.query.tcp(update, '127.0.0.1', timeout=10) return "update with {0}\n".format(ip)
def create_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.replace(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)) logging.debug("DNS record PTR") ### Create reverse entry (PTR) # Neat function to generate a reverse entry reventry = dns.reversename.from_address(new_ipaddress) revzone = '' # Specify the reverse lookup zone based on the reverse IP address. # The labels[X:] property allows you to specify which octet to use. # e.g. 3: will apply the record to the 10.in-addr.arpa zone, # whereas 1: will apply it to the 72.23.10.in-addr.arpa zone revzone = b'.'.join(dns.name.from_text(str(reventry)).labels[1:]) # revzone = revzone.decode() # Prepare the payload for the DNS record update raction = dns.update.Update(zone=revzone, keyname='dynamic.vmware.haf.', keyring=keyring, keyalgorithm=dns.tsig.HMAC_SHA512) # Although we are updating the reverse lookup zone, # the record needs to point back to the ‘test.example.com’ domain, not the 10.in-addr.arpa domain new_host_fqdn = '%s.%s' % (new_hostname, dns_domain) # Inject the updated record details into the the class, preparing for submission to the DNS server raction.replace(reventry, TTL, dns.rdatatype.PTR, new_host_fqdn) # submit the new record to the DNS server to apply the update response = dns.query.tcp(raction, PRIMARY_DNS_SERVER_IP, timeout=5) flags = dns.flags.to_text(response.flags) logging.debug(" PTR DNS update response: {} {}".format( dns.rcode.to_text(response.rcode()), flags))
def UpdateDnsA(self,host,ip,domain,type,dnsip): logging.debug('UpdateDnsA: '+host+' '+ip+' '+domain+' '+dnsip) update = dns.update.Update(domain) update.replace(host, 3600, type, ip) try: logging.debug('UpdateDnsA: writing to dns server') response = dns.query.tcp(update, dnsip) except: logging.info('Writing A record failed') logging.exception('')
def UpdateDnsA(self, host, ip, domain, type, dnsip): logging.debug('UpdateDnsA: ' + host + ' ' + ip + ' ' + domain + ' ' + dnsip) update = dns.update.Update(domain) update.replace(host, 3600, type, ip) try: logging.debug('UpdateDnsA: writing to dns server') response = dns.query.tcp(update, dnsip) except: logging.info('Writing A record failed') logging.exception('')
def modify_record(self): update = dns.update.Update(self.zone, keyring=self.keyring, keyalgorithm=self.algorithm) update.replace(self.record, self.ttl, self.type, self.value) response = self.__do_update(update) if dns.message.Message.rcode(response) == 0: return True else: return False
def dockerbind(action, event, config): """ This will update a zone in a bind dns configured for dynamic updates """ dnsserver = config['dnsserver'] ttl = config['ttl'] port = config['dnsport'] update = dns.update.Update(config['zonename'], keyring=config['keyring'], keyname=config['keyname']) #logging.debug('EVENT: %s', event) try: if "srvrecords" in event: srvrecords = event["srvrecords"].split() for srv in srvrecords: values = srv.split("#") #print("%s %s\n" % (values, event['hostname'])) if action == 'start' and event['ip'] != '0.0.0.0': update.replace(event['hostname'], ttl, 'A', event['ip']) if event['ipv6'] != '': update.replace(event['hostname'], ttl, 'AAAA', event['ipv6']) logging.info( '[%s] Updating dns %s , setting %s.%s to %s and %s', event['name'], dnsserver, event['hostname'], config['zonename'], event['ip'], event['ipv6']) else: logging.info('[%s] Updating dns %s , setting %s.%s to %s', event['name'], dnsserver, event['hostname'], config['zonename'], event['ip']) elif action == 'die': logging.info('[%s] Removing entry for %s.%s in %s', event['name'], event['hostname'], config['zonename'], dnsserver) update.delete(event['hostname']) response = dns.query.tcp(update, dnsserver, timeout=10, port=port) if response.rcode() != 0: logging.error("[%s] Error Reported while updating %s (%s/%s)", event['name'], event['hostname'], dns.rcode.to_text(response.rcode()), response.rcode()) except (socket.error, dns.exception.Timeout): logging.error('Timeout updating DNS') response = 'Timeout Socket' except dns.query.UnexpectedSource: logging.error('Unexpected Source') response = 'UnexpectedSource' except dns.exception.SyntaxError: logging.error('Missing parameters to update DNS') except dns.tsig.PeerBadKey: logging.error('Bad Key for DNS, Check your config files') response = "BadKey" return event
def update_rev(self): try: name = self.validate_rev_name() if not name: return None update = dns.update.Update(self.get_rev_domain_fqdn(), keyring=self.__keyring) update.replace(name, self.__ttl, 'PTR', self.get_fqdn()) return dns.query.tcp(update, self.__server_ip).rcode() except Exception, error: raise Exception("Error updating DNS PTR Entry: %s" % (error))
def edit_record(self, domain_zone, domain_name, ttl, record_type, record_value): update = dns.update.Update(domain_zone, keyring=self.keyring, keyalgorithm=self.sha_type) update.replace(domain_name, ttl, record_type, record_value) dns.query.tcp(update, self.name_server_addr) if self.search_record(domain_name + '.' + domain_zone, record_type): return {'code': 0, 'message': 'ok'} else: return {'code': '2', 'message': 'not edit'}
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 modify_record(self): update = dns.update.Update(self.zone, keyring=self.keyring) update.replace(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 update(self, domain="", hostIP=""): if domain == "": return False update = dns.update.Update('flashhold.com', keyring=self.keyring) if hostIP: update.replace(domain, 300, 'A', hostIP) else: update.replace(domain, 300, 'A', settings.DNS_HOST) response = dns.query.tcp(update, settings.DNS_HOST) print response
def modify_record(self): update = dns.update.Update(self.zone, keyring=self.keyring) update.replace(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 update_dns(coords=None, domain=None, key=None): if domain and key and coords: print('Update DNS: {0}'.format(coords)) keyring = dns.tsigkeyring.from_text({ domain : key }) update = dns.update.Update(domain, keyring=keyring) update.replace('geo', 300, dns.rdatatype.TXT, '"%s"' % coords) return dns.query.tcp(update, 'localhost') else: return None
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_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_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_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 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 add_reverse_record(fqdn, domain, ip_address, ttl, dns_server, key_file, key_name): """Add a reverse PTR record to the specific DNS server and zone.""" reverse_fqdn = str(dns.reversename.from_address(ip_address)) reverse_ip = re.search(r"([0-9]+).(.*).$", reverse_fqdn).group(1) reverse_domain = re.search(r"([0-9]+).(.*).$", reverse_fqdn).group(2) try: key_ring = keyutils.read_tsigkey(key_file, key_name) except: raise update = dns.update.Update(reverse_domain, keyring = key_ring) update.replace(reverse_ip, ttl, 'PTR', fqdn + ".") try: response = dns.query.tcp(update, dns_server) except Exception, err: exc_type, exc_obj, exc_tb = sys.exc_info() print "type: %s, obj: %s, tb: %s" % (exc_type, exc_obj, exc_tb) print "Unhandled exception in add_forward_record: %s" % err raise
def publish(self): # # Replace the keyname and secret with appropriate values for your # configuration. # keyring = dns.tsigkeyring.from_text({ 'host-example.' : 'XXXXXXXXXXXXXXXXXXXXXX==' }) # # Replace "example.com" with your domain, and "MY_HOSTNAME" with your hostname. # update = dns.update.Update('example.com', keyring=keyring) update.replace('MY_HOSTNAME', 300, 'A', self.myip) # # Replace "127.0.0.1" with the IP address of your master server. # response = dns.query.tcp(update, '127.0.0.1', timeout=10)
def updatedns_records(self): config = getconfig.Config() configParser = config.getConfig() dbcon = dbconn.DbConn() keyname = configParser['keyname'] secretkey = configParser['secretkey'] zone = configParser['zone'] dnsServer = configParser['dnsserver'] ddnsRecords = dbcon.getRecords() self.LOG.debug("keyname: {}, secretkey: {}, zone: {}, dnsserver: {}".format(keyname,secretkey,zone, dnsServer)) for row in ddnsRecords: '''created_at | updated_at | data | action | name | type | ttl''' '''vmname = row[4].split('.')[0]''' vmname = row[4][:len(row[4])-(len(zone)+1)] ip = row[2] recType = row[5] ttl = row[6] created = row[0] updated = row[1] action = row[3] if (action == 'UPDATE') or (action == 'CREATE'): try: keyring = dns.tsigkeyring.from_text({keyname : secretkey}) except: raise update = dns.update.Update(zone, keyring=keyring) self.LOG.debug("vmname: {}, ip {}, record Type: {}".format(vmname, ip, recType)) update.replace(vmname, 300, recType, ip) try: response = dns.query.tcp(update, dnsServer) except dns.tsig.PeerBadKey: self.LOG.exception ("The remote DNS server ns5.kcdc.att.com. did not accept the key passed.") raise except Exception, err: exc_type, exc_obj, exc_tb = sys.exc_info() self.LOG.exception ("type: %s, obj: %s, tb: %s" % (exc_type, exc_obj, exc_tb)) self.LOG.exception ("Unhandled exception in add_forward_record: %s" % err) raise self.LOG.debug("Forward Record Output: %s" % response)
def add_forward_record(hostname, domain, ip_address, ttl, dns_server, key_file, key_name): """Add an A record to the specific DNS server with the provided hostname/IP/key information.""" try: key_ring = keyutils.read_tsigkey(key_file, key_name) except: raise update = dns.update.Update(domain, keyring = key_ring) update.replace(hostname, ttl, 'A', ip_address) try: response = dns.query.tcp(update, dns_server) except dns.tsig.PeerBadKey: print "The remote DNS server %s did not accept the key passed." % dns_server raise except Exception, err: exc_type, exc_obj, exc_tb = sys.exc_info() print "type: %s, obj: %s, tb: %s" % (exc_type, exc_obj, exc_tb) print "Unhandled exception in add_forward_record: %s" % err raise
def plugin(srv, item): srv.logging.debug("*** MODULE=%s: service=%s, target=%s", __file__, item.service, item.target) if HAVE_DNS == False: return False config = item.config dns_nameserver = config['dns_nameserver'] dns_keyname = config['dns_keyname'] dns_keyblob = config['dns_keyblob'] try: zone, domain, ttl, rrtype = item.addrs except: srv.logging.error("Incorrect target configuration for {0}/{1}".format(item.service, item.target)) return False text = item.message try: keyring = dns.tsigkeyring.from_text( { str(dns_keyname) : str(dns_keyblob) }); update = dns.update.Update(zone, keyring = keyring, keyname = dns_keyname, keyalgorithm = 'hmac-sha256') #FIXME configurable if rrtype.upper() == 'TXT': text = '"%s"' % text update.replace(domain, ttl, rrtype, text) response = dns.query.tcp(update, dns_nameserver, timeout=10) srv.logging.debug("DNS Update: {0}".format(dns.rcode.to_text(response.rcode()))) except Exception, e: srv.logging.warning("Cannot notify to dnsupdate `%s': %s" % (dns_nameserver, str(e))) return False
def update(): user_config = Config.users[request.authorization.username] hostname = request.args.get("hostname") if hostname not in user_config["hostnames"]: raise Exception("hostname %s not defined for user %s" % (hostname, request.authorization.username)) myip = request.args.get("myip") if myip is None: raise Exception("parameter 'myip' is required.") try: ip = socket.inet_ntoa(socket.inet_aton(myip)) except: raise Exception("invalid ip '" + myip + "' in get parameter 'myip'") keyring = dns.tsigkeyring.from_text(Config.keyring_data) update = dns.update.Update( user_config["domain"], keyring=keyring, keyname=Config.key_name, keyalgorithm=Config.key_algo ) update.replace(str(hostname), 10, "A", ip) response = dns.query.tcp(update, Config.nameserver) return "ok"
def create_forward_zone_record(dns_server, zone_name, record_name, record_type, record_data, ttl, key_file): """ Parse passed elements and determine which records to create. Args: String dns_server String zone_name String record_name (just record name, not FQDN) String record_type (A, AAAA, etc) String record_data (IP address) Int ttl String key_name (from Key model) Return: Dict containing {description, output} from record creation issue #3: before add the forward record, u need validate if the record is exist,if not exist, return fail, if exist ,return success,and add the record """ KeyRing = getKey(key_file) update = dns.update.Update(zone_name, keyring = KeyRing) update.replace(record_name, ttl, record_type, record_data) response = dns.query.tcp(update, dns_server, timeout=10) rcode = response.rcode() return rcode
def get_crt(account_key, csr, skip_check=False, log=LOGGER, CA=PROD_CA, contact=None, dns_zone_update_server=None, dns_zone_keyring=None, dns_zone=None, dns_update_algo=None): directory, acct_headers, alg, jwk, nonce = None, None, None, None, [None] # global variables # helper functions - base64 encode for jose spec def _b64(b): return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "") # helper function - run external commands def _cmd(cmd_list, stdin=subprocess.PIPE, cmd_input=None, err_msg="Command Line Error"): proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) out, err = proc.communicate(cmd_input) if proc.returncode != 0: raise IOError("{0}\n{1}".format(err_msg, err)) return out # helper function - make request and automatically parse json response def _do_request(url, data=None, err_msg="Error", depth=0): try: resp = urlopen(Request(url, data=data, headers={"Content-Type": "application/jose+json", "User-Agent": "acme-tiny-dns"})) resp_data, code, headers = resp.read().decode("utf8"), resp.getcode(), resp.headers except IOError as e: resp_data = e.read().decode("utf8") if hasattr(e, "read") else str(e) code, headers = getattr(e, "code", None), {} nonce[0] = headers.get('Replay-Nonce', None) try: resp_data = json.loads(resp_data) # try to parse json results except ValueError: pass # ignore json parsing errors if depth < 100 and code == 400 and resp_data['type'] == "urn:ietf:params:acme:error:badNonce": raise IndexError(resp_data) # allow 100 retrys for bad nonces if code not in [200, 201, 204]: raise ValueError("{0}:\nUrl: {1}\nResponse Code: {2}\nResponse: {3}".format(err_msg, url, code, resp_data)) return resp_data, code, headers # helper function - make signed requests def _send_signed_request(url, payload=None, err_msg="Error", depth=0): payload64 = _b64(json.dumps(payload).encode('utf8')) if payload is not None else "" if nonce[0] is None: _do_request(directory['newNonce']) protected = {"url": url, "alg": alg, "nonce": nonce[0]} protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']}) protected64 = _b64(json.dumps(protected).encode('utf8')) protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8') out = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], cmd_input=protected_input, err_msg="OpenSSL Error") data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)}) try: return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth) except IndexError: # retry bad nonces (they raise IndexError) return _send_signed_request(url, payload, err_msg, depth=(depth + 1)) # helper function - poll until complete def _poll_until_not(url, pending_statuses, err_msg="Error", timeout=90): deadline = time.time() + timeout while True: result, _, _ = _send_signed_request(url, err_msg=err_msg) if time.time() < deadline and result['status'] in pending_statuses: time.sleep(2) continue return result # parse account key to get public key log.info("Parsing account key...") out = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"], err_msg="OpenSSL Error") pub_pattern = r"modulus:\n\s+00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)" pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups() pub_exp = "{0:x}".format(int(pub_exp)) pub_exp = "0{0}".format(pub_exp) if len(pub_exp) % 2 else pub_exp alg = "RS256" jwk = { "e": _b64(binascii.unhexlify(pub_exp.encode("utf-8"))), "kty": "RSA", "n": _b64(binascii.unhexlify(re.sub(r"(\s|:)", "", pub_hex).encode("utf-8"))), } accountkey_json = json.dumps(jwk, sort_keys=True, separators=(',', ':')) thumbprint = _b64(hashlib.sha256(accountkey_json.encode('utf8')).digest()) # find domains log.info("Parsing CSR...") out = _cmd(["openssl", "req", "-in", csr, "-noout", "-text"], err_msg="Error loading {0}".format(csr)) domains = set([]) common_name = re.search(r"Subject:.*? CN\s?=\s?([^\s,;/]+)", out.decode('utf8')) if common_name is not None: domains.add(common_name.group(1)) subject_alt_names = re.search(r"X509v3 Subject Alternative Name: \n +([^\n]+)\n", out.decode('utf8'), re.MULTILINE|re.DOTALL) if subject_alt_names is not None: for san in subject_alt_names.group(1).split(", "): if san.startswith("DNS:"): domains.add(san[4:]) log.info("Found domains: {0}".format(", ".join(domains))) # get the ACME directory of urls log.info("Getting directory...") directory, _, _ = _do_request(CA, err_msg="Error getting directory") log.info("Directory found!") # create account, update contact details (if any), and set the global key identifier log.info("Registering account...") reg_payload = {"termsOfServiceAgreed": True} account, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering") log.info("{0}egistered: {1}".format("R" if code == 201 else "Already r", acct_headers['Location'])) if contact is not None: account, _, _ = _send_signed_request(acct_headers['Location'], {"contact": contact}, "Error updating contact details") log.info("Updated contact details:\n{0}".format("\n".join(account['contact']))) # create a new order log.info("Creating new order...") order_payload = {"identifiers": [{"type": "dns", "value": d} for d in domains]} order, _, order_headers = _send_signed_request(directory['newOrder'], order_payload, "Error creating new order") log.info("Order created!") pending = [] # get the authorizations that need to be completed for auth_url in order['authorizations']: authorization, _, _ = _send_signed_request(auth_url, err_msg="Error getting challenges") domain = authorization['identifier']['value'] rdomain = '*.{0}'.format(domain) if authorization.get('wildcard', False) else domain if authorization['status'] == 'valid': log.info('Existing authorization for {0} is still valid!'.format(rdomain)) continue types = [c['type'] for c in authorization['challenges']] if 'dns-01' not in types: raise IndexError('Challenge dns-01 is not allowed for {0}. Permitted challenges are: {1}'.format(rdomain, ', '.join(types))) log.info("Verifying {0} part 1...".format(rdomain)) # find the dns-01 challenge and write the challenge file challenge = [c for c in authorization['challenges'] if c['type'] == "dns-01"][0] token = re.sub(r"[^A-Za-z0-9_\-]", "_", challenge['token']) keyauthorization = "{0}.{1}".format(token, thumbprint) record = _b64(hashlib.sha256(keyauthorization.encode('utf8')).digest()) log.info('_acme-challenge.%s. 60 IN TXT %s' % (domain, record)) zone = '_acme-challenge.'+domain if dns_zone: zone = dns_zone if isinstance(dns_zone, int): zone = '.'.join(('_acme-challenge.' + domain).split('.')[dns_zone:]) pending.append((auth_url, authorization, challenge, domain, keyauthorization, rdomain, record, token, zone)) if pending: if not dns_zone_update_server: log.info('Press enter to continue after updating DNS server') six.moves.input() else: log.debug('Performing DNS Zone Updates...') for authz in pending: auth_url, authorization, challenge, domain, keyauthorization, rdomain, record, token, zone = authz log.debug('Updating TXT record {0} in DNS zone {1}'.format('_acme-challenge.'+domain,zone)) update = dns.update.Update(zone, keyring=dns_zone_keyring, keyalgorithm=dns_update_algo) update.replace('_acme-challenge.'+domain+'.', 60, 'TXT', str(record)) response = dns.query.tcp(update, dns_zone_update_server, timeout=10) if response.rcode() != 0: raise Exception("DNS zone update failed, aborting, query was: {0}".format(response)) # verify each domain for authz in pending: auth_url, authorization, challenge, domain, keyauthorization, rdomain, record, token, zone = authz log.info("Verifying {0} part 2...".format(rdomain)) if not skip_check: # check that the DNS record is in place addr = set() for x in dns.resolver.query(dns.resolver.zone_for_name(domain), 'NS'): addr = addr.union(map(str, dns.resolver.query(str(x), 'A', raise_on_no_answer=False))) addr = addr.union(map(str, dns.resolver.query(str(x), 'AAAA', raise_on_no_answer=False))) if not addr: raise ValueError("No DNS server for {0} was found".format(domain)) qname = '_acme-challenge.{0}'.format(domain) valid = [] for x in addr: req = dns.message.make_query(qname, 'TXT') try: resp = dns.query.udp(req, x, timeout=30) except socket.error as e: log.warn('Exception contacting {0}: {1}'.format(x, e)) except dns.exception.DNSException as e: log.warn('Exception contacting {0}: {1}'.format(x, e)) else: if resp.rcode() != dns.rcode.NOERROR: raise ValueError("Query for {0} returned {1} on nameserver {2}".format(qname, dns.rcode.to_text(resp.rcode()), x)) else: answer = resp.get_rrset(resp.answer, dns.name.from_text("{0}.".format(qname.rstrip(".")), None), dns.rdataclass.IN, dns.rdatatype.TXT) if answer: txt = list(map(lambda x: str(x)[1:-1], answer)) if record not in txt: raise ValueError("{0} does not contain {1} on nameserver {2}".format(qname, record, x)) else: valid.append(x) else: raise ValueError("Query for {0} returned an empty answer set on nameserver {1}".format(qname, x)) if not valid: raise ValueError("No DNS server for {0} was reachable".format(qname)) # say the challenge is done _send_signed_request(challenge['url'], {}, "Error submitting challenges: {0}".format(rdomain)) # skip checking challenge state because it won't change if another challenge for this authorization has completed authorization = _poll_until_not(auth_url, ["pending"], "Error checking authorization status for {0}".format(rdomain)) if authorization['status'] != "valid": errors = [c for c in authorization['challenges'] if c['status'] not in ('valid', 'pending') and 'error' in c] dns_error = [c for c in errors if c['type'] == 'dns-01'] reason = dns_error[0] if dns_error else errors[0] if errors else None if reason is not None: raise ValueError("Challenge {0} failed (status: {1}) for {2}:\n{3}".format(reason['type'], reason['status'], rdomain, pprint.pformat(reason['error']))) else: raise ValueError("Authorization failed for {0}:\n{1}".format(rdomain, pprint.pformat(authorization))) log.info("{0} verified!".format(domain)) # poll the order to monitor when it's ready order = _poll_until_not(order_headers['Location'], ["pending"], "Error checking order status") if order['status'] != "ready": raise ValueError("Order failed: {0}".format(order)) # finalize the order with the csr log.info("Signing certificate...") csr_der = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"], err_msg="DER Export Error") _send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order") # poll the order to monitor when it's done order = _poll_until_not(order_headers['Location'], ["ready", "processing"], "Error checking order status") if order['status'] != "valid": raise ValueError("Order failed: {0}".format(order)) # download the certificate certificate_pem, _, cert_headers = _send_signed_request(order['certificate'], err_msg="Certificate download failed") if cert_headers['Content-Type'] != "application/pem-certificate-chain": raise ValueError("Certifice received in unknown format: {0}".format(cert_headers['Content-Type'])) # the spec recommends making sure that other types of PEM blocks don't exist in the response prefix = "-----BEGIN " suffix = "CERTIFICATE-----" for line in certificate_pem.splitlines(): if line.startswith(prefix) and not line.endswith(suffix): raise ValueError("Unexpected PEM header in certificate: {0}".format(line)) log.info("Certificate signed!") if pending: if not dns_zone_update_server: log.debug("You can now remove the _acme-challenge records from your DNS zone.") else: log.debug('Removing DNS records added for ACME challange...') for authz in pending: auth_url, authorization, challenge, domain, keyauthorization, rdomain, record, token, zone = authz log.debug('Removing TXT record {0} in DNS zone {1}'.format('_acme-challenge.'+domain,zone)) update = dns.update.Update(zone, keyring=dns_zone_keyring, keyalgorithm=dns_update_algo) update.delete('_acme-challenge.'+domain+'.', 'TXT') response = dns.query.tcp(update, dns_zone_update_server, timeout=10) return certificate_pem
def dman(zone, name, ttl, type, rr, delete=False): if type == 'cname' and len(rr) == 1: update = dns.update.Update(name, keyring=keyring) update.replace('host', ttl, type, rr)
# /usr/local/sbin/ddns.py $IPADDR # fi # # in /etc/ifup-local. # import sys import dns.update import dns.query import dns.tsigkeyring # # Replace the keyname and secret with appropriate values for your # configuration. # keyring = dns.tsigkeyring.from_text({ 'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ==' }) # # Replace "example." with your domain, and "host" with your hostname. # update = dns.update.Update('example.', keyring=keyring) update.replace('host', 300, 'A', sys.argv[1]) # # Replace "10.0.0.1" with the IP address of your master server. # response = dns.query.tcp(update, '10.0.0.1', timeout=10)
def run(api, args, logger): global logf action = None if __name__ == "cobbler.modules.nsupdate_add_system_post": action = "replace" elif __name__ == "cobbler.modules.nsupdate_delete_system_pre": action = "delete" else: return 0 settings = api.settings() if not str(settings.nsupdate_enabled).lower() in ["1", "yes", "y", "true"]: return 0 # read our settings if str(settings.nsupdate_log) is not None: logf = open(str(settings.nsupdate_log), "a+") nslog(">> starting %s %s\n" % (__name__, args)) if str(settings.nsupdate_tsig_key) is not None: keyring = dns.tsigkeyring.from_text({ str(settings.nsupdate_tsig_key[0]): str(settings.nsupdate_tsig_key[1]) }) else: keyring = None if str(settings.nsupdate_tsig_algorithm) is not None: keyring_algo = str(settings.nsupdate_tsig_algorithm) else: keyring_algo = "HMAC-MD5.SIG-ALG.REG.INT" # nslog( " algo %s, key %s : %s \n" % (keyring_algo,str(settings.nsupdate_tsig_key[0]), str(settings.nsupdate_tsig_key[1])) ) # get information about this system system = api.find_system(args[0]) # process all interfaces and perform dynamic update for those with --dns-name for (name, interface) in system.interfaces.iteritems(): host = interface["dns_name"] host_ip = interface["ip_address"] if not system.is_management_supported(cidr_ok=False): continue if not host: continue if host.find(".") == -1: continue domain = ".".join(host.split(".")[1:]) # get domain from host name host = host.split(".")[0] # strip domain nslog("processing interface %s : %s\n" % (name, interface)) nslog("lookup for '%s' domain master nameserver... " % domain) # get master nameserver ip address answers = dns.resolver.query(domain + '.', dns.rdatatype.SOA) soa_mname = answers[0].mname soa_mname_ip = None for rrset in answers.response.additional: if rrset.name == soa_mname: soa_mname_ip = str(rrset.items[0].address) nslog("%s [%s]\n" % (soa_mname, soa_mname_ip)) nslog("%s dns record for %s.%s [%s] .. " % (action, host, domain, host_ip)) # try to update zone with new record update = dns.update.Update(domain + '.', keyring=keyring, keyalgorithm=keyring_algo) if action == "replace": update.replace(host, 3600, dns.rdatatype.A, host_ip) update.replace(host, 3600, dns.rdatatype.TXT, '"cobbler (date: %s)"' % (time.strftime("%c"))) else: update.delete(host, dns.rdatatype.A, host_ip) update.delete(host, dns.rdatatype.TXT) try: response = dns.query.tcp(update, soa_mname_ip) rcode_txt = dns.rcode.to_text(response.rcode()) except dns.tsig.PeerBadKey: nslog("failed (refused key)\n>> done\n") logf.close() raise CX("nsupdate failed, server '%s' refusing our key" % soa_mname) nslog('response code: %s\n' % rcode_txt) # notice user about update failure if response.rcode() != dns.rcode.NOERROR: nslog('>> done\n') logf.close() raise CX("nsupdate failed (response: %s, name: %s.%s, ip %s, name server %s)" % (rcode_txt, host, domain, host_ip, soa_mname)) nslog('>> done\n') logf.close() return 0