From 0fd49bc023ed247a0a7424f50f141672f717cfad Mon Sep 17 00:00:00 2001 From: jedi Date: Mon, 8 Apr 2024 20:54:29 +0200 Subject: [PATCH] add javascript dns resolver using DoH --- frontend/src/dns.js | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 frontend/src/dns.js diff --git a/frontend/src/dns.js b/frontend/src/dns.js new file mode 100644 index 0000000..f07ea22 --- /dev/null +++ b/frontend/src/dns.js @@ -0,0 +1,50 @@ +import {query} from 'dns-query'; + +function get_prefered_server() { + try { + const servers = JSON.parse(localStorage.getItem('dns-servers')); + if (servers && servers.length > 0) { + return servers; + } + } catch (e) { + console.error(e); + } + const request = new XMLHttpRequest(); + request.open('GET', '/local/dns', false); + request.send(null); + if (request.status === 200) { + const servers = JSON.parse(request.responseText); + if (servers && servers.length > 0) { + return servers; + } + } + return ['1.1.1.1', '8.8.8.8']; +} + +class FallBackResolver { + constructor() { + this._servers = get_prefered_server(); + this._cache = JSON.parse(localStorage.getItem('dns-cache')) || {}; + } + + async query(domain, type) { + const key = domain + ':' + type; + if (key in this._cache && this._cache[key].time > Date.now() - 1000 * 60 * 60) { + const age_seconds = Math.ceil(Date.now() / 1000 - this._cache[key].time / 1000); + return [this._cache[key].data]; + } + const result = await query( + {question: {type: type, name: domain}}, + { + endpoints: this._servers, + } + ) + if (result.answers.length === 0) throw new Error('No answer'); + const first = result.answers[0]; + this._cache[key] = {time: Date.now(), ...first}; // TODO hadle multiple answers + localStorage.setItem('dns-cache', JSON.stringify(this._cache)); + return [first.data]; + } +} + +export default FallBackResolver; \ No newline at end of file