Nginx配置proxy protocol代理获取真实ip的全过程

 更新时间:2025年09月26日 09:29:27   作者:李袁明  
在现代开发中有很多场景需要拿到用户的真实ip,比如安全策略,和地区热点信息推送等功能,但是现在代理很多,用户可能会通过代理访问服务,或者黑客攻击的时候也会使用很多肉机隐藏其真实ip,所以本文给大家介绍了Nginx配置proxy protocol代理获取真实ip的全过程

前言

在现代开发中有很多场景需要拿到用户的真实ip,比如安全策略,和地区热点信息推送等功能,但是现在代理很多。用户可能会通过代理访问服务,或者黑客攻击的时候也会使用很多肉机隐藏其真实ip。接下来我们就来一起学习一下看怎么才能拿到真实的ip。

一、PROXY Protocol协议

PROXY Protocol 是一种由 HAProxy 作者 Willy Tarreau 于 2010 年设计的网络协议,旨在解决代理环境中后端服务器无法获取客户端真实信息(如源 IP、端口等)的问题。它通过在 TCP/UDP 连接建立后插入一个轻量级头部,实现客户端信息的透传,且与上层应用协议无关
它有两个版本:V1、V2

  • v1
  • 结构: PROXY <协议类型> <源IP> <目标IP> <源端口> <目标端口>
    特点:
    • 人类可读,便于调试。
    • 仅支持 TCP/IPv4/IPv6,无扩展能力。
    • 头部最大长度 108 字节(IPv6 场景)
  • v2
字段长度说明
签名(Signature)12 字节固定值 0x0D0A0D0A000D0A515549540A,标识 V2 协议
版本/命令(Ver/Cmd)1 字节高 4 位为版本号(0x2),低 4 位为命令(0x1=PROXY;0x0=LOCAL)
地址族/协议(Fam)1 字节高 4 位为地址族(IPv4/IPv6/UNIX),低 4 位为协议(TCP/UDP)
数据长度(Len)2 字节后续数据的长度(大端序)
地址数据(Addr)可变根据地址族存储源/目标 IP 和端口
TLV 扩展可变类型-长度-值结构,传递 SSL 证书、唯一 ID 等扩展信息

特点:

  • 高效​​:二进制解析速度快,适合高并发场景
  • 可扩展​​:通过 TLV 支持 SSL 信息(如证书 CN、加密算法)、唯一连接 ID 等
  • 多协议​​:支持 UDP、UNIX Socket 等

二、配置方法

现在内网测试有两台机器:
一台70,一台80;两台均为Linux机器
其中70是用于代理转发,把请求转发到80机器上进行处理
80就是部署程序的机器了

代理服务器配置

这里也就是指的70服务器
首先找到nginx对应的配置文件。一般路径都在:etc目录下
先切换到管理员权限:

sudo su

编辑配置文件命令

vi /etc/nginx/nginx.conf

配置内容

http模块代理

http {  # 使用 http 模块处理 HTTP 流量
   
server {
        listen 8888 proxy_protocol;  # 启用 PROXY Protocol 解析
        server_name localhost;

        location / {
            proxy_pass http://192.168.1.80:7890/;#转发目标地址(应用程序部署服务器)
            # 传递真实 IP 到后端(需后端支持)
            proxy_set_header X-Real-IP       $proxy_protocol_addr;  # 真实客户端 IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 兼容性头部
            proxy_set_header Host             $host;
        }
    }
 log_format tcp_log 'http->[$time_local] $proxy_add_x_forwarded_for → $server_addr ($status)';
         access_log /var/log/nginx/tcp_access.log tcp_log;#记录日志

}

防火墙开放端口

sudo ufw allow 8888/tcp

​​Stream 模块​代理

这我配置了一下日志,方便后面测试查看配置是否起效

stream {
    server {
        listen 8880 proxy_protocol;  # 启用PROXY协议解析
        proxy_pass 192.168.1.80:7890;#转发目标地址(应用程序部署服务器)
        proxy_protocol on; #显示启动代理协议透传
    }
    log_format tcp_log 'tcp->[$time_local] $proxy_protocol_addr → $server_addr ($status)';
    access_log /var/log/nginx/tcp_access.log tcp_log;#记录日志
}

防火墙开放端口

sudo ufw allow 8880/tcp

注意

http模块代理和stream模块代理监听的端口不能是相同

修改配置文件后需要重启nginx

nginx -s reload

重启服务

systemctl restart nginx

在stream 模块中的这一段配置

listen 8880 proxy_protocol

这里如果设置了就需要在请求中携带PROX头,下面我会用C#代码示例怎么携带,这一般是代理服务器自己会处理的,如果连接70机器的服务没有使用代理服务器这里我们就可以不添加
proxy_protocol 这一段 直接使用listen 8880即可,这样普通的TCP请求也可以直接连接。

测试配置是否生效

端口检查

重启成功后我们可以通过以下命令查看端口是否正常监听

sudo netstat -na | grep LIST | grep 8888

如果查看正常监听那就是配置成功了

测试ip记录

验证http

linux命令行输入以下命令(这里测试用的内网85的机器发起请求)

curl -H “X-Forwarded-For: 203.0.113.42” 192.168.1.70 8888

日志打印内容如下:

