当前位置: 首页 > news >正文

后端nginx使用set_real_ip_from获取用户真实IP

         随着nginx的迅速崛起,越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速,但是随之也遇到一个问题:nginx如何获取用户的真实IP地址.

前言:Nginx ngx_http_realip_module

官方说明:

Module ngx_http_realip_module

例子1

        realip模块的作用是:当本机的nginx处于一个反向代理的后端时获取到真实的用户IP

        如果没有realip模块,nginx的access_log里记录的IP会是反向代理服务器的IP,PHP中$_SERVER[‘REMOTE_ADDR’]的值也是反向代理的IP。

        而安装了realip模块,并且配置正确,就可以让nginx日志和php的REMOTE_ADDR都变成真实的用户IP。

举一个最简单的例子,网络架构如图:

        如果不做任何配置,后端web服务器nginx日志里记录的IP将会是10.10.10.10,这个时候我们增加如下nginx配置:

set_real_ip_from 10.10.10.10;

real_ip_header X-Forwarded-For;

  • set_real_ip_from指令是告诉nginx,10.10.10.10是我们的反代服务器(信任服务器,记住这个名词,下面会提到),不是真实的用户IP,
  • real_ip_header则是告诉nginx真正的用户IP是存在X-Forwarded-For请求头中(对X-Forwarded-For不了解的同学请自行百度)。

        重新加载nginx配置之后,就可以看到nginx日志里记录的IP就是123.123.123.123了,php里的REMOTE_ADDR也是123.123.123.123。

        realip模块还提供了另外一个指令real_ip_recursive,可以用来处理更加复杂的情况,架构如图:

        这个时候如果还用上面的配置,后端nginx的日志里显示的IP就变成了192.168.1.10了,这个时候就需要real_ip_recursive这个指令了。

set_real_ip_from 10.10.10.10;

set_real_ip_from 192.168.1.10;

real_ip_header X-Forwarded-For;

real_ip_recursive on;

官网文档对于real_ip_recursive指令的解释十分拗口,看了老半天才明白。

首先要明确一点,realip模块生效的前提是:直接连接nginx的ip是在set_real_ip_from中指定的。

  • 当real_ip_recursive为off时,nginx会把real_ip_header指定的HTTP头中的最后一个IP当成真实IP
  • 当real_ip_recursive为on时,nginx会把real_ip_header指定的HTTP头中的最后一个不是信任服务器的IP当成真实IP

        在这个例子中,当请求到达后端web服务器时,X-Forwarded-For应该是123.123.123.123, 192.168.1.10。

        如果real_ip_recursive为off,nginx取X-Forwarded-For的最后一个IP也就是192.168.1.10作为真实IP。

        如果real_ip_recursive为on,由于192.168.1.10是信任服务器IP,所以nginx会继续往前查找,发现123.123.123.123不是信任服务器IP,就认为是真实IP了。

例子2:

实例环境:

  • 用户IP 120.22.11.11
  • CDN前端 61.22.22.22
  • CDN中转 121.207.33.33
  • 公司NGINX前端代理 192.168.50.121(外网121.207.231.22)

1、使用CDN自定义IP头来获取

假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下:

proxy_set_header remote-user-ip $remote_addr;

后端PHP代码getRemoteUserIP.php

<?php
$ip = getenv("HTTP_REMOTE_USER_IP"); 
echo $ip;
?>

访问getRemoteUserIP.php,结果如下:

120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳

2、通过HTTP_X_FORWARDED_FOR获取IP地址

        一般情况下CDN服务器都会传送HTTP_X_FORWARDED_FOR头,这是一个ip串,后端的真实服务器获取HTTP_X_FORWARDED_FOR头,截取字符串第一个不为unkown的IP作为用户真实IP地址, 例如:
        120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121(用户IP,CDN前端IP,CDN中转,公司NGINX代理)
getFor.php

<?php
$ip = getenv("HTTP_X_FORWARDED_FOR");
echo $ip;
?>

访问getFor.php结果如下:

120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121

如果你是php程序员,你获取第一个不为unknow的ip地址,这边就是120.22.11.11.

3.使用nginx自带模块realip获取用户IP地址

安装nginx之时加上realip模块,我的参数如下:

./configure --prefix=/usr/local/nginx-1.4.1 --with-http_realip_module

真实服务器nginx配置

server {listen 80;server_name www.zcy.com;access_log /data/logs/nginx/www.ttlsa.com.access.log main;index index.php index.html index.html;root /data/site/www.ttlsa.com;location /{root /data/site/www.ttlsa.com;}location = /getRealip.php{set_real_ip_from 192.168.50.0/24;set_real_ip_from 61.22.22.22;set_real_ip_from 121.207.33.33;set_real_ip_from 127.0.0.1;real_ip_header X-Forwarded-For;real_ip_recursive on;fastcgi_pass unix:/var/run/phpfpm.sock;fastcgi_index index.php;include fastcgi.conf;}
}

