2010-11-01 27 views
9

Là một phần của công cụ tôi đang viết Tôi muốn có một chẩn đoán sẽ cho người dùng biết liệu họ đã định cấu hình DNS của miền của họ một cách chính xác cho một dịch vụ cụ thể hay chưa. Tôi muốn truy vấn máy chủ DNS có thẩm quyền cho miền của họ để tôi có thể bỏ qua bất kỳ kết quả được lưu trong bộ nhớ cache nào.Làm cách nào để tìm máy chủ DNS có thẩm quyền cho miền bằng dnspython?

Trả lời

14

Đây là nỗ lực của tôi về điều này. Nó sử dụng máy chủ DNS tiêu chuẩn của hệ thống để tìm kiếm máy chủ gốc cho miền cấp cao nhất và để giải quyết tên của các máy chủ DNS khác nhau dọc theo chuỗi mà tôi nghĩ là phù hợp vì những tên đó có lẽ sẽ thay đổi rất thường xuyên.

import dns 
import dns.name 
import dns.query 
import dns.resolver 

def get_authoritative_nameserver(domain, log=lambda msg: None): 
    n = dns.name.from_text(domain) 

    depth = 2 
    default = dns.resolver.get_default_resolver() 
    nameserver = default.nameservers[0] 

    last = False 
    while not last: 
     s = n.split(depth) 

     last = s[0].to_unicode() == u'@' 
     sub = s[1] 

     log('Looking up %s on %s' % (sub, nameserver)) 
     query = dns.message.make_query(sub, dns.rdatatype.NS) 
     response = dns.query.udp(query, nameserver) 

     rcode = response.rcode() 
     if rcode != dns.rcode.NOERROR: 
      if rcode == dns.rcode.NXDOMAIN: 
       raise Exception('%s does not exist.' % sub) 
      else: 
       raise Exception('Error %s' % dns.rcode.to_text(rcode)) 

     rrset = None 
     if len(response.authority) > 0: 
      rrset = response.authority[0] 
     else: 
      rrset = response.answer[0] 

     rr = rrset[0] 
     if rr.rdtype == dns.rdatatype.SOA: 
      log('Same server is authoritative for %s' % sub) 
     else: 
      authority = rr.target 
      log('%s is authoritative for %s' % (authority, sub)) 
      nameserver = default.query(authority).rrset[0].to_text() 

     depth += 1 

    return nameserver 


import sys 

def log(msg): 
    print msg 

print get_authoritative_nameserver(sys.argv[1], log) 

Dưới đây là một số lượng mẫu:

Looking up com. on 192.168.255.10 
l.gtld-servers.net. is authoritative for com. 
Looking up stackoverflow.com. on 192.41.162.30 
ns1.p19.dynect.net. is authoritative for stackoverflow.com. 
Looking up meta.stackoverflow.com. on 208.78.70.19 
Same server is authoritative for meta.stackoverflow.com. 
208.78.70.19 
5

Tôi đã xem qua câu trả lời Jon Colverson, và nó giúp tôi hiểu module dnspython và làm thế nào để xử lý các kết quả (tôi đoán tất cả các module DNS có cùng uốn lượn mê cung của cấu trúc lớp học ...) Tôi cần TTL và các bản ghi keo, vì vậy tôi đã tạo ra sự thích nghi của riêng mình. Tôi đăng nó ở đây trong trường hợp ai đó sẽ thấy nó hữu ích; Tôi không có ý định cạnh tranh với câu trả lời tuyệt vời của Jon Colverson, chỉ cần điền vào một số khoảng trống bổ sung. Cải tiến cơ bản là việc sử dụng thông tin máy chủ tên từ phần bổ sung của câu trả lời, nếu có. Tôi cho rằng một máy chủ có thể đặt một cái gì đó khác hơn so với hồ sơ keo trong phần bổ sung, vì vậy có lẽ điều này vẫn nên được tăng cường để tương quan đúng thông tin từ phần bổ sung với thông tin trong phần câu trả lời. Tôi cũng lấy và in tất cả các máy chủ định danh, không chỉ là máy chủ đầu tiên.

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import dns.query 
import dns.resolver 
from dns.exception import DNSException 

