Skip to content

Commit

Permalink
Some fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCjw committed Aug 14, 2019
1 parent e9f0ef8 commit 5697be9
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 133 deletions.
24 changes: 24 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# https://editorconfig.org/

root = true

[*]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
charset = utf-8

# Docstrings and comments use max_line_length = 79
[*.py]
max_line_length = 119

# Use 2 spaces for the HTML files
[*.html]
indent_size = 2

# The JSON files contain newlines inconsistently
[*.json]
indent_size = 2
insert_final_newline = ignore
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,11 @@ $RECYCLE.BIN/
*.lnk

GeoLite2-Country.mmdb
public-resolvers.md
public-resolvers.md

# https://github.com/github/gitignore/blob/master/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
14 changes: 14 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.pythonPath": "/usr/bin/python3"
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

[![status](https://img.shields.io/travis/TheCjw/DoHVerifier.svg?style=flat-square)](https://travis-ci.org/TheCjw/DoHVerifier)

Find best DoH resolver and test is edns client subnet supported.
Find best DoH resolver and test if ECS(edns client subnet) supported.
261 changes: 130 additions & 131 deletions doh_verifier.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,131 +1,130 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import concurrent.futures
import base64
import io
from struct import unpack
import re

import requests
from requests import ConnectTimeout
from requests import ReadTimeout
from tabulate import tabulate
import maxminddb

from libs.log import logger

reader = maxminddb.open_database("GeoLite2-Country.mmdb")

def parse_resolvers(content):
result = re.findall(r"^##.+?(?P<resolver>.+$)(?P<description>(\n|.)+?)(?P<stamp>^sdns.+)",
content, re.M)
if result is None:
return None

resolvers = []
for r in result:
# Skip sdns://

stamp = r[3][7:]

# FIX Padding.
stamp += "=" * ((4 - len(stamp) % 4) % 4)
decoded_stamp = base64.urlsafe_b64decode(stamp)

stream = io.BytesIO(decoded_stamp)
# https://github.com/jedisct1/dnscrypt-proxy/wiki/stamps

flag = unpack("B", stream.read(1))[0]

# Parse DNS-over-HTTPS only.
if flag != 0x02:
continue

resolver = {}

resolver["name"] = r[0]
resolver["ip_address"] = ""

props = unpack("Q", stream.read(8))[0]

_len = unpack("B", stream.read(1))[0]
if _len != 0:
# can be empty.
ip_address = stream.read(_len)
resolver["ip_address"] = ip_address.decode()

# https://github.com/jedisct1/dnscrypt-proxy/blob/master/vendor/github.com/jedisct1/go-dnsstamps/dnsstamps.go#L159
while True:
vlen = unpack("B", stream.read(1))[0]
_len = vlen & (~0x80)
if _len > 0:
hashes = stream.read(_len)

if (vlen & 0x80) != 0x80:
break

_len = unpack("B", stream.read(1))[0]
host = None
if _len != 0:
host = stream.read(_len)

_len = unpack("B", stream.read(1))[0]
path = None
if _len != 0:
path = stream.read(_len)

resolver["url"] = f"https://{host.decode()}{path.decode()}"
resolvers.append(resolver)

return resolvers


def test_resolver(resolver):
logger.debug(f"Querying {resolver['name']}")
try:
params = {
"name": "dl.google.com"
}
r = requests.get(resolver["url"], params=params, timeout=2)
resolver["latency"] = r.elapsed.total_seconds() * 1000

for answer in r.json()["Answer"]:
if answer["type"] == 1:
ip = answer["data"]
country = reader.get(ip)
resolver["google"] = f"{ip}({country['country']['iso_code']})"
break
except (ConnectTimeout, ReadTimeout):
resolver["latency"] = "timeout"
return resolver


def main():
content = open("public-resolvers.md", encoding="utf-8").read()
resolvers = parse_resolvers(content)

ipv4_resolvers = []
for resolver in resolvers:
ip_address = resolver["ip_address"]
if len(ip_address):
# Ignore ipv6
if ip_address[0] == "[":
continue
ipv4_resolvers.append(resolver)

result = []
with concurrent.futures.ThreadPoolExecutor() as executor:
future_list = {executor.submit(test_resolver, resolver): resolver for resolver in ipv4_resolvers}
for future in concurrent.futures.as_completed(future_list):
try:
if future.result():
result.append(future.result())
except Exception as exc:
pass

print(tabulate(result, headers = "keys", tablefmt="github"))


if __name__ == "__main__":
main()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import concurrent.futures
import base64
import io
from struct import unpack
import re

import requests
from requests import ConnectTimeout
from requests import ReadTimeout
from tabulate import tabulate
import maxminddb

from libs.log import logger

reader = maxminddb.open_database("GeoLite2-Country.mmdb")

def parse_resolvers(content):
result = re.findall(r"^##.+?(?P<resolver>.+$)(?P<description>(\n|.)+?)(?P<stamp>^sdns.+)",
content, re.M)
if result is None:
return None

resolvers = []
for r in result:
# Skip sdns://
stamp = r[3][7:]

# FIX Padding.
stamp += "=" * ((4 - len(stamp) % 4) % 4)
decoded_stamp = base64.urlsafe_b64decode(stamp)

stream = io.BytesIO(decoded_stamp)
# https://github.com/jedisct1/dnscrypt-proxy/wiki/stamps

flag = unpack("B", stream.read(1))[0]

# Parse DNS-over-HTTPS only.
if flag != 0x02:
continue

resolver = {}

resolver["name"] = r[0]
resolver["ip_address"] = ""

props = unpack("Q", stream.read(8))[0]

_len = unpack("B", stream.read(1))[0]
if _len != 0:
# can be empty.
ip_address = stream.read(_len)
resolver["ip_address"] = ip_address.decode()

# https://github.com/jedisct1/dnscrypt-proxy/blob/master/vendor/github.com/jedisct1/go-dnsstamps/dnsstamps.go#L159
while True:
vlen = unpack("B", stream.read(1))[0]
_len = vlen & (~0x80)
if _len > 0:
hashes = stream.read(_len)

if (vlen & 0x80) != 0x80:
break

_len = unpack("B", stream.read(1))[0]
host = None
if _len != 0:
host = stream.read(_len)

_len = unpack("B", stream.read(1))[0]
path = None
if _len != 0:
path = stream.read(_len)

resolver["url"] = f"https://{host.decode()}{path.decode()}"
resolvers.append(resolver)

return resolvers


def test_resolver(resolver):
logger.debug(f"Querying {resolver['name']}")
try:
params = {
"name": "dl.google.com"
}
r = requests.get(resolver["url"], params=params, timeout=2)
resolver["latency(ms)"] = int(r.elapsed.total_seconds() * 1000)

for answer in r.json()["Answer"]:
if answer["type"] == 1:
ip = answer["data"]
country = reader.get(ip)
resolver["google"] = f"{ip}({country['country']['iso_code']})"
break
except (ConnectTimeout, ReadTimeout):
resolver["latency(ms)"] = "timeout"
return resolver


def main():
content = open("public-resolvers.md", encoding="utf-8").read()
resolvers = parse_resolvers(content)

ipv4_resolvers = []
for resolver in resolvers:
ip_address = resolver["ip_address"]
if len(ip_address):
# Ignore ipv6
if ip_address[0] == "[":
continue
ipv4_resolvers.append(resolver)

result = []
with concurrent.futures.ThreadPoolExecutor() as executor:
future_list = {executor.submit(test_resolver, resolver): resolver for resolver in ipv4_resolvers}
for future in concurrent.futures.as_completed(future_list):
try:
if future.result():
result.append(future.result())
except Exception as exc:
pass

print(tabulate(result, headers = "keys", tablefmt="github"))


if __name__ == "__main__":
main()

0 comments on commit 5697be9

Please sign in to comment.