Remote IP address varies when client is tethered over cell

527 views Asked by At

I am building a solution in php which requires me to accurately know the ip of the requestor. For most cases, the classic call to

$ip = $_SERVER['REMOTE_HOST'];

works just fine.

However, I've noted that in the case where the client is making their request over a tethered connection, I get a completely different address than what google and my firewall report.

I can verify this on the client (tethered) side by searching for "my ip" on google which gives me an IP that matches what my server's firewall is reporting as well. Neither of these match what the $_SERVER['REMOTE_HOST'] contains on the server side though.

My questions then are:

  • Why do these addresses differ in general?
  • How do I get to the ip address that my firewall and google see, specifically using php?
3

There are 3 answers

0
mr_z_ro On BEST ANSWER

Huh, turns out this was being done using a javascript "feature" (what I'd think about calling a vulnerability instead) all along. Scary stuff, as it also exposes your internal IP address as well. Anyway it's something called WebRTC, that just started getting a lot of attention this week as it's been officially implemented by firefox and chrome:

//get the IP addresses associated with an account
function getIPs(callback){
    var ip_dups = {};

    //compatibility for firefox and chrome
    var RTCPeerConnection = window.RTCPeerConnection
        || window.mozRTCPeerConnection
        || window.webkitRTCPeerConnection;
    var mediaConstraints = {
        optional: [{RtpDataChannels: true}]
    };

    //firefox already has a default stun server in about:config
    //    media.peerconnection.default_iceservers =
    //    [{"url": "stun:stun.services.mozilla.com"}]
    var servers = undefined;

    //add same stun server for chrome
    if(window.webkitRTCPeerConnection)
        servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};

    //construct a new RTCPeerConnection
    var pc = new RTCPeerConnection(servers, mediaConstraints);

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

        //skip non-candidate events
        if(ice.candidate){

            //match just the IP address
            var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/
            var ip_addr = ip_regex.exec(ice.candidate.candidate)[1];

            //remove duplicates
            if(ip_dups[ip_addr] === undefined)
                callback(ip_addr);

            ip_dups[ip_addr] = true;
        }
    };

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

    //create an offer sdp
    pc.createOffer(function(result){

        //trigger the stun server request
        pc.setLocalDescription(result, function(){});

    }, function(){});
}

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

Source: https://github.com/diafygi/webrtc-ips

Demo: https://diafygi.github.io/webrtc-ips/

1
Kinexus On

They could well be using a proxy server which you would have no control over. The underlying client IP would not be visible if this were the case.

2
glglgl On

Thast depends on your cell phone provider. More often than not, your phone gets an IP address from the private range and gets NATed when making connections "to the internet" - like most of home networks.

Unlike home networks, the provider's network may have several connections (gateways) to the internet. So potentially every connection you make can go over a different gateway. Thus you see a different address on different calls.

In these cases (networks with several uplinks), the routing rules may be quite complicated. So for example, the destination may play a role - the provider might be peering at several different places (network nodes) and choose the one closest to the destination. So you can have consistent sources regarding one destination, but a different one on another destination.

In any case, you cannot do anything with these addresses, as the provider won't allow any incoming connections.