dd(request()->ip());
var_dump(request()->getClientIp());
但是,这是在没有代理的情况下,有时候我们的业务使用了反向代理、负载均衡、cdn加速等等,我们就要设置信任的代理IP。
修改 app\Http\Middleware\TrustProxies.php
中的 $proxies
protected $proxies = [
'192.168.1.1/24',//你信任的代理IP,支持IP段。
];
如果你不清楚代理服务器IP,或者IP会一直变动。可以设置信任所有代理。(这样是极其不安全的,用户可以伪造X-Forwarded-For来伪造IP)
192.168.1.0/24表示网段是192.168.1.0,子网掩码是24位,子网掩码为:255.255.255.0,
用二进制表示为:11111111 11111111 11111111 00000000 ,
这里为什么是24呢,就是因为子网掩码里面的前面连续的“1”的个数为24个,一定要连续的才行。
192.168.1.0/28表示的意思是网段是192.168.1.0,子网掩码为:255.255.255.240,
用二进制表示为:11111111 11111111 11111111 11110000。
这时候你也许就疑惑了,就是24和28两个字不一样,为什么网段是一样的呢?
24位说明网络位是24位,那么主机位就是32-24=8位了,则子网的IP个数是254个,即是从00000001到11111110.
28位说明网络位是28位,那么主机位4位,则子网的IP个数是14个,即是从00000001到00001110.
protected $proxies = '**';
namespace App\Http\Controllers;
class TestController extends Controller
{
public function ip()
{
dd($this->getClientIp());
}
/**
* 获取用户真实 ip
* @return array|false|mixed|string
*/
private function getClientIp()
{
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
}
if (getenv('HTTP_X_REAL_IP')) {
$ip = getenv('HTTP_X_REAL_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
$ips = explode(',', $ip);
$ip = $ips[0];
} elseif (getenv('REMOTE_ADDR')) {
$ip = getenv('REMOTE_ADDR');
} else {
$ip = '0.0.0.0';
}
return $ip;
}
}
(PHP 4,PHP 5,PHP 7,PHP 8)
getenv —获取环境变量的值
var_dump(getenv('PATH'));
string(106) "/usr/local/node/bin:/usr/local/jdk-12.0.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$_SERVER['HTTP_CLIENT_IP']; //代理端的(有可能存在,可伪造)
nginx 代理模式下,获取客户端真实IP
$_SERVER['HTTP_X_REAL_IP']; // 得到的都是客户端的地址
在nginx中设置:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
后端程序可以从Server变量HTTP_X_REAL_IP和HTTP_X_FORWARDED_FOR中获取用户的ip地址。
HTTP_X_REAL_IP的值是nginx得到的用户REMOTE_ADDR。
$_SERVER['HTTP_X_FORWARDED_FOR']; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)
一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。
四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。
五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
如果不想获取代理ip需要对NGINX进行设置。
$_SERVER['REMOTE_ADDR']; //访问端(有可能是用户,有可能是代理的)IP
表示发出请求的远程主机的 IP 地址,remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。
x_forwarded_for
简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项,正如上面所述,当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,把连接它的客户端IP(即你的上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP。
格式一般为:
X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3
代表 请求由1.1.1.1发出,经过三层代理,第一层是2.2.2.2,第二层是3.3.3.3,而本次请求的来源IP4.4.4.4是第三层代理。
是很简单的场景,Nginx Proxy直接把请求往后转发,没有做任何处理
Nginx Proxy
192.168.107.107 nginx.conf
location /test {
proxy_pass http://192.168.107.112:8080;
}
192.168.107.112 nginx.conf
location /test {
proxy_pass http://192.168.107.114:8080;
}
Nginx Proxy就是简单的把请求往后转发。
Nginx Backend
192.168.107.114 nginx.conf
location /test {
default_type text/html;
charset gbk;
echo "$remote_addr || $http_x_forwarded_for";
}
Nginx Backend输出客户端IP( r e m o t e a d d r ) 和 X − F o r w a r d e d − F o r 请 求 头 ( remote_addr)和X-Forwarded-For请求头( remoteaddr)和X−Forwarded−For请求头(http_x_forwarded_for),当访问服务时输出结果如下所示:
192.168.107.112 ||
分析
1.$remote_addr
代表客户端IP,当前配置的输出结果为最后一个代理服务器的IP,并不是真实客户端IP;
2.在没有特殊配置情况下,X-Forwarded-For请求头不会自动添加到请求头中,即Nginx Backend的$http_x_forwarded_for输出为空。
判断192.168.1.127是否在 (192.168.1.1–192.168.1.255)的范围
定义变量 | 注释 |
---|---|
$ip_start = get_iplong(‘192.168.1.1’); | 起始ip |
$ip_end = get_iplong(‘192.168.1.255’); | 结束ip |
$ip = get_iplong(‘192.168.1.127’); | 判断的ip |
//可以这样简单判断
if($ip>=$ip_start && $ip <=$ip_end){
echo 'IP在此范围内';
}else{
echo 'IP不在此范围';
}
/*将ip地址转换成int型*/
function get_iplong($ip){
/*decbin() 函数把十进制数转换为二进制数,bindec() 函数把二进制转换为十进制。
ip2long();的意思是将IP地址转换成整型 ,
之所以要decbin和bindec一下是为了防止IP数值过大int型存储不了出现负数。 */
return bindec(decbin(ip2long($ip)));
}
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TestContainer extends Controller
{
# 获取客户端ip
public function containers()
{
if (getenv("HTTP_CLIENT_IP")) {
$ip = getenv("HTTP_CLIENT_IP");
}
else if (getenv("HTTP_X_FORWARDED_FOR")) {
$ip = getenv("HTTP_X_FORWARDED_FOR");
}
else if (getenv("HTTP_X_FORWARDED")) {
$ip = getenv("HTTP_X_FORWARDED");
}
else if (getenv("HTTP_FORWARDED_FOR")) {
$ip = getenv("HTTP_FORWARDED_FOR");
}
else if (getenv("HTTP_FORWARDED")) {
$ip = getenv("HTTP_FORWARDED");
}
else {
$ip = $_SERVER["REMOTE_ADDR"];
}
return $ip;
}
}