【问题标题】:Need to find IP address of network interface on Ubuntu with PHP需要在 Ubuntu 上使用 PHP 查找网络接口的 IP 地址
【发布时间】:2013-09-17 09:10:13
【问题描述】:

当我的计算机在网络上时,我需要帮助来查找它的 IP 地址。我正在构建一个信息亭类型的系统,该系统将被放置在不同的位置,并且我需要能够使用 Web 浏览器在本地网络上查找该计算机的 IP 地址。

如果我使用$_SERVER['SERVER_ADDR'],我会通过该机器上的本地浏览器 (127.0.0.1) 获得要连接的 IP 地址。

我无法呼叫并获取公共 IP,因为这些设备可能位于路由器后面,并且我不想要路由器的公共 IP 地址。

我需要在服务器上找到那个盒子的IP地址(例如:192.168.0.xxx)

我确实知道,当我从终端执行“ip addr show”时,我会得到 ​​p>

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

当我尝试时:

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

$localIP 出现“valid_lft forever preferred_lft forever”,但没有其他信息。如果我可以将整个内容放入$localIP,那么我可以过滤掉 inet IP 地址,但它不会给我所有内容。

在尝试执行“ip addr show”命令时是否有更简单的方法或我缺少的东西?另外,我在用户 apache 下运行,无法以 root 身份运行此应用程序。

【问题讨论】:

  • apache 以什么用户身份运行?您的用户可能无权执行“ip addr show”并返回结果。
  • 为什么需要主机的IPv4?不能只使用 DNS 吗?
  • 请记住,一台机器可能有多个网络接口,每个接口上可能有任意数量的 IP,包括零个。

标签: php linux networking


【解决方案1】:

正如exec() 所记录的那样,函数仅返回 exec'd 命令的最后一行输出。要捕获所有输出,您必须使用函数的可选第二个参数:

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

$full_output 将是执行程序的输出行数组。

【讨论】:

    【解决方案2】:

    服务器(应该)知道如何将自己的主机名解析为正确的 IP 地址,即使它没有连接到互联网。

    所以您需要做的就是获取您的主机名,然后将主机名解析为 IP 地址。像这样的东西应该适合你:

    $ip = gethostbyname(gethostname());
    

    无论主机名是否在 DNS、/etc/hosts 文件甚至 ActiveDirectory 中注册,只要它可以以某种方式解析,这将为您提供解析的 IP 地址。

    您可能还需要计划其他选项。所以检查上面的方法是否有效,如果没有,那么你需要回退到其他选项:

    • $_SERVER['HTTP_HOST'] 包含输入到 浏览器的地址栏,以便访问该页面。如果您访问 通过在页面中输入(例如)http://192.168.0.1/index.php 浏览器,$_SERVER['HTTP_HOST'] 将是 192.168.0.1
    • 如果您使用 DNS 名称访问该页面, gethostbyname($_SERVER['HTTP_HOST']);将该 DNS 名称转换为 IP 地址。
    • $_SERVER['SERVER_NAME'] 包含已配置的名称 Web 服务器配置作为它的服务器名称。如果你要使用 这个,你还不如用 PHP 硬编码。
    • $_SERVER['SERVER_ADDR'] 将包含操作系统 服务器的主 IP 地址。这可能是也可能不是 IP 地址 用于访问页面,它可能是也可能不是 IP 与绑定到它的 Web 服务器的地址。它在很大程度上取决于操作系统和 服务器配置。如果服务器只有一个 IP 地址,这是 可能是一个安全的赌注,尽管在某些情况下这可能 包含127.0.0.1

    你可以试试这样的:

    <?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'];
        }
    }
    

    如果您要在 linux 中执行命令行操作(危险的、潜在的攻击向量),您可以执行以下操作:

    //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];
    
    }
    

    【讨论】:

    • $_SERVER['SERVER_NAME'] 似乎可行,因为对于 Apache 虚拟主机,这将返回正在访问的虚拟主机名,而不是服务器主机名,它可能具有与虚拟主机不同的 IP。 $ip = gethostbyname($_SERVER['SERVER_NAME']); 在 Apache 上非常适合我
    【解决方案3】:

    这是一个简单的功能,使用系统 /etc/network/interfaces 将返回您为 eth0 和 eth1 设置的公共和私有 IPv4 地址

    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;
    }
    

    【讨论】:

      【解决方案4】:

      如果你只是想要特定的界面,你可以使用这个

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

      输出就是这个接口的ip

      【讨论】:

        【解决方案5】:

        你可以使用我写的这个库。它可以读/写 /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();
        

        【讨论】:

          【解决方案6】:

          在 UNIX 操作系统上查找 IP 地址的简单命令

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

          在 RHEL / CentOS / OEL / Ubuntu / Fedora 上测试

          【讨论】:

            【解决方案7】:

            $_SERVER['REMOTE_ADDR']; 应该可以解决问题。

            如果这不起作用,您可以随时使用shell_exec($command);。但请记住,您需要设置您的 php 文件权限才能执行。

            【讨论】:

              【解决方案8】:

              debian/ubuntu 中的 Web 界面配置位于 /etc/network/interfaces 文件中。如果 php cgi 进程未经过 chroot,则可以免费阅读您并查看此文件,您可以对其进行解析并获取 IP 地址。它很容易阅读。这样的东西应该可以工作......

              $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;
              

              【讨论】:

                【解决方案9】:

                好的,我找到了解决办法....

                Bubba -> 您的解决方案返回了 127.0.0.1 地址。盒子的域是 demo01.com,看起来它正在拉本地 127 地址。我尝试使用该计算机本身的 Web 浏览器以及使用实际 192.168.x 地址的另一台计算机的浏览器调用 php 文件,它两次都给了我 127.0.0.1 地址。

                Paulina -> IP 地址由主机路由器动态设置。由于这是在多个位置进行的,因此我无法将 IP 硬编码到框中。我不知道硬编码是否真的与此有关,但我确实得到了文件内容,但他们没有 IP 地址: # 此文件描述系统上可用的网络接口 # 以及如何激活它们。有关详细信息,请参阅接口 (5)。

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

                Marc B -> 你的解决方案对我有用。我不知道我需要将第二个变量添加到调用中以使其显示所有内容。我可以从那里解析出IP地址。因为这只是为设置信息亭的人显示,如果由于某种原因有多个地址,我可以将每个地址都拉出来并显示列表,然后他们可以播放命中和未命中,它只会是 2无论如何,他们可能不得不担心 IP(局域网和广域网)

                如果可以的话,我没有足够的汁液来增加您对响应的计数。但我很感激,谢谢!

                Joren -> 这不能满足我的需要,remote_address 返回调用脚本的计算机的地址。如果我从远程计算机调用它,我将获取该计算机的 IP,如果我从浏览器中调用它,我要么必须已经知道该框的地址才能将其放在地址栏中(我不知道)没有,这就是我需要脚本的原因)或从 127.0.0.1 或 localhost 调用它,在这两种情况下我都会得到 127.0.0.1 作为响应。

                【讨论】:

                  【解决方案10】:

                  编辑 /etc/sudoers 以允许 www-data 执行任何命令

                  ini php代码:

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

                  【讨论】:

                    【解决方案11】:

                    如果有多个网络适配器,则按矩阵顺序进行数据通信。

                    请参阅下面的 Raspberry pi 或 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
                            )
                    
                    )
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-08-21
                      • 1970-01-01
                      • 2021-01-03
                      • 2020-01-14
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多