利用Nginx正向代理实现局域网电脑访问外网
引言
在网络环境中,有时候我们需要让局域网内的电脑访问外网,但是由于网络策略或其他原因,直接访问外网是不可行的。这时候,可以借助 Nginx 来搭建一个正向代理服务器,实现局域网内电脑通过 Nginx 转发访问外网的需求。
在工作中我遇到了一个类似的情况:在公司网络中,由于管理要求,局域网内的电脑不能直接访问外网。但是,有时候我们需要让局域网内的电脑能够访问外网上的某个网站,这时候就需要用到正向代理。本文将介绍如何配置 Nginx 实现这一功能。
准备工作
首先,我们需要一台可以访问外网的服务器,例如一台服务器、电脑或者虚拟机。确保该服务器已经安装了 Nginx,并且网络配置正确。
我这里是有一台服务器是可以正常访问外网的(IP:192.168.0.10),同时局域网内的其他电脑也可以访问这台服务器。
修改nginx.conf
worker_processes 1;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 正向代理配置内容server {listen 9000; # 监听端口server_name localhost;set $url "proxy_server_doman_or_ip"; # 设置代理的域名或IP变量,这里替换成自己需要代理的网站location / {proxy_pass http://$url:8082; # 将请求转发到由 $url 变量表示的地址。}}
}
重启nginx,打开局域网电脑测试访问:192.168.0.10:9000,网页跳转成功。不就是请求转发嘛,so easy!
问题解决?如果这么简单我就不写这篇文章了😄
果然第二天就出问题了,有同事反馈网站进不去了。我想不可能吧,一测试果然不行。果断查阅了一下资料,找到问题原因:nginx在进行域名转发时会先把域名解析成IP保存在内存中,后面的访问都是通过IP直接访问,如果目标网站的 IP 地址发生变化,我们的代理就会失效。
找到原因就好办了,添加域名解析功能嘛
域名解析
为了解决 IP 地址变化的问题,我们可以使用域名解析来动态获取目标网站的 IP 地址。直接奉上完整配置,修改 Nginx 配置如下:
# 设置Nginx启动一个工作进程,这是Nginx的一个核心设置,它决定了Nginx会使用多少个工作进程来处理客户端请求。
worker_processes 1; # 配置定义了Nginx如何处理事件,例如连接请求,数据传输等
events {worker_connections 1024; # 定义了每个工作进程允许的最大并发连接数。
}# HTTP模块的配置块,包含了HTTP服务器的一般配置
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 正向代理配置内容server {listen 9000; # 监听端口server_name localhost;# 设置DNS解析器的地址为8.8.8.8,并且设置了解析器的缓存时间为300秒(这样每隔300s就会重新解析一次)。ipv6=off 是关闭IPv6的解析支持。resolver 8.8.8.8 valid=300 ipv6=off; resolver_timeout 3s; # 设置解析DNS的超时时间为3秒proxy_read_timeout 60s;proxy_send_timeout 60s;proxy_connect_timeout 60s;set $url "proxy_server_doman_or_ip"; # 设置代理的域名或IP变量,这里替换成自己需要代理的网站location / {proxy_pass http://$url:9000; # 将请求转发到由 $url 变量表示的地址。9000是目标网站的端口。proxy_buffers 256 4K; # 设置用于缓存后端响应的缓冲区大小为256个,每个大小为4K。proxy_max_temp_file_size 0; # 设置Nginx暂存响应数据的最大临时文件大小为0,即不使用临时文件。proxy_cache_valid 200 302 1m; # 针对状态码为200和302的响应,设置缓存有效期为1分钟。proxy_cache_valid 301 1h; # 针对状态码为301的响应,设置缓存有效期为1小时。proxy_cache_valid any 1m; # 对于其他任何响应状态码,设置缓存有效期为1分钟。}}
}
重启nginx,问题解决。到这里,正向代理功能就实现了。如果只想实现正向代理功能看到这里就可以了。后面是我在遇到问题时的一些调试经验技巧!
转发代理调试
我在实现代理后,发现正向代理响应的速度非常慢有时候需要一分钟才能响应结果。但有时候又很快。就好奇为啥会这样,为了方便调试和监控,我设置添加了Nginx 的访问日志。
修改 Nginx 配置如下:
# 设置日志记录格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"' 'upstreamIP: $upstream_addr' 'upgrade: $http_upgrade';# 正向代理配置内容server {listen 9000; # 监听端口server_name localhost;# 设置DNS解析器的地址为8.8.8.8,并且设置了解析器的缓存时间为300秒(这样每隔300s就会重新解析一次)。ipv6=off 是关闭IPv6的解析支持。resolver 8.8.8.8 valid=300 ipv6=off; resolver_timeout 3s; # 设置解析DNS的超时时间为3秒proxy_read_timeout 60s;proxy_send_timeout 60s;proxy_connect_timeout 60s;set $url "proxy_server_doman_or_ip"; # 设置代理的域名或IP变量,这里替换成自己需要代理的网站location / {proxy_pass http://$url:9000; # 将请求转发到由 $url 变量表示的地址。9000是目标网站的端口。proxy_buffers 256 4K; proxy_max_temp_file_size 0; proxy_cache_valid 200 302 1m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m; access_log logs/proxy/access.log main; # 定义了访问日志的路径和格式。error_log logs/proxy/error.log; # 定义了错误日志的路径}}
这样,Nginx 将会在nginx项目下的 logs/proxy/access.log 文件中记录所有代理转发日志。
日志信息:
192.168.0.28 - - [27/Feb/2024:17:02:03 +0800] “GET /prod-api/system/todo/listAll?pageNum=1&pageSize=10&active=true HTTP/1.1” 200 64 “http://192.168.20.2:8082/user-task/todo” “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0” "-"upstreamIP: 182.148.159.30:8082
192.168.0.28 - - [27/Feb/2024:17:02:03 +0800] “GET /prod-api/process/business/listAll?pageNum=1&pageSize=10&active=true HTTP/1.1” 200 979 “http://192.168.20.2:8082/user-task/todo” “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0” "-"upstreamIP: 182.148.159.30:8082
192.168.0.28 - - [27/Feb/2024:17:02:06 +0800] “GET /prod-api/system/user/select HTTP/1.1” 499 0 “http://192.168.20.2:8082/login?redirect=%2Findex” “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0” "-"upstreamIP: 172.16.30.6:8082
通过日志信息可以看到,请求转发后的upstreamIP有两个不同的IP:182.148.159.30和172.16.30.6,说明请求被转发到了两个不同的IP,当请求IP为182.148.159.30时,响应正常;当请求IP为172.16.30.6时,响应失败导致等待。
发现这个情况后,我也是很疑惑为啥会将域名解析出两个IP,第一反应是域名解析错误,为了验证我将DNS解析的服务器换成了离我最近的四川电信服务器:61.139.2.69,测试发现结果也是一样的。虽然感觉解析是没有问题的,保险起见我还是自己在网上通过解析网站测试了一下域名解析的结果:结果显示域名确实绑定了两个IP,一个是正常的一个是不行的。
然后我就联系我们这个域名对应网站的负责人,得出的结果就是他们确实绑定了两个IP,有一个IP是绑定的内网IP,所以才导致外网请求时失效。
失败的原因:nginx获取解析后的IP是通过轮询往IP转发请求,如果轮询到内网IP就会导致请求失败。
解决办法:
-
手动选择IP地址:在Nginx配置中,你可以手动指定代理的目标IP地址,而不是使用解析出的IP地址。这样可以避免将请求发送到内网IP。
-
使用域名解析出的IP地址进行请求:你可以通过解析域名获取到的IP地址列表,然后使用一些方法(比如按照某种规则选择IP地址)来保证请求不会发送到内网IP地址。
-
使用nginx的upstream模块进行负载均衡:通过upstream模块,你可以指定多个代理服务器,然后使用一定的负载均衡策略,比如轮询、权重等,来分配请求到不同的服务器。在这里,你可以手动配置upstream模块,指定外网IP,而不包括内网IP。
-
修改DNS设置:联系网站负责人,修改域名解析,只将外网IP绑定到域名上,而不包括内网IP。
你们猜我最后咋解决的???
必须是第四条啊!!!
相关文章:

