移动端h5页面会被植入广告问题解决

关注小编微信公众号公众号【前端基础教程从0开始】回复“1”,拉你进程序员技术讨论群,群内有大神,可以免费提供问题解答。公众号回复“小程序”,领取300个优秀的小程序开源代码+一套入门教程。公众号回复“领取资源”,领取300G前端,Java,产品经理,微信小程序,Python等资源合集大放送,让我们一起学前端。

https可以防止http劫持,但是无法防止dns劫持,因为dns劫持发生在你和web 服务器建立连接之前。

打个比方,你要#去超市买东西,dns是出租车,把你送到超市门口(web服务器),https能防止超市给你的商品里加了假货,但是你一开始就上了黑车(dns劫持)!后面的就不可能会发生了!

防止dns劫持,很难,尤其对于小运营商的用户,被劫持的概率非常大。如果你认为用户只要使用8.8.8.8或者119.29.29.29等公共dns就可以避免劫持,那说明你还没发现运营商有多险恶,他们甚至在网关处伪造dns应答,抢答了目标递归dns给你的应答。看你的提问,是站在网站服务提供者的角度来问的,那就更难了,还是上面那个例子,你作为一个超市,想要防止客人被黑车拐跑,你觉得可能吗?我提供三种思路:

第一个(我没试过),发现网站在某些地区运营商被劫持了,投诉工信部,让他们放开劫持。

第二个,选用cdn服务。大部分小运营商dns劫持,是由于你的网站流量大,而源站又在网外,他们为了避免产生高额的网间结算费用,将被网内的dns请求劫持到网内他们自己的缓存服务器集群里。如果你用了cdn,被劫持的概率会略有下降,因为cdn厂商大多节点很多,以我司为例,国内几乎无孔不入,既然都在网内,他们就不会盯上你。即使被劫持,cdn厂商凭借和小运营商良好的沟通渠道(至少我司是这样,经常一个电话或者社交软件上和对方负责人说一句就会放开了),也很容易放开劫持。

第三个,选用httpdns,利用腾讯httpDns应对dns劫持来举例:

主要有三个步骤

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; 
        
    }
}

你可能感兴趣的:(移动端h5页面会被植入广告问题解决)