openwrt-dns/dnscrypt_to_smartdns.py

84 lines
2 KiB
Python

import logging
import subprocess
from urllib.request import urlopen
from dnscrypt import parse, DNSoverHTTPS
SMARTDNS_GFW_CONF_FILE = '/etc/smartdns/conf.d/gfw.conf'
# https://github.com/DNSCrypt/dnscrypt-resolvers
PUBLIC_RESOLVER_URL_LIST = [
"https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md",
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md"
"https://dnsr.evilvibes.com/v3/public-resolvers.md"
]
def get_public_resolver_md() -> str:
for url in PUBLIC_RESOLVER_URL_LIST:
try:
logging.info('request {url}'.format(url=url))
with urlopen(url, timeout=15) as responsee:
return responsee.read().decode('utf-8')
except:
pass
raise IOError("can't download public-resolvers.md")
def get_stamps():
resolver_md: str = get_public_resolver_md()
lines = resolver_md.splitlines()
stamps = list(
map(
parse,
filter(lambda x: x.startswith('sdns://'), lines)
)
)
return stamps
def get_not_china_doh_list():
stamps = get_stamps()
def is_match(s) -> bool:
if isinstance(s, DNSoverHTTPS) is False:
return False
if s.nofilter is False:
return False
if s.dnssec is False:
return False
return True
return list(filter(
is_match,
stamps
))
def get_smartdns_config():
stamps = get_not_china_doh_list()
lines = set(map(
lambda x: 'server-https https://' + x.hostname + x.path + ' -group GFW -exclude-default-group',
stamps
))
return '\n'.join(lines)
def write_smartdns_config():
conf_txt = get_smartdns_config()
with open(SMARTDNS_GFW_CONF_FILE, 'w') as f:
f.write(conf_txt)
def reload_smartdns():
subprocess.run(["/etc/init.d/smartdns", "reload"])
def main():
write_smartdns_config()
reload_smartdns()
if __name__ == '__main__':
main()