利用Nginx正向代理实现局域网电脑访问外网
引言 在网络环境中,有时候我们需要让局域网内的电脑访问外网,但是由于网络策略或其他原因,直接访问外网是不可行的。这时候,可以借助 Nginx 来搭建一个正向代理服务器,实现局域网内电脑通过 Nginx 转发访问外网的需求…...

SpringMVC03、HelloSpring
3、HelloSpring 3.1、配置版 新建一个Moudle , springmvc-02-hello , 添加web的支持! 确定导入了SpringMVC 的依赖! 配置web.xml , 注册DispatcherServlet <?xml version"1.0" encoding"UTF-8…...
IOS面试题object-c 1-10
1、简述Object-C的理解与特性? OC 作为一门 面向对象 的语言,自然具有面向对象的语言特性:封装、继承、多态。 它既具有 静态语言的特性(如C),又有 动态语言的效率(动态绑定、动态加载等&#…...

原生JavaScript,根据后端返回扁平JSON动态【动态列头、动态数据】生成表格数据
前期准备: JQ下载地址: https://jquery.com/ <!DOCTYPE html> <html><head><meta charset"utf-8"><title>JSON动态生成表格数据,动态列头拼接</title><style>table {width: 800px;text-align: cen…...

hadoop报错:HADOOP_HOME and hadoop.home.dir are unset. 解决方法
参考:https://blog.csdn.net/weixin_45735242/article/details/120579387 解决方法 1.下载apache-hadoop-3.1.0-winutils-master 官网下载地址: https://github.com/s911415/apache-hadoop-3.1.0-winutils win配置系统环境: 然后重启idea…...

基于Springboot的高校物品捐赠管理系统(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的高校物品捐赠管理系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系…...
【硬件工程师面经整理29_FPGA】
文章目录 1 nand nor的区别,速度差异的原因?2 nand驱动方式?3 异步信号处理方法4 异步FIFO的深度是如何计算的5 异步复位同步释放的优缺点6 问了FPGA的内部组成?7 LE中查找表的实现原理?8 IOB的主要组成部分࿱…...

Ping工作原理
文章目录 目的ping网络协议 OSIICMP什么是ICMP作用功能报文类型查询报文类型差错报文类型ICMP 在 IPv4 和 IPv6 的封装ICMP 在 IPv4 协议中的封装ICMP 在 IPv6 协议中的封装ICMP 头部日常ping 排除步骤ping 查询报文使用code扩展目的 本文主要是梳理ping的工作原理- 揭开 ICMP…...
python调用jar中java方法 静态类为例
java package test;public class test {// run方法返回当前脚本路径public static String runV1(String s) {return "log: " System.getProperty(s);}}python import jpype from jpype import * import osif __name__ "__main__":print(os.environ[JAV…...

tcp服务器客户端通信(socket编程)
目录 1.编程流程 2.代码演示 2.1 服务器代码 2.2 客户端代码 3.注意 3.1 ping命令 3.2 netstat命令 3.3 为什么memset? 3.4 哪个会阻塞? 3.5 显示连接信息 1.概念 1.1 编程流程 1.2 connect与listen connect方法执行后,会进行三次握手,建立连…...
chatgpt 镜像站汇总
无需登录直接可用的: ChatGPT Web - GPT-3.5-16k免费使用,吐字块,每日20次数,不需要登陆思研AI - 免费时限制每小时6次提问https://chatgpt.nicelinks.site/ - 免费使用频次有限制抱歉,站点已暂停 - 免费由开发者提供A…...
java面试题:为什么 SQL 语句不要过多的 join?
1 考察点 面试官主要想了解面试者对于 SQL 优化的理解以及在实际工作中如何处理 SQL 语句的性能问题。要回答好这个问题,只需要了解 join 操作会带来哪些影响,而这些影响对程序产生什么样的影响就行了。这个问题就是面试官想考察我们是不是平日里善于积…...

JAVA实战开源项目:学生日常行为评分管理系统(Vue+SpringBoot)
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.2.1 登录注册模块2.2.2 用户管理模块2.2.3 评分项目模块2.2.4 评分数据模块2.2.5 数据字典模块 2.3 可行性设计2.4 用例设计2.5 数据库设计2.5.1 整体 E-R 图2.5.2 用户2.5.3 评分项目2.5.4 评分数据2.5.…...

力扣-[700. 二叉搜索树中的搜索]
递归法 确定递归函数的参数和返回值 递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。 代码如下: public TreeNode searchBST(TreeNode root, int val) 确定终止条件 如果root为空,返回null,…...

Hive-源码分析一条hql的执行过程
一、源码下载 下面是hive官方源码下载地址,我下载的是hive-3.1.3,那就一起来看下吧 https://dlcdn.apache.org/hive/hive-3.1.3/apache-hive-3.1.3-src.tar.gz 二、上下文 <Hive-源码带你看hive命令背后都做了什么>博客中已经讲到了hive命令执行…...

软考71-上午题-【面向对象技术2-UML】-UML中的图2
一、用例图 上午题,考的少;下午题,考的多。 1-1、用例图的定义 用例图展现了一组用例、参与者以及它们之间的关系。 用例图用于对系统的静态用例图进行建模。 可以用下列两种方式来使用用例图: 1、对系统的语境建模;…...
使用hashmap优化时间复杂度,leetcode1577
1577. 数的平方等于两数乘积的方法数 已解答 中等 相关标签 相关企业 提示 给你两个整数数组 nums1 和 nums2 ,请你返回根据以下规则形成的三元组的数目(类型 1 和类型 2 ): 类型 1:三元组 (i, j, k) ÿ…...

3、设计模式之工厂模式1
工厂模式是什么? 工厂模式是一种创建者模式,用于封装和管理对象的创建,屏蔽了大量的创建细节,根据抽象程度不同,主要分为简单工厂模式、工厂方法模式以及抽象工厂模式。 简单工厂模式 看一个具体的需求 看一个…...

一个Promise全新API
1. 资讯速览 最近,Promise 新出了一个方法,已经进入 Stage 3 (候选阶段) ,相信很快就能达到 Stage 4 (完成阶段),并在项目中广泛使用。 这个方法就是 Promise.withResolvers。它是…...

【力扣hot100】刷题笔记Day25
前言 这几天搞工作处理数据真是类似我也,还被老板打电话push压力有点大的,还好搞的差不多了,明天再汇报,赶紧偷闲再刷几道题(可恶,被打破连更记录了)这几天刷的是动态规划,由于很成…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...

Linux 内核内存管理子系统全面解析与体系构建
一、前言: 为什么内存管理是核心知识 内存管理是 Linux 内核最核心也最复杂的子系统之一,其作用包括: 为软件提供独立的虚拟内存空间,实现安全隔离分配/回收物理内存资源,维持系统稳定支持不同类型的内存分配器,最优…...