support iniziale DNS over Https
This commit is contained in:
77
lib/doh.py
Normal file
77
lib/doh.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# https://github.com/stamparm/python-doh
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
import re
|
||||
import socket
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
PY3 = sys.version_info >= (3, 0)
|
||||
|
||||
if hasattr(ssl, "_create_unverified_context"):
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
DOH_SERVER = "1.1.1.1" # Note: to prevent potential blocking of service based on DNS name
|
||||
else:
|
||||
DOH_SERVER = "cloudflare-dns.com" # Alternative servers: doh.securedns.eu, doh-de.blahdns.com, doh-jp.blahdns.com
|
||||
|
||||
if PY3:
|
||||
import urllib.request
|
||||
_urlopen = urllib.request.urlopen
|
||||
_Request = urllib.request.Request
|
||||
else:
|
||||
import urllib2
|
||||
_urlopen = urllib2.urlopen
|
||||
_Request = urllib2.Request
|
||||
|
||||
def query(name, type='A', server=DOH_SERVER, path="/dns-query", fallback=True, verbose=False):
|
||||
"""
|
||||
Returns domain name query results retrieved by using DNS over HTTPS protocol
|
||||
# Reference: https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/
|
||||
>>> query("one.one.one.one", fallback=False)
|
||||
['1.0.0.1', '1.1.1.1']
|
||||
>>> query("one", "NS")
|
||||
['a.nic.one.', 'b.nic.one.', 'c.nic.one.', 'd.nic.one.']
|
||||
"""
|
||||
|
||||
retval = None
|
||||
|
||||
try:
|
||||
req = _Request("https://%s%s?name=%s&type=%s" % (server, path, name, type), headers={"Accept": "application/dns-json"})
|
||||
content = _urlopen(req).read().decode()
|
||||
reply = json.loads(content)
|
||||
|
||||
if "Answer" in reply:
|
||||
answer = json.loads(content)["Answer"]
|
||||
retval = [_["data"] for _ in answer]
|
||||
else:
|
||||
retval = []
|
||||
except Exception as ex:
|
||||
if verbose:
|
||||
print("Exception occurred: '%s'" % ex)
|
||||
|
||||
if retval is None and fallback:
|
||||
if type == 'A':
|
||||
try:
|
||||
retval = socket.gethostbyname_ex(name)[2]
|
||||
except (socket.error, IndexError):
|
||||
pass
|
||||
|
||||
if retval is None:
|
||||
process = subprocess.Popen(("nslookup", "-q=%s" % type, name), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
content = (process.communicate()[0] or "").decode().replace("\r", "")
|
||||
|
||||
if "\n\n" in content and "can't" not in content.lower():
|
||||
answer = content.split("\n\n", 1)[-1]
|
||||
retval = re.findall(r"(?m)^%s.+= ([^=,\n]+)$" % re.escape(name), answer) or re.findall(r"Address: (.+)", answer)
|
||||
|
||||
if not retval:
|
||||
match = re.search(r"Addresses: ([\s\d.]+)", answer)
|
||||
if match:
|
||||
retval = re.split(r"\s+", match.group(1).strip())
|
||||
|
||||
if not PY3 and retval:
|
||||
retval = [_.encode() for _ in retval]
|
||||
|
||||
return retval
|
||||
Reference in New Issue
Block a user