getRealip.php内容

<?php
$ip = $_SERVER['REMOTE_ADDR'];
echo $ip;
?>

访问www.ttlsa.com/getRealip.php,返回:

120.22.11.11

注释 real_ip_recursive on或者 real_ip_recursive off:

访问www.ttlsa.com/getRealip.php,返回:

121.207.33.33

很不幸,获取到了中继的IP, real_ip_recursive的效果看明白了吧.

  • set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
  • real_ip_header:从哪个header头检索出要的IP地址
  • real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
 120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121

在real_ip_recursive on的情况下

        61.22.22.22,121.207.33.33,192.168.50.121都出现在set_real_ip_from中,仅仅120.22.11.11没出现,那么他就被认为是用户的ip地址,并且赋值到remote_addr变量。
        在real_ip_recursive off或者不设置的情况下192.168.50.121出现在set_real_ip_from中,  排除掉,接下来的ip地址便认为是用户的ip地址

如果仅仅如下配置:

set_real_ip_from 192.168.50.0/24;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

访问结果如下:

121.207.33.33

4、三种在CDN环境下获取用户IP方法总结

4.1 CDN自定义header头

  • 优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
  • 缺点:需要CDN厂商提供

4.2 获取forwarded-for头

  • 优点:可以获取到用户的IP地址
  • 缺点:程序需要改动,以及用户IP有可能是伪装的

4.3 使用realip获取

  • 优点:程序不需要改动,直接使用remote_addr即可获取IP地址
  • 缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段

参考

后端nginx使用set_real_ip_from获取用户真实IP-CSDN博客

nginx之ngx_http_realip_module使用详解-腾讯云开发者社区-腾讯云

相关文章:

后端nginx使用set_real_ip_from获取用户真实IP

随着nginx的迅速崛起&#xff0c;越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速&#xff0c;但是随之也遇到一个问题&#xff1a;nginx如何获取用户的真实IP地址. 前言&#xff1a;Nginx ngx_http_realip_module…...

python使用leveldb

LevelDB 是由 Google 开发的一个快速的键值存储库&#xff0c;提供了一个持久化的有序映射&#xff0c;非常适合用作简单的高性能数据库。 安装 Plyvel 首先&#xff0c;使用 pip3 来安装 plyvel pip3 install plyvel基本用法 接下来&#xff0c;介绍使用 plyvel 来操作 Le…...

hcs部署场景

HCS售前规划&#xff1a; eDesigner&#xff1f; SCT报价器&#xff1f; 将eDesigner项目导出到SCT后&#xff0c;报价器会自动对硬件进行配置及报价。 HCS规划设计工具 - HUAWEI CLOUD Stack Designer 用于支撑HUAWEI CLOUD Stack解决方案项目LLD设计&#xff0c;提升设计效率…...

从零开始学习的ai教程视频,如何入手?

个人认为小白想零基础学习ai应该从理论和实操两个方面入手。理论是支撑实践的前提&#xff0c;只有以一种全局观角度了解ai才能实现从熟练使用ai到有自我意识的用ai创作。 接下来将会简单介绍一些理论免费学习网站和软件&#xff08;一笔带过&#xff0c;不重点&#xff09;&a…...

【精选】发布应用到应用商店的基本介绍

摘要 本文旨在介绍如何在各大应用商店发布应用&#xff0c;包括市场选择、准备材料、上架步骤以及常见被拒原因及解决方法。通过详细的步骤和经验分享&#xff0c;帮助开发者顺利将应用推向市场。 引言 随着移动应用市场的不断发展&#xff0c;越来越多的开发者希望将他们的…...

LC 572.另一棵树的子树

572. 另一棵树的子树 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tr…...

PPT 操作

WPS 版式 PPT中&#xff0c;巧妙使用母版&#xff0c;可以提高效率。 双击母版&#xff0c;选择其中一个版式&#xff0c;插入装饰符号。 然后选择关闭。 这个时候&#xff0c;在该版式下的所有页面&#xff0c;就会出现新加入的符号。不在该版式下的页面&#xff0c;不会出现…...

python项目练习——19、单词计数器

这个项目允许用户输入一段文本,然后统计其中每个单词出现的次数,并按照出现次数从高到低进行排序显示。它涉及到字符串处理、数据结构和用户界面设计等方面的技术。 示例: import tkinter as tk # 导入 Tkinter 库 from collections import Counter # 导入计数器工具类 c…...

