How do I get the external IP of my server using PHP?

后端 未结 12 2636
后悔当初
后悔当初 2020-11-30 07:47

I often hear people say to use \"$_SERVER[\'SERVER_ADDR\']\", but that returns the LAN IP of my server (e.g. 192.168.1.100). I want the external IP.

相关标签:
12条回答
  • 2020-11-30 08:11

    I know this question is old and long answered, but I was googling for the same thing and want to add my own "hack". For this to work your webrequest has to come from an external IP address or you have to alter $own_url to a url that does an external request to itself.

    The point is, if you let the script do a request to itself than you get it's external IP address.

    <?php
    if (isset($_GET['ip'])) {
        die($_SERVER['REMOTE_ADDR']);
    }
    $own_url = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
    $ExternalIP = file_get_contents($own_url.'?ip=1');
    echo $ExternalIP;
    ?>
    
    0 讨论(0)
  • 2020-11-30 08:12

    I'm going to add a solution because the others weren't quite right for me because they:

    • need to be run on a server with a domain name e.g. gethostbyname() (if you think about it, you don't actually have the problem if you know this a priori)
    • can't be used on the CLI (rely on something in $_SERVER to be set by a web server)
    • assume a specific format of ifconfig output, which can include multiple non-public interfaces
    • depend on parsing someone's website (who may disappear, change the URL, change the format, start lying to you, etc, all without notice)

    This is what I would suggest:

    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    $res = socket_connect($sock, '8.8.8.8', 53);
    // You might want error checking code here based on the value of $res
    socket_getsockname($sock, $addr);
    socket_shutdown($sock);
    socket_close($sock);
    
    echo $addr; // Ta-da! The IP address you're connecting from
    

    The IP address there is a Google public DNS server. I trust they'll be around and running it for a while. It shouldn't really matter what address you use there as long as its a public IP address that belongs to someone who doesn't mind random connection attempts too much (yourself maybe?).

    This is based on an answer I came across when I had a similar problem in Python.


    P.S.: I'm not sure how well the above would work if there is sorcery going on between your machine and the internet.

    0 讨论(0)
  • 2020-11-30 08:15

    This is an old thread, but for what it's worth, I'm adding a simple function that I use. It uses outside services (which is inevitable it seems), but it provides a backup service as well, and local caching to avoid repetitive HTTP calls.

    /*
    USAGE
    $ip = this_servers_public_ip(); // Get public IP, and store it locally for subsequent calls.
    $ip = this_servers_public_ip(true); // Force remote query and refresh local cache if exists.
    */
    function this_servers_public_ip($purge=false) {
        $local = sys_get_temp_dir().'/this.servers.public.ip';
        if ( $purge===true && realpath($local) ) {
            unlink($local);
        }
        if ( realpath($local) ) {
            return file_get_contents($local);
        }
        // Primary IP checker query.
        $ip = trim( file_get_contents('https://checkip.amazonaws.com') );
        if ( (filter_var($ip, FILTER_VALIDATE_IP) !== false) ) {
            file_put_contents($local,$ip);
            return $ip;
        }
        // Secondary IP checker query.
        $ip_json = trim( file_get_contents('https://ipinfo.io') );
        $ip_arr = json_decode($ip_json,true);
        $ip=$ip_arr['ip'];
        if ( (filter_var($ip, FILTER_VALIDATE_IP) !== false) ) {
            file_put_contents($local,$ip);
            return $ip;
        }
        return false; // Something went terribly wrong.
    }
    
    0 讨论(0)
  • 2020-11-30 08:16

    You could try this:

    $ip = gethostbyname('www.example.com');
    echo $ip;
    

    to get the IP address associated with your domain name.

    0 讨论(0)
  • 2020-11-30 08:19

    You could parse it from a service like ip6.me:

    <?php
    
    // Pull contents from ip6.me
    $file = file_get_contents('http://ip6.me/');
    
    // Trim IP based on HTML formatting
    $pos = strpos( $file, '+3' ) + 3;
    $ip = substr( $file, $pos, strlen( $file ) );
    
    // Trim IP based on HTML formatting
    $pos = strpos( $ip, '</' );
    $ip = substr( $ip, 0, $pos );
    
    // Output the IP address of your box
    echo "My IP address is $ip";
    
    // Debug only -- all lines following can be removed
    echo "\r\n<br/>\r\n<br/>Full results from ip6.me:\r\n<br/>";
    echo $file;
    
    0 讨论(0)
  • 2020-11-30 08:22

    Assuming your PHP is running on a Linux server you can call ifconfig using PHP's exec function. This will give public IP without need to contact some external website/service. E.g.:

    $command = "ifconfig";  /// see notes below
    $interface = "eth0";    // 
    exec($command, $output);
    $output = implode("\n",$output);
    if ( preg_match('/'.preg_quote($interface).'(.+?)[\r\n]{2,}/s', $output, $ifaddrsMatch)
            && preg_match_all('/inet(6)? addr\s*\:\s*([a-z0-9\.\:\/]+)/is', $ifaddrsMatch[1], $ipMatches, PREG_SET_ORDER) )
    {
        foreach ( $ipMatches as $ipMatch ) 
            echo 'public IPv'.($ipMatch[1]==6?'6':'4').': '.$ipMatch[2].'<br>';
    }
    

    Note that sometimes as $command you have to specify full path of ifconfig. You can find this by executing

    whereis ifconfig

    from shell prompt. Furthermore $interface should be set to the name of your server's main network interface that has the link to the WAN.

    On Windows you can do something similar of course, using ipconfig instead of ifconfig (and corresponding adjusted regex).

    0 讨论(0)
提交回复
热议问题