1、自制DNS服务器,监听127.0.0.1:53
2、修改网络连接里面的首选DNS服务器为:127.0.0.1
3、服务器收到DNS请求后,从腾讯的httpDns接口查询,再返回给请求端,接口:http://119.29.29.29/d?dn=域名
https://gitee.com/fz6/mobile_h5_antihijacking
代码:
import hpsocket;
import hpsocket.udpServer;
import wsock;
namespace hpsocket
class dnsServer{
ctor(initFile, dnsApp ){
this = ..hpsocket.udpServer()
if(!this){
return null;
}
this.threadGlobal = {
_dnsApp = dnsApp;
_initFile = initFile;
response = {};
request = {};
}
this.onThreadCreated = function(){
import web.json;
import hpsocket.dnsServer;
import console;
log=function(...){
console.dump(...)
}
if(_initFile){
loadcodex(_initFile)
}
response.close = function(){
if(owner.resultStr and #owner.resultStr){
hpUdpServerEx.send(connId,owner.resultStr,#owner.resultStr)
}
owner.resultStr = "";
}
response.write = function(s,...){
if( s === null ) return;
var ts = type(s);
if( ts == 'table' ){
if(s[["_struct"]]) {
if( s@[["_tostring"]] ) s = tostring(s);
}
else s = web.json.stringify(s,owner.jsonPrettyPrint);
}
elseif( (ts != 'string') && (ts != 'buffer') ){
s = tostring(s);
};
owner.resultStr ++= s;
s = null;
ts=null
if(...===null) return;
return owner.write(...);
}
response.loadcode = function(path){
loadcodex( path );
}
global.print = function(...){
response.write(...);
};
}
this.onReceive = function(hpUdpServerEx,connId,pData,length){
global.hpUdpServerEx = hpUdpServerEx;
global.connId = connId
if(_dnsApp){
request.body = ..raw.tostring(pData,1,length)
request.domains = hpsocket.dnsServer.dealDNSbyte(request.body);
response.resultStr = "";
_dnsApp(request,response);
response.close();
}
}
};
}
namespace dnsServer{
class TDNSBitCode{
Word QR=0; //Query/Response Flag
Word OpCode=0; //
Word AA=0; //Authoritative Answer Flag
Word TC=0; //Truncation Flag
Word RD=0; //Recursion Desired
Word RA=0; //Recursion Available:
Word Z=0; //Zero
Word RCode=0; //Response Code
}
class TDNSHeader{
Word ID=0; //Identifier:
Word BitCode=0; //从中分析出TDNSBitCode
Word QDCount=0;
Word ANCount=0;
Word NSCount=0;
Word ARCount=0;
}
class dns_packet{
WORD Id=0;
WORD Flags=0;
WORD Questions=0;
WORD Answers=0;
WORD Authoritys=0;
WORD Additionals=0;
}
class DnsQuery{
Word TheType=0; //记录类型 A NS CNAME
Word TheClasses=0;
}
class DnsResponse{
Word TheName=0;
Word TheType=0;
Word TheClasses=0;
INT ttl=0;
Word length=0;
INT addr=0;
}
GetDNSBitCode = function( BitCode){
var result = TDNSBitCode();
result.QR = BitCode >> 15;
result.OpCode = ((BitCode & 0x7800) >> 11) & 0x000F;
result.AA = (BitCode & 0x0700) >> 10;
result.TC = (BitCode & 0x0200) >> 9;
result.RD = (BitCode & 0x0100) >> 8;
result.RA = (BitCode & 0x0800) >> 7;
result.Z = 0;
result.RCode = BitCode & 0x000F;
return result;
}
DNSStrToDomain = function(SrcStr, Idx){
var Result = '' ;
var fRPackSize = #SrcStr;
var SavedIdx = 0;
do{
var Len = SrcStr[Idx];
while( (Len & 0xC0)==0xC0 ){
if (SavedIdx == 0){
SavedIdx = Succ(Idx)
}
var aChar = Len & 0x3F;
Idx = twoCharToWord(aChar, SrcStr[Idx + 1]) + 1;
Len := SrcStr[Idx];
}
if (Idx >= fRPackSize){
return ;
}
var LabelStr='';
if (Len > 0){
LabelStr = ..string.sub(SrcStr,Idx+1,Idx+Len);
Idx += Len+1;
}
if (Idx+1 > fRPackSize){
return ;
}
Result ++= LabelStr ++ '.';
}while(!(SrcStr[Idx] == 0 or Idx > #SrcStr))
if (Result[#Result] == '.'#){
Result = ..string.left(Result,#Result-1)
}
if (SavedIdx > 0){
Idx = SavedIdx
}
Idx++;
return Result, Idx;
}
long2str=function(src,len=2){
if(type(src)==type.number){
var bytes
if(len==2){
bytes = ..raw.convert({WORD n=src},{BYTE s[2]={}});
}elseif(len==4) {
bytes = ..raw.convert({INT n=src},{BYTE s[4]={}});
}elseif(len==8) {
bytes = ..raw.convert({LONG n=src},{BYTE s[8]={}});
}
return ..string.pack(bytes.s)//..raw.malloc(#bytes.s,bytes);
}
}
BuilderDNSResponse = function(pDnsQuery, nQueryLen, SnoopIP){
if(pDnsQuery){
var dnsr = dns_packet();
var dnslen = ..raw.sizeof(dnsr);
var dnss = dns_packet();
var queryr = DnsQuery();
var str = ..string.left(pDnsQuery,dnslen);
..raw.convert(str,dnsr);
//标识字段
dnss.Id := dnsr.Id;
//标志字段,其中设置了QR = 1,RD = 1,RA = 1
dnss.Flags := ..wsock.htons(0x8180);
//问题数量
dnss.Questions := ..wsock.htons(1);
if(type(SnoopIP)==type.table){
//回答数量
dnss.Answers := ..wsock.htons(#SnoopIP);
}else {
//回答数量
dnss.Answers := ..wsock.htons(1);
}
dnss.Authoritys := 0;
dnss.Additionals := 0;
var querylen = ..raw.sizeof(queryr);
var ulen = nQueryLen - dnslen - querylen;
var start = dnslen+ ulen
start += 1;
var dname = ..string.sub(pDnsQuery, dnslen+1, dnslen+ulen)
str = ..string.sub(pDnsQuery, start, start+3)
..raw.convert(str,queryr);
start += 4;
var responses = DnsResponse();
var responselen = ..raw.sizeof(responses)
var usBufferLen
if(type(SnoopIP)==type.table){
usBufferLen = start + responselen*#SnoopIP;
}else {
usBufferLen = start + responselen;
}
var result = ..raw.malloc(usBufferLen,dnss);
var len = dnslen;
len = ..raw.concat(result,dname,len,#dname);
var queryr1 = ..raw.malloc(queryr);
len = ..raw.concat(result,queryr1,len,#queryr1);
if(type(SnoopIP)==type.table){
for(i=1;#SnoopIP;1){
//域名指针
str = long2str(..wsock.htons(0xC00C));
len =..raw.concat(result,str,len,#str);
//0005 CNAME
str = long2str(queryr.TheType);
len =..raw.concat(result,str,len,#str);
//0001 类,表示为Internet数据
str = long2str(queryr.TheClasses);
len =..raw.concat(result,str,len,#str);
//TTL 生存时间
str = long2str(0x0000000A,4);
len =..raw.concat(result,str,len,#str);
//数据长度 127 0 0 1
str = long2str(..wsock.htons(4));
len =..raw.concat(result,str,len,#str);
//内容 127 0 0 1
str = long2str(..wsock.inet_addr(SnoopIP[ i ]),4);
len =..raw.concat(result,str,len,#str);
}
}else {
//域名指针
str = long2str(..wsock.htons(0xC00C));
len = ..raw.concat(result,str,len,#str);
//0005 CNAME
str = long2str(queryr.TheType);
len = ..raw.concat(result,str,len,#str);
//0001 类,表示为Internet数据
str = long2str(queryr.TheClasses);
len = ..raw.concat(result,str,len,#str);
//TTL 生存时间
str = long2str(0xFFFFFFFF,4);
len = ..raw.concat(result,str,len,#str);
//数据长度 127 0 0 1
str = long2str(..wsock.htons(4));
len = ..raw.concat(result,str,len,#str);
//内容 127 0 0 1
str = long2str(..wsock.inet_addr(SnoopIP),4);
len = ..raw.concat(result,str,len,#str);
}
return ..raw.tostring(result,0,len);
}
}
twoCharToWord = function(b1,b2){
return ((b1 << 8) & 0xFF00) | (b2 & 0x00FF)
}
dealDNSbyte = function(strRecvData){
var id = twoCharToWord(strRecvData[1], strRecvData[2]);
var Code = twoCharToWord(strRecvData[3], strRecvData[4]);
var BitCode = GetDNSBitCode(Code);
if( BitCode.QR != 0){return}; //0表示查询,1表示反馈
var QDCount = twoCharToWord(strRecvData[5], strRecvData[6]);
if (QDCount <= 0) {return }
var APos = 13; // DNS头恒为12字节
var DomainName
var domains = {}
for(i=1;QDCount;1){
DomainName,APos = DNSStrToDomain(strRecvData, APos);
if (!DomainName){return };
var QueryType = twoCharToWord(strRecvData[APos], strRecvData[APos + 1]);
APos += 2;
var QueryClass = twoCharToWord(strRecvData[APos], strRecvData[APos + 1]);
APos += 2;
..table.push(domains,DomainName);
}
return domains;
}
}