def query_authoritative_ns (domain, log=lambda msg: None): 

    default = dns.resolver.get_default_resolver() 
    ns = default.nameservers[0] 

    n = domain.split('.') 

    for i in xrange(len(n), 0, -1): 
     sub = '.'.join(n[i-1:]) 

     log('Looking up %s on %s' % (sub, ns)) 
     query = dns.message.make_query(sub, dns.rdatatype.NS) 
     response = dns.query.udp(query, ns) 

     rcode = response.rcode() 
     if rcode != dns.rcode.NOERROR: 
      if rcode == dns.rcode.NXDOMAIN: 
       raise Exception('%s does not exist.' % (sub)) 
      else: 
       raise Exception('Error %s' % (dns.rcode.to_text(rcode))) 

     if len(response.authority) > 0: 
      rrsets = response.authority 
     elif len(response.additional) > 0: 
      rrsets = [response.additional] 
     else: 
      rrsets = response.answer 

     # Handle all RRsets, not just the first one 
     for rrset in rrsets: 
      for rr in rrset: 
       if rr.rdtype == dns.rdatatype.SOA: 
        log('Same server is authoritative for %s' % (sub)) 
       elif rr.rdtype == dns.rdatatype.A: 
        ns = rr.items[0].address 
        log('Glue record for %s: %s' % (rr.name, ns)) 
       elif rr.rdtype == dns.rdatatype.NS: 
        authority = rr.target 
        ns = default.query(authority).rrset[0].to_text() 
        log('%s [%s] is authoritative for %s; ttl %i' % 
         (authority, ns, sub, rrset.ttl)) 
        result = rrset 
       else: 
        # IPv6 glue records etc 
        #log('Ignoring %s' % (rr)) 
        pass 

    return result 

import sys 

def log (msg): 
    sys.stderr.write(msg + u'\n') 

for s in sys.argv[1:]: 
    print query_authoritative_ns (s, log) 
2

Các ví dụ khác là tốt nhưng quá phức tạp nếu bạn chỉ cần máy chủ định danh. Ví dụ từ http://c0deman.wordpress.com/2014/06/17/find-nameservers-of-domain-name-python/:

import dns.resolver 

domain = 'google.com' 
answers = dns.resolver.query(domain,'NS') 
for server in answers: 
    print server 
+1

Tôi có thể đúng trong suy nghĩ rằng có thể trả lại kết quả lưu trữ, mặc dù? Trong trường hợp của tôi, tôi đặc biệt muốn tìm máy chủ hiện tại tránh bất kỳ bộ nhớ đệm nào, nhưng có thể có cách làm đơn giản hơn đáng kể so với cách tôi đã làm. :) –

+2

Điều đó sẽ chỉ cung cấp cho bạn máy chủ định danh cho tên miền cấp cao nhất (hoặc các tên miền phụ nếu chúng có bản ghi NS). Nó sẽ không cho bạn biết máy chủ DNS có thẩm quyền là gì cho 'www.example.org' và sẽ đưa ra một ngoại lệ' dns.resolver.NoAnswer'. – pwaring

0

Im khá chắc chắn điều này sẽ làm điều đó.

import dns.resolver 

domain = 'co.uk' 

response = dns.resolver.query(domain, 'SOA') 
if response.rrset is not None: 
    print response.rrset 

Bạn có thể dọn dẹp tất nhiên phản ứng

import dns.resolver 
import re 

domain = 'co.uk' 

response = dns.resolver.query(domain, 'SOA') 

if response.rrset is not None: 
    pattern= r'(%s)\.\s(\d{1,})\s(\w+)\sSOA\s(.*?)\.\s(.*?)\.\s(\d{1,})\s(\d{1,})\s(\d{1,})\s(\d{1,})\s(\d{1,})' % domain 
    match = re.match(pattern, str(response.rrset)) 
    m_name, ttl, class_, ns, email, serial, refresh, retry, expiry, minim = match.groups() 

output =''' 
Main Name In Zone: {a}, 
Cache TTL: {b}, 
Class: {c}, 
Authoritive NS: {d}, 
Email Address: {e}, 
Last Change: {f}, 
Retry In Secs: {g}, 
Expiry: {h}, 
Slave Cache In Sec: {i} 
'''.format(a = m_name, b = ttl, c = class_, d = ns, e = str(email).replace('\\', ''), f = serial, g = retry, h = expiry, i = minim) 

print output 

này tạo

Main Name In Zone: co.uk, 
Cache TTL: 600, 
Class: IN, 
Authoritive NS: dns1.nic.uk, 
Email Address: hostmaster.nominet.org.uk, 
Last Change: 1305857394, 
Retry In Secs: 300, 
Expiry: 2419200, 
Slave Cache In Sec: 10800 
+1

Đúng nếu tôi sai, nhưng tôi tin rằng những kết quả SOA này vẫn có thể được lưu trữ trên trình phân giải, mặc dù? Nó đã bỏ qua bộ nhớ đệm khiến mọi thứ trở nên phức tạp hơn. –

Các vấn đề liên quan