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

nginx(四):如何在 Nginx 中配置以保留真实 IP 地址

如何在 Nginx 中配置以保留真实 IP 地址

  • 1、概述
  • 2、nginx配置示例
    • 2.1、配置说明
    • 2.2、客户端获取真实IP
      • 2.2.1、代码说明
  • 3、插曲
  • 4、总结

大家好,我是欧阳方超,可以我的公众号“欧阳方超”,后续内容将在公众号首发。在这里插入图片描述

1、概述

当使用nginx作为反向代理服务器时,客户端的请求会经过nginx转发到后端服务器。在这过程中,客户端的IP可能会被覆盖,导致后端在获取请求的IP时只能获取到nginx所在机器的IP。为了保留客户端的真实IP,nginx提供了X-Real-IP 和 X-Forwarded-For 两个 HTTP 头信息。

2、nginx配置示例

在nginx的配置文件中需要添加以下内容:

server {listen 80;location / {proxy_pass http://backend_server;  # 替换为具体的后端服务器地址proxy_set_header Host $host;  # 设置原始请求的 Host 头proxy_set_header X-Real-IP $remote_addr;  # 设置真实客户端 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 添加 X-Forwarded-For 头}
}

2.1、配置说明

proxy_pass: 指定请求转发到的后端服务器地址。
proxy_set_header Host $host: 将请求的 Host 头设置为原始请求的 Host。
proxy_set_header X-Real-IP $remote_addr: 将真实的客户端 IP 地址添加到 X-Real-IP 头中。这里的 $remote_addr 是 Nginx 的内置变量,代表直接连接的客户端 IP。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for: 将客户端 IP 地址附加到 X-Forwarded-For 头中。如果该头已经存在,则会在其后追加新的 IP 地址。

2.2、客户端获取真实IP

在后端应用中,需要从请求中读取这些头信息以获取真实的客端IP。以下为示例代码:

import javax.servlet.http.HttpServletRequest;public class NetworkUtils {public static String getClientIp(HttpServletRequest request) {String ip = request.getHeader("X-Real-IP");if (ip == null || ip.isEmpty()) {ip = request.getHeader("X-Forwarded-For");if (ip != null && ip.contains(",")) {ip = ip.split(",")[0];  // 获取第一个 IP}}return (ip != null && !ip.isEmpty()) ? ip : request.getRemoteAddr();}
}

2.2.1、代码说明

获取 X-Real-IP: 首先检查 X-Real-IP 头,如果存在则返回该值。
获取 X-Forwarded-For: 如果 X-Real-IP 不存在,则检查 X-Forwarded-For。如果它包含多个 IP 地址(逗号分隔),则取第一个,通常这是原始客户端的 IP。
回退到 getRemoteAddr(): 如果以上两个头都不存在,则使用 request.getRemoteAddr() 获取直接连接的 IP 地址。

3、插曲

由于我的nginx设置了https请求方式(之前文章提到过),当前端以http方式请求接口时,请求被重定向到 HTTPS ,此时浏览器会发起一个新的请求。确保 HTTPS 服务器(如 Nginx)也正确配置了 CORS。确保 Nginx 的配置中没有阻止或修改 CORS 头。可以在 Nginx 的 HTTPS 配置中添加类似以下内容:

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization';

接着前端尝试访问接口,发现报了405错误(method not allowed),这是因为 301/302 重定向默认会将 POST 请求转换为 GET 请求。这是 HTTP 协议的标准行为。解决方法是使用307/308重定向。307是 临时重定向,保持原有的 HTTP 方法, 308是永久重定向,保持原有的 HTTP 方法。
完整nginx配置如下:


#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '#                  '$status $body_bytes_sent "$http_referer" '#                  '"$http_user_agent" "$http_x_forwarded_for"';#access_log  logs/access.log  main;sendfile        on;#tcp_nopush     on;#keepalive_timeout  0;keepalive_timeout  65;#gzip  on;server {listen 80;server_name localhost;#return 301 https://$host$request_uri;#rewrite ^ https://$host$request_uri permanent;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization';#rewrite ^(.*)$ https://$host$1 permanent;return 308 https://$host$request_uri;}server {listen       443 ssl;#listen       80;server_name  localhost;ssl_certificate /usr/local/nginx/ssl/demo.crt; #证书路径ssl_certificate_key /usr/local/nginx/ssl/demo.key; #私钥路径ssl_protocols TLSv1.2 TLSv1.3;  # 启用的TLS版本ssl_ciphers HIGH:!aNULL:!MD5;  # 加密套件#charset koi8-r;#access_log  logs/host.access.log  main;location / {root   html;index  index.html index.htm;}location /test/ {proxy_pass http://192.168.25.34:3010/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}#error_page  404              /404.html;# redirect server error pages to the static page /50x.html#error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}
}

另外,下图展示了浏览器确实发出了两个请求:
在这里插入图片描述

4、总结

安全性: 当处理来自不受信任源的 X-Forwarded-For 和 X-Real-IP 时,需要谨慎,因为这些头可以被伪造。确保应用只在可信任的代理后面运行。
多级代理: 如果有多个代理服务器,确保每个代理都正确设置这些头信息,以便最终服务器能够获得真实的客户端 IP。
通过以上配置和代码示例,可以有效地在 Nginx 中保留并传递真实的客户端 IP 地址。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。

相关文章:

nginx(四):如何在 Nginx 中配置以保留真实 IP 地址

如何在 Nginx 中配置以保留真实 IP 地址 1、概述2、nginx配置示例2.1、配置说明2.2、客户端获取真实IP2.2.1、代码说明 3、插曲4、总结 大家好,我是欧阳方超,可以我的公众号“欧阳方超”,后续内容将在公众号首发。 1、概述 当使用nginx作为…...

docker对nginx.conf进行修改后页面无变化或页面报错

可能是因为没有重启nginx容器 可以执行 docker restart nginx 重启nginx试试 引入了其他的配置文件 本人安装的是docker默认的nginx,自带了一个default.conf的配置文件,并且在nginx.conf中还引入了这个文件,后面我还对nginx.conf添加了一个…...

SpringCloudGateway — 网关路由

Spring Cloud Gateway 是 Spring 提供的一个高效、灵活的 API 网关解决方案,基于 Spring 5、Spring Boot 2 和 Project Reactor,具有高并发和低延迟的特点。它用于在微服务架构中对外提供统一的入口,处理请求的路由、过滤、负载均衡等功能。 …...

docker pull 拉取镜像失败,使用Docker离线包

1、登录并注册Github,然后在Github中搜索并打开“wukongdaily/DockerTarBuilder” 项目,在该项目主页点击“Fork”。 然后点 “Create Fork”,将项目创建到自己的Github主页。 2、接着在自己创建过来的这个项目中点击“Actions” 3、然后…...

轻松理解操作系统 - 轻松了解 inode 是如何管理文件的

Linux 由于其开源、比较稳定等特点统治了服务端领域。也因此,学习Linux 系统相关知识在后端开发等岗位中变得越来越重要,甚至可以说是必不可少的。 因为它的广泛应用,所以在程序员的日常工作和面试中,它都是经常出现的。它的开源特…...

go中Println和Printf的区别

Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 go中Println和Printf的区别 package mainimport ( "fmt" )//TIP To run your code, right-click the c…...

C++现代教程七之模块

优点 编译时间减少:模块消除了重复解析和编译头文件的需要,从而显著减少了编译时间。特别是在大型项目中,这一点尤为重要。更好的封装性:模块允许更严格的封装,可以明确地控制哪些符号对外可见。这有助于减少命名冲突和…...

AVLTree

1.AVL树的概念 二叉搜索树虽然可以提高查找的效率,但是如果数据有序或者接近有序,二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。为了解决该问题,于是就有了AVLTree。即当向二叉搜索树中插入…...

Java面向对象 C语言字符串常量

1. (1). package liujiawei;public class Phone {String brand;double price;public void call(){System.out.println("手机打电话");}public void play(){System.out.println("手机打游戏");} } public class phonetest {public…...

SpringBoot+Thymeleaf电商系统

> 这是一个基于SpringBootThymeleafBootstrap实现的简单电商系统。 > 实现了用户浏览、添加购物车、商品管理等功能,并支持响应式布局。 > 本项目适合JAVA初学者作为入门学习项目 一、部分界面演示 二、技术栈 技术栈中文描述Spring Boot快速开发框架…...

了解数据库并发产生的问题

在数据库管理系统中,并发控制是一个至关重要的方面。随着多个用户或进程同时访问和修改数据库中的数据,如果没有适当的并发控制机制,就可能导致数据不一致、丢失更新、脏读、不可重复读和幻读等问题。在单用户系统中,数据库操作是…...

openstack之guardian介绍与实例创建过程

运行特征 采集模块:扩展Ceilometer,采集存储网、业务网连通性、nova目录是否可读写; 收集模块:将采集到的数据存储到数据库中; 分析模块:根据采集的结果,分析各节点状态,并进行反向检…...

新一代跟踪器StrongSORT: Make DeepSORT Great Again论文解析—让 DeepSORT 再次伟大

新一代跟踪器StrongSORT: Make DeepSORT Great Again论文解析—让 DeepSORT 再次伟大 时间:2023年 机构:北京邮电大学 发表在:IEEE TRANSACTIONS ON MULTIMEDIA, VOL. 25, 2023 代码源码地址: pytorch版本:https://github.com/dyh…...

SAP ABAP开发学习——RFC

目录 RFC接口 定义 调用过程 RFC的通信 RFC通信情况 RFC接口系统 RFC的通信模式 RFC版本 RFC调用方式 Web Service接口 SAP创建Web Service示例 远程目标的维护 创建远程目标 外部系统访问设置 RFC的调用 RFC接口 定义 调用过程 RFC的通信 RFC通信情况 RFC接…...

Elasticsearch里的索引index是什么概念?(ChatGPT回答)

在 Elasticsearch(ES)中,索引(Index) 是一种数据结构,用来存储、组织和管理文档数据。它可以理解为数据库中的一张表,但有一些关键的不同之处。索引是 Elasticsearch 全文搜索引擎的核心概念之一…...

安全性测试

安全性测试评估系统在面对各种安全威胁时的防护能力和安全性的过程。以下是安全性测试的一些主要方面和方法: 1. 身份验证和授权测试 测试目标 确保系统能够正确验证用户的身份,并根据用户的权限授予相应的访问权限。测试方法 弱密码测试:尝…...

ComfyUI和Photoshop相结合,PS内实现:文生图,图生图,高清放大,局部重绘,面部修复,设计师福音

本文主要介绍:ComfyUI和Photoshop相结合,一个平台实现:图像生成,放大,局部重绘,面部修复,实时绘画 简直是设计师的福音。 主要包括: Photoshop 的安装以及插件的安装 Creative Cl…...

使用 map 和 reduce 提取对象数组中的 id 并组成新数组

在开发过程中,经常需要对 API 返回的数据进行处理,例如从对象数组中提取某些字段,并将它们组成新的数组。这里我们将介绍如何通过 JavaScript 的 map 和 reduce 方法来完成这一需求,并深入比较这两者的用法与适用场景。 需求&…...

Zero-Shot Relational Learning for Multimodal Knowledge Graphs

摘要 关系学习是知识表示领域,特别是知识图补全(KGC)领域的一项重要任务。虽然传统单模态环境下的关系学习已经得到了广泛的研究,但在多模态KGC环境下探索关系学习提出了不同的挑战和机遇。其中一个主要挑战是在没有任何相关训练…...

AUTOSAR COM 模块的主要功能导读以及示例

AUTOSAR COM 模块的主要功能 AUTOSAR COM 模块在车载系统中用于管理通信的中间层,主要功能包括: 信号传输与接收: • 提供信号打包和解包功能,将信号数据打包成协议数据单元(I-PDU)以便传输,或从接收到的…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂&#xff…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

如何在网页里填写 PDF 表格?

有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据&#xff…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...