http->[22/Jul/2025:09:40:16 +0800] 203.0.113.42, 192.168.1.85 → 192.168.1.73 (200)

验证tcp

这里验证tcp我是采用的.net Core代码发起的tcp请求(181是我本机ip)

代码如下:

static void Main(string[] args)
{    try
        {
        // 创建 Socket
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // 连接到Nginx
        IPAddress ipAddress = IPAddress.Parse("192.168.1.73");
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, 8880);
        socket.Connect(remoteEP);

        // 构造并发送PROXY Protocol v1头部
        string proxyHeader = $"PROXY TCP4 {GetLocalIP()} 192.168.1.73 {GetLocalPort(socket)} 8880\r\n";
        byte[] proxyHeaderBytes = Encoding.ASCII.GetBytes(proxyHeader);
        socket.Send(proxyHeaderBytes);

        // 发送实际数据
        string request = "123465";
        byte[] requestData = Encoding.ASCII.GetBytes(request);
        socket.Send(requestData);

        // 辅助函数:获取本地IP
        
        string GetLocalIP()
        {
            return Dns.GetHostEntry(Dns.GetHostName())
                .AddressList.First(ip => ip.AddressFamily == AddressFamily.InterNetwork)
                .ToString();
        }

        // 辅助函数:获取本地端口
         int GetLocalPort(Socket _socket)
        {
            return ((IPEndPoint)_socket.LocalEndPoint).Port;
        }
    }
        catch (Exception ex)
        {
            Console.WriteLine($"发生错误: {ex.Message}");
        }
}

日志打印内容如下

tcp->[22/Jul/2025:10:16:32 +0800] 192.168.1.181 → 192.168.1.73 (200)

这里我们就可以看到我们模拟的proxy头里的ip了

流程如下

注意事项和理解误区

对于用户的真实ip获取需要注意的是,http请求可以从x-forwarded-for里获取,但是tcp请求就需要请求发起方携带prox头,不然nginx会返回400错误。

应用程序机器配置

程序中可以使用suerpsocket包,SuperSocket 是一个用于 .NET 的高性能、可扩展的套接字服务器应用程序框架。它为构建自定义网络通信应用程序提供了强大的架构,支持包括 TCP、UDP 和 WebSocket 在内的多种协议。它2.0中还支持ProxyProtocol协议的支持。

代码在程序中的位置:SuperSocket.Connection/ConnectionBase

总结

以上就是Nginx配置proxy protocol代理获取真实ip的全过程的详细内容,更多关于Nginx配置proxy protocol获取真实ip的资料请关注脚本之家其它相关文章!

相关文章

  • Nginx工作模式及代理配置的使用细节

    Nginx工作模式及代理配置的使用细节

    这篇文章主要为大家介绍了Nginx工作模式及代理配置的使用细节,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • nginx根据二级目录转发服务以及带/和不带/的区别说明

    nginx根据二级目录转发服务以及带/和不带/的区别说明

    Nginx使用proxy_pass进行二级目录转发时,配置中的斜杠(/)影响路径的处理方式:带斜杠表示绝对路径,不带斜杠表示相对路径,具体转发到后端服务的URL会有所不同
    2024-12-12
  • nginx配置后访问出现白屏的问题解决

    nginx配置后访问出现白屏的问题解决

    本文主要介绍了nginx配置后访问出现白屏
    2024-06-06
  • Nginx配置支持IPV6地址的方法示例

    Nginx配置支持IPV6地址的方法示例

    本文主要介绍了如何搭建并测试Nginx以支持IPV6地址的过程,包括下载安装包、编译安装、配置和启动Nginx等步骤,同时,文章还解决了在测试IPV6地址时遇到的两个问题:curl解析错误和阿里云、腾讯云IPV6地址配置问题
    2024-11-11
  • nginx中的proxy_redirect的使用案例详解

    nginx中的proxy_redirect的使用案例详解

    proxy_redirect 该指令用来修改被代理服务器返回的响应头中的Location头域和“refresh”头域,这篇文章主要介绍了nginx中的proxy_redirect的使用案例详解,需要的朋友可以参考下
    2024-06-06
  • nginx处理http请求实例详解

    nginx处理http请求实例详解

    这篇文章主要介绍了nginx处理http请求实例详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • Nginx下ModSecurity模块安装的实现步骤

    Nginx下ModSecurity模块安装的实现步骤

    本文提供了在Nginx 1.28.0上安装ModSecurity v3的完整教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • 深入理解nginx的access.log文件

    深入理解nginx的access.log文件

    NGINX软件会把每个用户访问网站的日志记录到指定的日志文件里,供网站者分析用户的浏览行为,本文主要介绍了nginx的access.log文件,感兴趣的可以了解一下
    2023-09-09
  • nginx重写和重定向关系与配置方式

    nginx重写和重定向关系与配置方式

    这篇文章主要介绍了nginx重写和重定向关系与配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 解决httpd占用80端口导致Nginx启动失败报错的解决办法

    解决httpd占用80端口导致Nginx启动失败报错的解决办法

    今天在建自己小网站时启动Nginx时,发现其报下列错误,意思是因为80端口被占用导致Nginx启动失败,所以本文小编给大家介绍介绍如何解决解决httpd占用80端口导致Nginx启动不成功报nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    2023-11-11

最新评论