【发布时间】:2011-12-16 02:22:34
【问题描述】:
我经常听到有人说要使用“$_SERVER['SERVER_ADDR']”,但这会返回我服务器的 LAN IP(例如 192.168.1.100)。我想要外部IP。
【问题讨论】:
我经常听到有人说要使用“$_SERVER['SERVER_ADDR']”,但这会返回我服务器的 LAN IP(例如 192.168.1.100)。我想要外部IP。
【问题讨论】:
如果您使用的是路由器,则无法通过传统 PHP 获取您的 ISP 指定的基础 IP 地址。获取外部 IP 的一种方法是找到一个服务,该服务将为您获取它并将地址回显给您。我找到了一个方便的服务。 http://ipecho.net/
你可以使用:
$realIP = file_get_contents("http://ipecho.net/plain");
【讨论】:
只需查询返回您的 IP 地址的主机:
$externalContent = file_get_contents('http://checkip.dyndns.com/');
preg_match('/Current IP Address: \[?([:.0-9a-fA-F]+)\]?/', $externalContent, $m);
$externalIp = $m[1];
或者,设置一个只回显 IP 的服务,并像这样使用它:
$externalIp = file_get_contents('http://yourdomain.example/ip/');
通过简单地回显远程 IP 地址自行设置服务,或花钱请人托管。未经许可,请勿不要使用他人的服务器。以前,此答案与我的一项服务相关联,该服务现在每秒被多次点击。
请注意,在具有一个或多个NATs 的 IP 网络中,您可能有多个外部 IP 地址。这只会给你其中之一。
此外,此解决方案当然取决于可用的远程主机。但是,由于没有广泛实施的标准(没有 ISP,只有一些家庭路由器实施UPnP),没有其他方法可以获取您的外部 IP 地址。即使您可以与本地 NAT 通信,您也无法确定它后面是否有另一个 NAT。
【讨论】:
[ 允许使用括号来分隔 IPv6 地址。最后的< 确实是可选的,如果格式发生变化,它会使代码更加健壮。
我将添加一个解决方案,因为其他解决方案不太适合我,因为他们:
gethostbyname()(如果你考虑一下,如果你先验地知道,你实际上并没有问题)$_SERVER 中的某些内容由 Web 服务器设置)ifconfig输出的特定格式,可以包括多个非公共接口这是我的建议:
$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
IP 地址有一个Google public DNS 服务器。我相信他们会在附近运行一段时间。你在那里使用什么地址并不重要,只要它是属于不介意随机连接尝试太多的人的公共 IP 地址(也许是你自己?)。
这是基于我在 Python 中遇到类似问题时遇到的 answer。
P.S.:如果你的机器和互联网之间发生巫术,我不确定上述方法的效果如何。
【讨论】:
您可以从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;
【讨论】:
ip4.me 站点,因为在这种情况下,您(您客户的)浏览器可能没有 IPv6 连接并显示Page not found。跨度>
你可以试试这个:
$ip = gethostbyname('www.example.com');
echo $ip;
获取与您的域名关联的 IP 地址。
【讨论】:
我知道这个问题已经很久很久了,但我在谷歌上搜索同样的东西并想添加我自己的“hack”。为此,您的 webrequest 必须来自外部 IP 地址,或者您必须将 $own_url 更改为对其自身执行外部请求的 url。
关键是,如果您让脚本向自己发出请求,而不是获得它的外部 IP 地址。
<?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;
?>
【讨论】:
我认为其他答案中有很多代码,但我的答案很短,但是您需要在shell中执行命令才能获取ip...
但它又短又快,我认为...
php 执行 bash > bash 运行 > bash 获取 ip > php 获取 ip
echo shell_exec( "dig +short myip.opendns.com @resolver1.opendns.com");
对不起我的英语,我希望它对你有帮助......
【讨论】:
这是一个旧线程,但为了它的价值,我添加了一个我使用的简单函数。它使用外部服务(这似乎是不可避免的),但它也提供备份服务和本地缓存以避免重复的 HTTP 调用。
/*
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/json') );
$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.
}
【讨论】:
如果您的服务器有域名,您可以 ping 或使用:
$sMyServerIP = gethostbyname('yourdomain.com');
echo $sMyServerIP;
它将返回您的外部 IP 地址。
【讨论】:
假设您的 PHP 在 Linux 服务器上运行,您可以使用 PHP 的 exec 函数调用 ifconfig。这将提供公共 IP,而无需联系某些外部网站/服务。例如:
$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>';
}
请注意,有时作为 $command 您必须指定 ifconfig 的完整路径。你可以通过执行找到这个
ifconfig 在哪里
来自 shell 提示符。此外,$interface 应该设置为您的服务器的主网络接口的名称,该接口具有到 WAN 的链接。
在 Windows 上,你当然可以做类似的事情,使用 ipconfig 而不是 ifconfig(以及相应的调整正则表达式)。
【讨论】:
您也可以通过基于主机名或服务器名的 DNS A 记录获取 IP:
$dnsARecord = dns_get_record($_SERVER['HTTP_HOST'],DNS_A);
if ( $dnsARecord ) echo 'IPv4: '.$dnsARecord[0]['ip'];
$dnsARecord = dns_get_record($_SERVER['HTTP_HOST'],DNS_AAAA);
if ( $dnsARecord ) echo 'IPv6: '.$dnsARecord[0]['ip'];
如果两者之一不能满足您的需求,您也可以使用 SERVER_NAME 而不是 HTTP_HOST。
但是,这是假设您的服务器已根据 DNS 正确配置。情况可能并非总是如此。使用 ifconfig 查看我的其他答案可能更好。
【讨论】:
你试过了吗:
gethostbyname(php_uname('n'));
?
【讨论】:
php_uname('n') 在大多数情况下返回 internal IP 地址,即基于 LAN。 OP 要求一个外部。