文章目录

  • 一、前言
  • 二、关于用户IP的背景知识
  • 2.1 HTTP请求
  • 2.2 HTTP代理服务器
  • 2.3 X-Forwarded-For头部
  • 三、代码实现
  • 3.1 Nginx配置
  • 3.2 PHP代码处理
  • 总结


一、前言

在Web应用程序中,IP地址是常见的数据项。例如,它可以用于用户认证、访问控制、日志记录和其他安全功能。然而,在某些情况下,获取客户端的真实IP地址可能会变得非常困难。

nginx 获取不到443请求 nginx获取请求ip_tcp/ip

由于HTTP协议的本质,当您从Web服务器接收请求时,它只包含HTTP头中的客户端的最后一个代理服务器的IP地址。这称为X-Forwarded-For头。

因此,如果您希望了解客户端的真实IP地址,则需要深入探究HTTP请求如何跨多个代理服务器传递。

本文将向您展示如何使用PHP和Nginx来获取客户端的真实IP地址。

二、关于用户IP的背景知识

在深入探讨代码之前,我们需要先了解一些基础知识。如什么是HTTP,HTTP请求包含了哪些信息。请求到服务器这个过程是怎么一回事等。

2.1 HTTP请求

nginx 获取不到443请求 nginx获取请求ip_nginx_02

HTTP请求由请求行、请求头和请求体组成。

请求行指定请求方法(GET、POST等)、URI和HTTP协议的版本号。

请求头包含HTTP版本、Host头、User-Agent头、Cookie头和其他自定义头部。

请求体包含客户端提交的数据,通常是表单数据或JSON数据。

2.2 HTTP代理服务器

HTTP代理服务器是介于客户端和Web服务器之间的一种服务器。代理服务器可以用于缓存、负载均衡、安全性和其他目的。当客户端向代理服务器发出HTTP请求时,代理服务器将该请求转发到下一个目标服务器。

nginx 获取不到443请求 nginx获取请求ip_nginx 获取不到443请求_03

2.3 X-Forwarded-For头部

X-Forwarded-For头是一种HTTP头部,用于指示客户端的真实IP地址。当Web服务器从代理服务器接收请求时,它会检查X-Forwarded-For头,并提取最后一个IP地址。如果此头不存在,则Web服务器将使用代理服务器的IP地址。

如果请求通过多个代理服务器传递,则每个代理服务器都可以在X-Forwarded-For头中添加一个IP地址。在这种情况下,最后一个IP地址是客户端的真实IP地址。

三、代码实现

3.1 Nginx配置

PHP代码正常工作,我们需要在Nginx服务器上启用X-Forwarded-For头部。这是通过将以下行添加到Nginx配置文件中完成的:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

此行告诉Nginx将客户端的IP地址添加到X-Forwarded-For头中。当请求被转发时,代理服务器将检查此头以提取客户端的真实IP地址。

以下是完整的Nginx配置文件示例:

server {
    listen 80;
    server_name example.com;
 
    access_log /var/log/nginx/example.access.log main;
    error_log /var/log/nginx/example.error.log;
 
    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

此配置将所有请求转发到本地主机上运行的HTTP服务器。每个传入请求都会添加一个X-Forwarded-For头并转发到9000端口。

3.2 PHP代码处理

以下是获取客户端真实IP地址的PHP代码:

function get_ip_address() {
    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
 
    // Check for IP passed in via HTTP_X_FORWARDED_FOR header
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // Check if multiple IP addresses exist in this header
        $ip_addresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
 
        foreach ($ip_addresses as $ip) {
            if (validate_ip($ip)) {
                return $ip;
            }
        }
    }
 
    // Check for IP passed in via REMOTE_ADDR header
    if (validate_ip($_SERVER['REMOTE_ADDR'])) {
        return $_SERVER['REMOTE_ADDR'];
    }
 
    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}
 
function validate_ip($ip) {
    if (strtolower($ip) === 'unknown') {
        return false;
    }
 
    // Generate IPv4 network address
    $ipv4_network = ip2long('0.0.0.0/24');
 
    // Generate IPv6 network address
    $ipv6_network = inet_pton('::ffff:0.0.0.0') . '/96';
 
    // Check if IP address is IPv4
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
        // Convert IP to IPv4 network address
        $ip_network = ip2long($ip) & ~((1 << (32 - 24)) - 1);
 
        return $ip_network === $ipv4_network;
    }
 
    // Check if IP address is IPv6
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
        // Convert IP to IPv6 network address
        $ip_network = inet_pton($ip) & ~((1 << (128 - 96)) - 1);
 
        return $ip_network === $ipv6_network;
    }
 
    return false;
}

此代码使用3种方法来检测客户端的真实IP地址:

  1. 如果HTTP_CLIENT_IP头部存在且有效,则返回该IP地址。
  2. 如果HTTP_X_FORWARDED_FOR头部存在,则迭代其值,并返回第一个有效IP地址。
  3. 如果REMOTE_ADDR头部存在且有效,则返回该IP地址。
  4. 如果所有检查都失败,则返回REMOTE_ADDR头中的IP地址。

validate_ip()函数用于检查传递的IP地址是否有效。以下是它的工作原理:

  1. 检查地址是否为“unknown”。
  2. 生成IPv4和IPv6的网络地址。
  3. 检测IP地址是否为IPv4,并将其转换为网络地址。如果地址匹配IPv4网络地址,则返回true。
  4. 检测IP地址是否为IPv6,并将其转换为网络地址。如果地址匹配IPv6网络地址,则返回true。

总结

以上内容介绍了如何通过PHP结合Nginx实现获取用户真实IP地址。我们从了解了HTTP请求和代理服务器的工作原理出发,并讨论了X-Forwarded-For头的作用。最后演示了如何编写有效的PHP代码来获取客户端真实IP地址。

nginx 获取不到443请求 nginx获取请求ip_tcp/ip_04