首页 > 代码库 > nginx反向代理下thinkphp、php获取不到正确的外网ip
nginx反向代理下thinkphp、php获取不到正确的外网ip
在记录用户发送短信需要获取用户ip时,tp一直获取的是内网ip:10.10.10.10
tp框架获取ip方法:get_client_ip
1 /** 2 * 获取客户端IP地址 3 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 4 * @param boolean $adv 是否进行高级模式获取(有可能被伪装) 5 * @return mixed 6 */ 7 function get_client_ip($type = 0,$adv=false) { 8 $type = $type ? 1 : 0; 9 static $ip = NULL;10 if ($ip !== NULL) return $ip[$type];11 if($adv){12 if (isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘])) {13 $arr = explode(‘,‘, $_SERVER[‘HTTP_X_FORWARDED_FOR‘]);14 $pos = array_search(‘unknown‘,$arr);15 if(false !== $pos) unset($arr[$pos]);16 $ip = trim($arr[0]);17 }elseif (isset($_SERVER[‘HTTP_CLIENT_IP‘])) {18 $ip = $_SERVER[‘HTTP_CLIENT_IP‘];19 }elseif (isset($_SERVER[‘REMOTE_ADDR‘])) {20 $ip = $_SERVER[‘REMOTE_ADDR‘];21 }22 }elseif (isset($_SERVER[‘REMOTE_ADDR‘])) {23 $ip = $_SERVER[‘REMOTE_ADDR‘];24 }25 // IP地址合法验证26 $long = sprintf("%u",ip2long($ip));27 $ip = $long ? array($ip, $long) : array(‘0.0.0.0‘, 0);28 return $ip[$type];29 }
因一些原因,w项目是在Apache下,后来另外一些项目挤进来使用了nginx,nginx下的项目需要也微信80端口授权,所以使用了反向代理。
经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址
tp框架自带函数获取的是$remote_addr,所以我们没办法获取真实ip。
打开/usr/local/reverse_proxy_nginx/conf/nginx.conf 可以看到如下关键配置
location / { proxy_pass http://backend2; #Proxy Settings proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
测试
$remoteaddr=$_SERVER["REMOTE_ADDR"]; echo $remoteaddr; echo "---"; $remotehost=$_SERVER["REMOTE_HOST"]; echo $remotehost; echo "---"; $xforwardedfor=$_SERVER["HTTP_X_FORWARDED_FOR"]; echo $xforwardedfor; echo "---"; $xrealip=$_SERVER["HTTP_X_REAL_IP"]; echo $xrealip;
输出
10.10.10.123------181.128.136.191---181.128.136.191
181.128.136.191便是你真实的外网ip,所以只需要获取HTTP_X_FORWARDED_FOR或者HTTP_X_REAL_IP就可以了。
下面是修改后的tp框架函数
ThinkPHP\Common\functions.php
1 /* 2 * 访问时用localhost访问的,读出来的是“::1”是正常情况。 3 * ::1说明开启了ipv6支持,这是ipv6下的本地回环地址的表示。 4 * 使用ip地址访问或者关闭ipv6支持都可以不显示这个。 5 */ 6 function get_client_ip() { 7 $ip = "unknown"; 8 if (isset($_SERVER)) { 9 if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {10 $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];11 } elseif (isset($_SERVER["HTTP_CLIENT_ip"])) {12 $ip = $_SERVER["HTTP_CLIENT_ip"];13 } else {14 $ip = $_SERVER["REMOTE_ADDR"];15 }16 } else {17 if (getenv(‘HTTP_X_FORWARDED_FOR‘)) {18 $ip = getenv(‘HTTP_X_FORWARDED_FOR‘);19 } elseif (getenv(‘HTTP_CLIENT_ip‘)) {20 $ip = getenv(‘HTTP_CLIENT_ip‘);21 } else {22 $ip = getenv(‘REMOTE_ADDR‘);23 }24 }25 if(trim($ip)=="::1"){26 $ip="127.0.0.1";27 }28 return $ip;29 }
Apache下的tp项目,再调用get_client_ip函数就可正常获取外网ip了
nginx反向代理下thinkphp、php获取不到正确的外网ip
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。