Node.JS编写的DNS分发器

 

const dgram = require('dgram');
//获取本地时间字符串
function getDateStr() {
return (new Date()).toLocaleString();
}
function checkDomainOne(sReq, sDomain) {
const aReq = sReq.split('.');
const aDomain = sDomain.split('.');
const iLen = aDomain.length;
for (var i = 0; i < iLen; i++) {
const sReq = aReq.pop();
if (sReq === undefined) {
return false;
}
const sDom = aDomain.pop();
if (sDom !== sReq) {
return false;
}
}
return true;
}
function checkDomainByList(sReq, sList) {
const aList = sList.split(',');
for (var i = 0; i < aList.length; i++) {
const sDomain = aList[i];
if (checkDomainOne(sReq, sDomain)) {
return true;
}
}
return false;
}
function getDnsAddrByHost(conf, sReqHost) {
if (checkDomainByList(sReqHost, conf.domain_gfw)) {
return '192.168.30.1';
}
return '192.168.5.1';
}
function parseHost(_msg) {
const sMsg = _msg.subarray(12);
const aHost = [];
var num = sMsg.readUInt8(0);
var offset = 1;
while (num !== 0) {
aHost.push(sMsg.subarray(offset, offset + num).toString());
offset += num;
num = sMsg.readUInt8(offset);
offset += 1;
}
return aHost.join('.');
}
// 创建DNS代理
function proxyDNS(conf) {
const serverUDP = dgram.createSocket('udp4');
serverUDP.on('error', (err) => {
console.error(`[${getDateStr()}] [ERROR] - ${err}`);
});
serverUDP.on('message', (msg, rinfo) => {
const sReqHost = parseHost(msg);
const dnsAddr = getDnsAddrByHost(conf, sReqHost);
console.info(`[${getDateStr()}] ${rinfo.address} ${sReqHost} => ${dnsAddr}`);
const client = dgram.createSocket('udp4');
client.on('error', (err) => {
console.error(`[${getDateStr()}] [ERROR] - ${err}`);
client.close();
});
client.on('message', (fbMsg, fbRinfo) => {
serverUDP.send(fbMsg, rinfo.port, rinfo.address, (err) => {
if (err) console.error(`[${getDateStr()}] [ERROR] - ${err}`);
});
client.close();
});
client.send(msg, 53, dnsAddr, (err) => {
if (err) {
console.error(`[${getDateStr()}] [ERROR] - ${err}`);
client.close();
}
});
});
serverUDP.bind(conf.bind[1], conf.bind[0], () => {
console.info(`[${getDateStr()}] [INFO] - UDP Server start ${conf.bind[0]}:${conf.bind[1]}`);
});
return serverUDP;
}
const conf = {};
conf.bind = ["0.0.0.0", 53];
conf.domain_gfw = 'app.cloudcone.com,facebook.com,fbcdn.net,githubusercontent.com,gstatic.com,gmail.com,google.com,google.com.hk,googleapis.com,googleusercontent.com,googlevideo.com,instagram.com,line.me,line-apps.com,line-scdn.net,messenger.com,naver.jp,tdesktop.com,telegram.org,v2fly.org,youtube.com,ytimg.com';
proxyDNS(conf);

 

根据域名转发DNS到不同的服务器