-
Notifications
You must be signed in to change notification settings - Fork 1
/
public-dns-check.py
executable file
·73 lines (60 loc) · 1.87 KB
/
public-dns-check.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env python3
# Author: github.com/danielhoherd
# License: MIT
"""Check a hostname against a list of known public DNS resolvers and return a single-character result status.
See also: https://www.whatsmydns.net"""
import datetime
import dns.resolver
import typer
app = typer.Typer(pretty_exceptions_enable=False, help=__doc__)
local_timezone = datetime.datetime.now(datetime.UTC).astimezone().tzinfo
nameservers = [
"1.1.1.1",
"4.2.2.1",
"4.2.2.2",
"4.2.2.3",
"4.2.2.4",
"4.2.2.5",
"4.2.2.6",
"8.8.4.4",
"8.8.8.8",
"9.9.9.9",
"149.112.112.112",
"156.154.70.1",
"156.154.71.1",
"198.6.1.4",
"208.67.220.220",
"208.67.222.222",
]
def lookup_host_in_nameserver(host, nameserver):
resolver = dns.resolver.Resolver()
resolver.nameservers = [nameserver]
try:
resolver.resolve(host, lifetime=2.0)
return "•"
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
return "x"
except dns.resolver.LifetimeTimeout:
return "?"
@app.command()
def main(
hosts: list[str] = typer.Argument(..., help="Host to check"),
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose mode"),
):
now = datetime.datetime.now(local_timezone).strftime("%FT%T%z")
host_column_length = max(len(host) for host in hosts)
for host in hosts:
print(f"{now} {host:>{host_column_length}}", end=" ")
failures = []
for nameserver in nameservers:
res = lookup_host_in_nameserver(host, nameserver)
if res == "x":
failures.append(nameserver)
print(lookup_host_in_nameserver(host, nameserver), end="", flush=True)
if verbose:
for failure in failures:
print(f"\n {host} failed on {failure}", end="")
print()
if __name__ == "__main__":
main.__doc__ = __doc__
app()