Created
October 29, 2017 14:34
-
-
Save wfjsw/9f8682dda26522d22edcd7be2d89066e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const rp = require('request-promise-native') | |
// const dns = require('dns2') | |
const dns = require('native-dns') | |
const { | |
port, | |
proxy | |
} = require('./config.json') | |
let edns_subset, server, server_t | |
server = dns.createServer() | |
server_t = dns.createTCPServer() | |
async function getMyIP() { | |
let resp = await rp({ | |
url: 'http://ip.cn', | |
headers: { | |
'User-Agent': 'curl/7.52.1' | |
} | |
}) | |
return resp.match(/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/)[0] | |
} | |
function cutToC(ip) { | |
let ips = ip.split('.') | |
ips[3] = '0/24' | |
return ips.join('.') | |
} | |
async function resolve(name, type) { | |
let resp = await rp({ | |
url: 'https://dns.google.com/resolve', | |
proxy, | |
qs: { | |
name, | |
type, | |
edns_subset | |
}, | |
json: true | |
}) | |
return resp | |
} | |
function formatAnswer(ans) { | |
let answer = { | |
name: ans.name, | |
ttl: ans.TTL | |
} | |
switch (ans.type) { | |
case 1: | |
answer.address = ans.data | |
answer = dns.A(answer) | |
break | |
case 2: | |
answer.data = ans.data | |
answer = dns.NS(answer) | |
break | |
case 5: | |
answer.data = ans.data | |
answer = dns.CNAME(answer) | |
break | |
case 6: | |
[answer.primary, answer.admin, answer.port, answer.serial, answer.refresh, answer.retry, answer.expiration, answer.minimum] = ans.data.split(' ') | |
answer.serial = parseInt(answer.serial) | |
answer.refresh = parseInt(answer.refresh) | |
answer.retry = parseInt(answer.retry) | |
answer.expiration = parseInt(answer.expiration) | |
answer.minimum = parseInt(answer.minimum) | |
answer = dns.SOA(answer) | |
break | |
case 12: | |
answer.data = ans.data | |
answer = dns.PTR(answer) | |
break | |
case 15: | |
[answer.priority, answer.exchange] = ans.data.split(' ') | |
answer.priority = parseInt(answer.priority) | |
answer = dns.MX(answer) | |
break | |
case 16: | |
answer.data = [ans.data] | |
answer = dns.TXT(answer) | |
break | |
case 33: | |
[answer.priority, answer.weight, answer.port, answer.target] = ans.data.split(' ') | |
answer.priority = parseInt(answer.priority) | |
answer.weight = parseInt(answer.weight) | |
answer.port = parseInt(answer.port) | |
answer = dns.SRV(answer) | |
break | |
default: | |
answer = false | |
} | |
return answer | |
} | |
async function processDNSRequest(request, resp) { | |
try { | |
// let resp = new dns.Packet(request) | |
for (let question of request.question) { | |
console.log('> request %s', question.name); | |
try { | |
let res = await resolve(question.name, question.type) | |
if (res.Status == 0) { | |
resp.header.qr = 1 | |
resp.header.tc = res.TC ? 1 : 0 | |
resp.header.ra = res.RA ? 1 : 0 | |
resp.header.rd = res.RD ? 1 : 0 | |
resp.header.ad = res.AD ? 1 : 0 | |
if (res.Answer) { | |
for (let ans of res.Answer) { | |
let answer = formatAnswer(ans) | |
if (!answer) continue | |
resp.answer.push(answer) | |
} | |
} | |
if (res.Authority) { | |
for (let ans of res.Authority) { | |
let answer = formatAnswer(ans) | |
if (!answer) continue | |
resp.authority.push(answer) | |
} | |
} | |
if (res.Additional) { | |
for (let ans of res.Additional) { | |
let answer = formatAnswer(ans) | |
if (!answer) continue | |
resp.additional.push(answer) | |
} | |
} | |
} else { | |
resp.header.rcode = res.Status | |
resp.header.qr = 1 | |
resp.header.tc = res.TC ? 1 : 0 | |
resp.header.ra = res.RA ? 1 : 0 | |
resp.header.rd = res.RD ? 1 : 0 | |
resp.header.ad = res.AD ? 1 : 0 | |
} | |
} catch (e) { | |
console.error(e.stack) | |
resp.header.rcode = 2 | |
resp.header.qr = 1 | |
resp.header.tc = res.TC ? 1 : 0 | |
resp.header.ra = res.RA ? 1 : 0 | |
resp.header.rd = res.RD ? 1 : 0 | |
resp.header.ad = res.AD ? 1 : 0 | |
} | |
} | |
resp.send() | |
} catch (e) { | |
console.error(e.stack) | |
} | |
} | |
server.on('request', processDNSRequest) | |
server_t.on('request', processDNSRequest) | |
server.on('error', function (err, buff, req, res) { | |
console.log(err.stack) | |
}) | |
async function init() { | |
let ip = await getMyIP() | |
console.log('Your IP: ', ip) | |
edns_subset = cutToC(ip) | |
console.log('Your EDNS Subset: ', edns_subset) | |
server.serve(port) | |
server_t.serve(port) | |
console.log('Google Public DNS listen on', port) | |
} | |
init() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment