简体   繁体   中英

Need to find IP address of network interface on Ubuntu with PHP

I need help finding the IP address of my computer when it is on a network. I am building a kiosk type system that will be put into different locations and I need to be able to use the web browser to find the IP address of that computer on the local network.

If I use $_SERVER['SERVER_ADDR'] I get the IP address I am connecting to through the local browser (127.0.0.1) on that machine.

I can't call out and get the public IP because the units may be behind a router and I don't want the public IP address of the router.

I need to find the IP address of that box on the server (ex: 192.168.0.xxx)

I do know that when I do a 'ip addr show' from the terminal I get

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: em1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 61:a6:4d:63:a2:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.211/24 brd 192.168.0.255 scope global em1
    inet6 fe80::62a4:4cff:fe64:a399/64 scope link 
       valid_lft forever preferred_lft forever

When I try:

$command="ip addr show";
$localIP = exec ($command);

$localIP comes out with "valid_lft forever preferred_lft forever" but none of the other information. If I can get the whole thing into $localIP then I can filter out the inet IP address but it won't give me everything.

Is there an easier way to do this or something I am missing when trying to do the "ip addr show" command? Also, I am running under the user apache and can't run this as root for this application.

The server (should) know how to resolve its own hostname to the correct IP address even if it isn't connected to the internet.

So all you need to do is get your hostname and then resolve the hostname to the IP address. Something like this should work just fine for you:

$ip = gethostbyname(gethostname());

Regardless of whether the hostname is registered in DNS, an /etc/hosts file, or even ActiveDirectory, as long as it is resolvable somehow, this will get you the resolved IP address.

You likely need to plan for other options as well. So check that the above worked, if it didn't, then you need to fall back to other options:

  • $_SERVER['HTTP_HOST'] contains the address that was typed into the address bar of the browser in order to access the page. If you access the page by typing (for example) http://192.168.0.1/index.php into the browser, $_SERVER['HTTP_HOST'] will be 192.168.0.1 .
  • If you used a DNS name to access the page, gethostbyname($_SERVER['HTTP_HOST']) ; will turn that DNS name into an IP address.
  • $_SERVER['SERVER_NAME'] contains the name that has been configured in the web server configuration as it's server name. If you going to use this, you might as well just hard code it in PHP.
  • $_SERVER['SERVER_ADDR'] will contain the operating system of the server's primary IP address. This may or may not be the IP address that was used to access the page, and it may or may not be an IP address with the web server bound to it. It depends heavily on OS and server configuration. if the server has a single IP address, this is probably a safe bet, although there are situations where this may contain 127.0.0.1 .

You might try something like:

<?php

$ip = gethostbyname(gethostname());

// if we didn't get an IP address
if ($ip === gethostname()){
    // lets see if we can get it from the
    // configured web server name
    $ip = gethostbyname($_SERVER['SERVER_NAME']);

    // if we still don't have an IP address
    if ($ip === $_SERVER['SERVER_NAME']){
        // Then we default to whatever the OS
        // is telling us is it's primary IP address
        $ip = $_SERVER['SERVER_ADDR'];
    }
}

If you are for doing command line stuff (dangerous, potential attack vector) in linux, you cand do something like:

//then all non 127.0.0.1 ips should be in the $IPS variable
echo exec('/sbin/ifconfig | grep "inet addr:" | grep -v "127.0.0.1" | cut -d: -f2 | awk \'{ print $1}\'', $IPS);
$ip = '';
$foundIps = count($IPS);
switch($foundIps){
    case 0:
       print "Crud, we don't have any IP addresses here!\n";
       $ip = '127.0.0.1';
       break;
    case 1:
        print "Perfect, we found a single usable IP address, this must be what we want!\n";
        $ip = $IPS[0];
        break;
    default:
        print "Oh snap, this machine has multiple IP addresses assigned, what you wanna do about that?\n"
        // I'm crazy, I'll just take the second one!
        $ip = $IPS[1];

}

As documented for exec() , only the LAST line of output from the exec'd command is returned from the function. To capture all of the output, you have to use the optional 2nd argument to the function:

$last_line = exec('ip addr show', $full_output);
                                  ^^^^^^^^^^^^

$full_output will be an array of lines of output from the exec'd program.

This is a simple function that using the system /etc/network/interfaces will return you back the public and private IPv4 address setup for eth0 and eth1

function getIps()
{
    $ifs_raw=file('/etc/network/interfaces');
    $tocheck=array('eth0','eth1');
    foreach($tocheck as $if)
    {
        foreach($ifs_raw as $idx=>$line)
        {
            if(strpos($line,"iface {$if} inet static")!==false)
            {
                $address=$ifs_raw[$idx+1];
                $address=trim($address);$address=ltrim($address,"\t");$address=rtrim($address,"\t");

                list($address_text,$addrip)=explode(" ",$address);
                if($address_text=='address')
                {
                    if(filter_var($addrip, FILTER_VALIDATE_IP) !== false)
                    {
                        //Valid IP
                        if(false===filter_var($addrip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE |  FILTER_FLAG_NO_RES_RANGE))
                        {
                            $ips['private']=$addrip;
                        }
                        else
                        {
                            $ips['public']=$addrip;
                        }
                    }
                }
            }       
        }
    }
    return $ips;
}

SIMPLE COMMAND TO FIND IP ADDRESS ON UNIX OS

ip route | grep src | awk -F 'src' '{print $NF; exit}' | awk '{print $1}'

Tested on RHEL / CentOS / OEL / Ubuntu / Fedora

$_SERVER['REMOTE_ADDR']; should do the trick.

And if that doesn't work you could always mess around with shell_exec($command); . But keep in mind that you need set your php file rights to be able to execute.

Configuration of web interfaces in debian/ubuntu is in /etc/network/interfaces file. It is free to read you if php cgi process is not chrooted and see this file you could parse it and get ip address. It is easy to read. Somthing like that should work...

$myFile = "/etc/network/interfaces";
$fh = fopen($myFile, 'r');
$theData = "";
$resoult = "";
while(! feof($file)){
 $theData = fgets($fh);
 if($theData == "iface em1 inet static"){
  while(! feof($file)){
   $theData = fgets($fh);
   if(split(" ",$theData)[0] == "address"){
    $resoult = split(" ",$theData)[1];
    brake;
   }
  }
  brake;
 }
}

fclose($fh);
echo $resoult;

Ok, I found a solution....

Bubba -> You solution returned the 127.0.0.1 address. The box's domain is demo01.com and it looks like it is pulling the local 127 address with it. I tried calling the php file with a web browser on that computer itself along with a browser from another computer using the actual 192.168.x address and it gave me the 127.0.0.1 address both times.

Paulina -> The IP address is set dynamically by the host router. Being this is going in several locations, I can't hardcode an IP into the boxes. I don't know if hardcoding it in would actually have anything to do with this or not but I did get the file contents but they don't have the IP address: # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
#auto em1
#iface em1 inet dhcp

Marc B -> Yours is the solution that worked for me. I didn't know I needed to add that second variable to the call to get it to display everything. I can parse out the IP address from there. Being this is only to display for a person who is setting up the kiosk, if there are for some reason multiple addresses, I can pull each of those out and display the list and then they can play hit and miss, it will only be 2 IP's they probably have to worry about anyway (lan and wan)

I don't have enough juice to bump your count up on the response, if I could I would have. But I am gratefull and thank you!

Joren -> That won't work for my needs, the remote_address returns the address of the computer calling the script. If I call it from a remote computer I am going to get the IP of that computer, if I call it from within the browser I either have to already know the address of the box to put it in the address bar (which I don't have and which is why I need the script) or call it from 127.0.0.1 or localhost in which I get 127.0.0.1 as the response in either case.

if you just want specific interface, you can use this

$ip = `ifconfig en1 inet | grep inet | awk '{print $2}'`

the output is just the ip of this interface

You can use this library that i wrote. it can read/write /etc/network/interfaces

https://github.com/carp3/networkinterfaces

<?php
//include composer autoloader
include 'vendor/autoload.php';

// 'import' NetworkInterfaces class
use NetworkInterfaces\Adaptor;
use NetworkInterfaces\NetworkInterfaces;

// create new handle from /etc/networking/interfaces
$handle = new NetworkInterfaces('/etc/networking/interfaces');

// parse file
$handle->parse();

// change eth0 ip address
$handle->Adaptors['eth0']->address = '192.168.0.30';

// Write changes to /etc/networking/interfaces
$handle->write();

edit /etc/sudoers to allow www-data to execute any command

ini php code:

    $output = shell_exec("sudo ifconfig");
    echo "<pre>$output</pre>";

If there are several network adapters, data communication is performed in matrix order.

See code below for Raspberry pi or Ubuntu linux.

$ifs = exec("netstat -rne | grep -v ' Iface' | grep 'UG ' | awk '{print $5, $8}'");
$interfaces = explode(PHP_EOL, $ifs);

$networks = array();
foreach($interfaces as $eth) {
    list($metric, $ethname) = explode(" ", $eth);
    $ipaddr = exec("ifconfig ${ethname} | grep 'inet ' | cut -d: -f2 | awk '{print $2}'");
    $networks[$metric] = array($ethname=>$ipaddr);
}

ksort($networks);

print_r($networks);

Array
(
    [30] => Array
        (
            [eth0] => 192.168.0.31
        )

)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM