NiceLeeのBlog 用爱发电 bilibili~

备忘录 通过WebRTC获取客户端真实IP

2024-08-11
nIceLee

阅读:


WebRTC是什么不说了。
它有个漏洞或者说特性,使得浏览器通过javascript可以获取到客户端的真实IP地址。
不论浏览器开了代理与否。

如何禁用WebRTC

如何获取公共的STUN Server

如何检查STUN Server是否有效

WebRTC samples - Trickle ICE

相关代码

代码参考了diafygi/webrtc-ips
复制代码,浏览器F12可执行。

function getIPs(callback){
    let ip_dups = {};
    let ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
    
    let callbackOnce = function(ip_addr){
        if(ip_dups[ip_addr] === undefined)
            callback(ip_addr);

        ip_dups[ip_addr] = true;
    };
    //compatibility for firefox and chrome
    let RTCPeerConnection = window.RTCPeerConnection
        || window.mozRTCPeerConnection
        || window.webkitRTCPeerConnection;
    let useWebKit = !!window.webkitRTCPeerConnection;

    //bypass naive webrtc blocking using an iframe
    if(!RTCPeerConnection){
        //NOTE: you need to have an iframe in the page right above the script tag
        //
        //<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
        //<script>...getIPs called in here...
        //
        let win = iframe.contentWindow;
        RTCPeerConnection = win.RTCPeerConnection
            || win.mozRTCPeerConnection
            || win.webkitRTCPeerConnection;
        useWebKit = !!win.webkitRTCPeerConnection;
    }

    //minimal requirements for data connection
    let mediaConstraints = {
        optional: [{RtpDataChannels: true}]
    };
    
    // turn server list  https://gist.github.com/sagivo/3a4b2f2c7ac6e1b5267c2f1f59ac6c6b
    // to check if the server works - https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice
    // let servers = {iceServers: [{urls: "stun:stun.l.google.com:19302"}]};
    let servers = {iceServers: [
        {urls: "stun:stun.l.google.com:19302"},
    //   {urls: "stun:stun2.1.google.com:19302"},
    //    {urls: "stun:stun3.1.google.com:19302"},
    //    {urls: "stun:stun4.1.google.com:19302"},
    //    {urls: "stun:stun.sip.us:3478"},
    //    {urls: "stun:stun:stun.dus.net:3478"},
    //    {urls: "stun:stun:stun.easyvoip.com:3478"},
    //    {urls: "stun:stun:stun.easybell.de:3478"},
    //    {urls: "stun:stun.freecall.com:3478"},
    //    {urls: "stun:stun.freeswitch.org:3478"},
        {urls: "stun:stun.nfon.net:3478"},
    ]};
    
    
    //construct a new RTCPeerConnection
    let pc = new RTCPeerConnection(servers, mediaConstraints);

    function handleCandidate(candidate){
        //match just the IP address
        const m = candidate.match(ip_regex);
        m && callbackOnce(m[0]);
    }

    //listen for candidate events
    pc.onicecandidate = function(ice){

        //skip non-candidate events
        if(ice.candidate)
            handleCandidate(ice.candidate.candidate);
    };

    //create a bogus data channel
    pc.createDataChannel("");

    //create an offer sdp
    pc.createOffer(function(result){
        result.sdp.split("\n").forEach(function(t) {
            const m = t.match(ip_regex);
            m && callbackOnce(m[0]);
        });
        //trigger the stun server request
        pc.setLocalDescription(result, function(){}, function(){});

    }, function(){});

    //wait for a while to let everything done
    setTimeout(function(){
        //read candidate info from local description
        let lines = pc.localDescription.sdp.split('\n');

        lines.forEach(function(line){
            if(line.indexOf('a=candidate:') === 0)
                handleCandidate(line);
        });
    }, 1000);
}

//Test: Print the IP addresses into the console
getIPs(function(ip){console.log(ip);});

相似文章

内容
隐藏