单链表专题

文章目录 目录1. 链表的概念及结构2. 实现单链表2.1 链表的打印2.2 链表的尾插2.3 链表的头插2.4 链表的尾删2.5 链表的头删2.6 查找2.7 在指定位置之前插入数据2.8 在指定位置之后插入数据2.9 删除pos节点2.10 删除pos之后的节点2.11 销毁链表 3. 链表的分类 目录 链表的概念…...

js把数组中的某一项移动到第一位

在JavaScript中&#xff0c;如果你要将数组中的某一项移动到第一位&#xff0c;你可以使用以下几种方法。 假设我们有一个数组arr&#xff0c;并且想要将位于索引index的项移动到数组的第一个位置&#xff1a; let arr [1, 2, 3, 4, 5]; let index 2; // 假设我们想将3&…...

MyBatis如何实现分页

文章目录 MyBatis分页方式对比使用数据库厂商提供的分页查询语句通过自定义 SQL 实现分页逻辑1. 使用 RowBounds 实现分页2. 使用 PageHelper 实现分页 数组分页使用 MyBatis-Plus 进行分页MyBatis物理分页和逻辑分页MyBatis 手写一个 拦截器分页 在 MyBatis 中实现分页通常有两…...

在 Python 编程中,面向对象编程的核心概念包括哪些部分?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 在 Python 编程中&#xff0c;面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;的核心概念主要包括类&#xff08;Class&#xff09;、对象&#xff08;Object&#x…...

elementui树形组件自定义高亮颜色

1、需求描述&#xff1a;点击按钮切换树形的章节&#xff0c;同时高亮 2、代码实现 1&#xff09;style样式添加 <style> .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {background-color: #81d3f8 !important; //高亮颜色colo…...

富格林:技巧抵抗曝光虚假套路

富格林悉知&#xff0c;黄金具备独特的优势吸引着众多投资者的目光&#xff0c;在现货黄金市场也被认为是一条潜力无限的盈利之道。但我们要明白风险与盈利是相辅相成的&#xff0c;因此在这复杂的市场中我们必须利用技巧来抵抗曝光的虚假套路。下面富格林将给大家分享一些正确…...

24年权威数学建模报名通知汇总(含妈妈杯、国赛、美赛、电工杯、数维杯、五一数模、深圳杯......)

1、MathorCup比赛 报名时间&#xff1a;2024年4月11日中午12点&#xff08;周四&#xff09; 比赛开始时间&#xff1a;2024年4月12日上午8时&#xff08;周五&#xff09; 比赛结束时间&#xff1a;2024年4月16日上午9时&#xff08;周二&#xff09; 报名费用&#xff1a…...

【C语言自定义类型之----结构体,联合体和枚举】

一.结构体 1.结构体类型的声明 srruct tag {nemer-list;//成员列表 }varible-list;//变量列表结构体在声明的时候&#xff0c;可以不完全声明。 例如&#xff1a;描述一个学生 struct stu {char name[20];//名字int age;//年龄char sex[20];//性别 };//分号不能省略2.结构体…...

[Java基础揉碎]StringBuffer类 StringBuild类

目录 StringBuffer类 介绍 继承图 String VS StringBuffer StringBuffer的构造器 String和StringBuffer的转换 StringBuffer类常见方法 测试题 StringBuild类 基本介绍 继承图 String、StringBuffer 和StringBuilder的比较 通过字符串拼接循环测试可以看到各自的性…...

Android Studio修改项目包名

1.第一步&#xff0c;项目结构是这样的&#xff0c;3个包名合在了一起&#xff0c;我们需要把每个包名单独展示出来 2.我们点击这个 取消选中后的包名结构是这样的&#xff0c;可以看到&#xff0c;包名的每个文件夹已经展示分开了&#xff0c;现在我们可以单独对每个包名文件夹…...

c++语言增强的地方

目录 1.对全局变量的检测能力 2.struct类型增强 3.c中所有变量和函数都必须有类型 4.c中新增的bool类型 5.三目运算符的加强 6.const的增强 7.对枚举的增强 1.对全局变量的检测能力 C语言中同时定义两个相同的全局变量编译器并不会报错&#xff0c;而c中就会报重定义错…...

评论发布完整篇(react版)

此篇文章阐述评论的最新、最热之间的tab标签切换&#xff08;包括当前所在tab标签的高亮显示问题&#xff09;&#xff1b;当前评论的删除&#xff1b;除此之外还延伸了用户的评论实时发布功能。其中最新tab标签所展示的内容是根据当前评论点赞数来进行排序&#xff0c;点赞数量…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...