美文网首页
标识访问者电脑与账户的关系,获取ip,mac或者设备指纹对比

标识访问者电脑与账户的关系,获取ip,mac或者设备指纹对比

作者: 云鹤道人张业斌 | 来源:发表于2023-11-07 16:33 被阅读0次

    想过用js获取信息标识用户机器吗?获取本地ip?mac地址?

    通过一番探索结论如下:

    一、 mac地址不用想了。
    二、 获取ip

    我们知道nginx的配置X-Forwarded-For 后端可以拿到ip,这个ip是出口ip,标识不了访问者机器

    location /api {
            proxy_set_header        Host    $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_connect_timeout   300;client_max_body_size 30m;
            rewrite ^/wisbayar_api(.*)$ $1 break;
            proxy_pass http://xx.xx.xx.xx:11001/;
    }
    
    三、利用webrtc网页即时通信 功能 实现点对点通信,获取ip,我们看代码如下。
        function findIP(onNewIP) {
                    var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
                    var pc = new myPeerConnection({iceServers: [{urls: "stun:stun.l.google.com:19302"}]}),
                    noop = function() {},
                    localIPs = {},
                    ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
                    key;
    
                    function ipIterate(ip) {
                        if (!localIPs[ip]) onNewIP(ip);
                        localIPs[ip] = true;
                    }
                      
                    pc.createDataChannel("");
                     
                    pc.createOffer(function(sdp) {
                        sdp.sdp.split('\n').forEach(function(line) {
                            if (line.indexOf('candidate') < 0) return;
                            line.match(ipRegex).forEach(ipIterate);
                        });
                        pc.setLocalDescription(sdp, noop, noop);
                    }, noop);
                      
                    pc.onicecandidate = function(ice) {
                             console.log('ice.candidate', ice.candidate)
                        if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
                        ice.candidate.candidate.match(ipRegex).forEach(ipIterate);
                    };
                }
    
                function addIP(ip) {
                    console.log('got ip: ', ip);
                }
                findIP(addIP)
    

    上面的代码提到的概念有点多,我们通过代码逐步看一下点对点通信概念:

    new myPeerConnection({iceServers: [{urls: "stun:stun.l.google.com:19302"}]}),
    
    1. 先看这里iceServers 是什么?
      ICE(Interactive Connectivity Establishment):是一个框架,允许您的 Web 浏览器 (一个Peer A)与对等方(另一个Peer B)连接,它需要绕过阻止打开连接的防火墙,内网限制。如果您的路由器不允许您直接与对等方连接,则通过服务器中继数据。 而ICE 使用STUN/TURN的一些技术来实现此目的
      实现点对点通信,实例名取RTCPeerConnection,就好理解了。

    2. 代码里的stun.l.google.com:19302 是什么?
      这是google的STUN服务器。这里还有很多公益的免费的可以查看:其他公共STUN 或 TURN 服务器
      当然如果你要做自己的视频功能,你也可以替换为自己的服务。

    如果我们这里不写这个STUN服务器,在pc.onicecandidate中打印ice.candidate. address可以看到 是一个以.local结尾的字符串而不是自己想要的IP。

    长这个样子.png
    1. STUN服务器干了什么呢?
      STUN(Session Traversal Utilities for NAT )是一种协议。客户端将向 Internet 上的 STUN 服务器发送请求,该服务器将回复客户端的公共IP以及客户端是否可以在 NAT 后面访问
    点对点通信.png
    1. NAT 是什么?
      NAT(Network Address Translation):为设备提供公共 IP 地址,俗称路由器。 给局域网内部分配内网地址,对外就使用它的公共 IP 地址。
      但是,某些路由器对谁可以连接到网络上的设备有限制,即使我们有 STUN 服务器找到的公共 IP 地址,也不是任何人都可以创建连接。在这种情况下,我们需要转向 TURN

    2. 再看TURN 是什么?

    TURN(Traversal Using Relays around NAT):围绕 NAT 使用中继遍历,实际上就是NAT路由器限制了不能直连,就使用TURN 服务器来中转转发,是一种降级方式。

    结合上面的图,现在我们就明白了,为了实现无延迟,实时通信,就要通过绕过NAT的限制,达到直连机器的目的。如果不能直连,就使用TURN中转。
    STUN服务器是用来取外网地址的。
    TURN服务器是在P2P(点对点)失败时进行转发的

    1. 代码里pc.createDataChannel, pc.createOffer是什么意思?

    pc.createDataChannel 是创建了一个数据通道,这是在建立连接之前交换信息的通信渠道。需要需要交换的信息是一端发送Offer(pc.createOffer)和远端响应Answer (remote.createAnswer)。交换的信息就是sdp

    1. sdp 是什么?

    SDP (Session Description Protocol) 用于描述多媒体会话,以便进行会话通知、会话邀请和其他形式的多媒体会话启动。在启动多媒体电话会议、IP 语音呼叫、流式视频或其他会话时,需要向参与者传达媒体详细信息、传输地址和其他会话描述元数据。

    sdp信息.png
    1. 交换sdp信息后,两边还必须交换有关网络连接的信息,pc.onicecandidate 就是干这个的

    ICE candidate 直接翻译:ice 候选人。这个pc.onicecandidate方法就说明了两边通信是直连还是说要通过 TURN服务器中继。这个方法里就能得到公共IP

    通信过程图.png

    到这里,我们就了解了获取IP代码的意思。拿到了公共IP,至于内网IP,浏览器做了限制,放开限制才能拿到, 以下是不同浏览器放开限制的方法

    火狐(FireFox) 删除隐藏IP

    浏览器输入 about:config

    搜索配置 media.peerconnection.enabled 改为false ( 刷新程序,IP正常显示 )

    谷歌(Chrome) 删除隐藏IP

    浏览器输入:chrome://flags/#enable-webrtc-hide-local-ips-with-mdns

    把 Anonymize local IPs exposed by WebRTC 设置为 disabled ( 刷新程序,IP正常显示 )

    edge浏览器删除隐藏ip

    浏览器输入: edge://flags/#enable-webrtc-hide-local-ips-with-mdns

    把 Anonymize local IPs exposed by WebRTC 设置为 disabled ( 刷新程序,IP正常显示 )

    四、 使用设备指纹

    首先可以想到的是使用uuid生成一个放在本地,但是不够固定。删了本地存的,在浏览器版本未变的情况下就又生成了一个新的。

    npm 上的fingerprintjs 这个指纹信息可以是字体、canvas、插件、屏幕分辨率、时区、地理位置或者是你使用的语言等其他的参数,信息越多并且信息的区别度越大,越能决定浏览器指纹的准确性。
    在高版本要获得许可了,可以使用免费的低版本版本。

    实测使用它在不同机器上,相同版本浏览器下生成唯一id是不一样的,似乎可用。
    依然要注意以下问题:

    1. 升级浏览器后,id会变 (重装浏览器,大概率版本号也变了)
    2. 稳定性,这个id会持续多久。文档提到免费版维持几周
    3. 不同的浏览器生成的id是不一样的。

    这里我在登陆时生成一次后,存在本地。后续登陆不再生成,并结合浏览器名称和版本,作为唯一标识id。基本满足使用场景来判断这个用户是否在另一个人的机器上登陆过

    相关文章

      网友评论

          本文标题:标识访问者电脑与账户的关系,获取ip,mac或者设备指纹对比

          本文链接:https://www.haomeiwen.com/subject/eyrnidtx.html