3792 字
19 分钟
代理学习
2026-03-07

1 什么是代理#

1.1 代理的概念与定位#

代理服务器是客户端和服务器之间的”中间人”,所有的请求和响应都经它转手。根据代理站在哪一侧、服务于谁,分成正向代理和反向代理两种。

代理能做的事情很多:转发请求、缓存资源、过滤内容、做鉴权、负载均衡……核心思路都是——请求经过我这里,我就能对它做处理

1.2 代理的基本请求流程#

客户端 → 代理服务器 → 目标服务器
客户端 ← 代理服务器 ← 目标服务器

具体过程:

  1. 客户端按照代理协议与代理服务器建立连接
  2. 客户端告诉代理自己想访问哪里
  3. 代理去请求目标服务器
  4. 目标服务器返回响应给代理
  5. 代理把响应转发回客户端

2 正向代理(Forward Proxy)#

2.1 概念与工作原理#

正向代理站在客户端一侧,替客户端去访问服务器。

[客户端] → [正向代理] → [目标服务器]

客户端需要主动配置才能用(比如在系统或浏览器里设置代理地址),它完全知道代理的存在。目标服务器收到请求后,看到的来源是代理的 IP,不知道真实客户端是谁

一句话概括:正向代理为客户端服务,隐藏的是客户端身份。

2.2 核心特点#

特点说明
隐藏客户端目标服务器只看到代理 IP,不知道真实客户端
访问控制可以限制客户端能访问哪些目标(公司/学校内网常见)
缓存加速缓存热门资源,同样的请求第二次直接从缓存返回
突破限制绕过网络屏蔽,访问被封锁的资源

2.3 常见使用场景#

  • 科学上网:请求经代理转发出去,绕过封锁
  • 企业内网管控:员工统一走公司代理上网,便于审计和过滤
  • 内容过滤:学校图书馆屏蔽不良网站
  • 爬虫代理池:频繁切换代理 IP,防止被目标站封禁

3 反向代理(Reverse Proxy)#

3.1 概念与工作原理#

反向代理站在服务器一侧,替服务器接收客户端的请求,再转发给后端真实服务器。

→ [后端服务器 A]
[客户端] → [反向代理] → → [后端服务器 B]
→ [后端服务器 C]

客户端不需要任何配置,以为自己在直接访问目标服务器,完全感知不到反向代理的存在,也不知道真正的后端服务器是谁

一句话概括:反向代理为服务器服务,隐藏的是服务器身份。

3.2 核心特点#

特点说明
隐藏后端客户端不知道真实服务器的 IP 和端口
负载均衡把请求分发给多台后端服务器,均摊压力
安全防护过滤恶意请求,防 DDoS,充当 WAF 入口
SSL 卸载在代理层统一处理 HTTPS,后端只跑 HTTP
缓存静态资源图片、CSS、JS 由代理直接返回,不占用后端

3.3 常见使用场景#

  • Web 应用部署:Nginx 作反向代理,把 80/443 端口的请求转发给后面的 Node.js / Python / Java 服务
  • 负载均衡:多台应用服务器前面放一个反向代理统一调度
  • API 网关:统一入口做鉴权、限流、路由
  • CDN:全球各地部署反向代理节点,用户访问最近的节点

4 正向代理 vs 反向代理#

4.1 核心区别对比#

对比项正向代理反向代理
服务对象客户端服务器
隐藏的一方客户端(服务器不知道真实客户端)服务器(客户端不知道真实服务器)
架设位置客户端网络侧服务器网络侧
客户端是否需要配置✅ 需要手动设置代理❌ 无感知,不需要配置
主要用途突破访问限制、隐藏身份负载均衡、安全防护、高可用
典型工具Clash、V2Ray、SquidNginx、HAProxy、Caddy

4.2 相同点#

  • 都位于客户端和服务器之间
  • 都做请求转发
  • 都能通过缓存机制提升访问速度
  • 对通信的另一方都是”透明”的(对方不知道代理的存在)

4.3 四层代理 vs 七层代理#

反向代理还有一个维度的分类,工作在哪一个网络层:

类型工作层路由依据特点典型工具
四层代理TCP/UDP 层IP + 端口做 hash速度快,不解析内容LVS、HAProxy TCP 模式
七层代理HTTP 应用层URL、Header、Cookie 等功能丰富,可精细路由Nginx、HAProxy HTTP 模式

四层代理不理解 HTTP,只看 IP 和端口,处理速度更快;七层代理能读懂请求内容,可以根据 URL 路径、Cookie、请求头来做更灵活的转发决策。Nginx 是典型的七层代理。


5 用 Nginx 搭建反向代理#

5.1 整体架构说明#

本节目标:用 Nginx 作为反向代理入口,对外统一暴露 80 端口,实际请求由 Nginx 转发给后端服务。

根据后端服务的情况,分三种方案:

方案一:后端是本机 Flask 应用
外部用户 → Nginx:80 → Flask:5000(同一台机器)
方案二:后端是同机器上的博客
外部用户 → Nginx:80 → 博客程序:端口(同一台机器)
方案三:后端博客在另一台服务器上
外部用户 → Nginx:80 → 另一台服务器IP:端口(跨机器)

5.2 第一步:准备后端应用#

5.2.1 方案一:Flask 应用(无博客时使用)#

安装 Flask:

Terminal window
pip3 install flask

创建应用:

Terminal window
mkdir -p /opt/myapp && cd /opt/myapp
vim app.py

写入以下内容:

from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def index():
return '''
<h1>Hello from Flask!</h1>
<p>这个页面由 Flask 提供,通过 Nginx 反向代理访问</p>
<p>客户端真实 IP:{}</p>
'''.format(request.headers.get('X-Real-IP', request.remote_addr))
@app.route('/api/info')
def info():
return {
"status": "ok",
"message": "反向代理工作正常",
"real_ip": request.headers.get('X-Real-IP', '未获取到'),
"forwarded_for": request.headers.get('X-Forwarded-For', '无')
}
if __name__ == '__main__':
# 只监听本地,由 Nginx 对外暴露
app.run(host='127.0.0.1', port=5000)

后台启动:

Terminal window
nohup python3 /opt/myapp/app.py > /opt/myapp/app.log 2>&1 &
# 验证启动成功
curl http://127.0.0.1:5000
# 能看到 HTML 内容说明 Flask 正常运行

5.2.2 方案二:博客在同一台服务器上#

常见的博客程序(Hexo、WordPress、Ghost 等)本身会监听某个端口,直接确认端口号即可,Nginx 负责把请求转过去。

Hexo(静态博客):

Terminal window
# Hexo 本地预览默认跑在 4000 端口
hexo server
# 此时访问 127.0.0.1:4000 可以看到博客
# 查看 Hexo 实际监听的端口
ss -tlnp | grep node

WordPress:

Terminal window
# 如果用 PHP 内置服务器启动
php -S 127.0.0.1:8080 -t /var/www/wordpress
# 查看端口
ss -tlnp | grep :8080

Ghost:

Terminal window
# Ghost 默认端口 2368
ghost start
ss -tlnp | grep :2368

确认博客本地可访问后,记下端口号,下一步配置 Nginx 时会用到。

Terminal window
# 用 curl 确认博客在本地能正常响应
curl http://127.0.0.1:<博客端口>

5.2.3 方案三:博客在其他服务器上(跨机器反代)#

博客部署在另一台机器,想通过自己的服务器做一层反向代理入口。这种情况下 Nginx 不是转发给 127.0.0.1,而是转发给那台机器的 IP 和端口。

需要提前确认的信息:

Terminal window
# 在 Nginx 所在机器上测试能否访问目标服务器
curl http://192.168.1.100:8080
# 能拿到响应说明网络通

注意事项:

  • 目标服务器的防火墙需要允许 Nginx 所在机器的 IP 访问对应端口
  • proxy_set_header Host 需要设置成博客实际绑定的域名,否则博客可能返回 404 或跳转
  • 跨公网代理时注意延迟,proxy_read_timeout 可适当调大

5.3 第二步:安装 Nginx#

5.3.1 yum 安装(CentOS / Rocky,推荐)#

Terminal window
# CentOS 7
yum install epel-release -y
yum install nginx -y
# CentOS 8 / Rocky Linux
dnf install nginx -y
# 验证
nginx -v

5.3.2 apt 安装(Ubuntu / Debian)#

Terminal window
apt update
apt install nginx -y
# 验证
nginx -v

5.3.3 编译安装(需要定制模块时使用)#

Terminal window
# 安装依赖
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel -y
# 下载源码
wget -P /usr/local/src http://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf /usr/local/src/nginx-1.24.0.tar.gz -C /usr/local/src
# 编译安装
cd /usr/local/src/nginx-1.24.0
./configure --prefix=/usr/local/nginx
make && make install
# 验证
/usr/local/nginx/sbin/nginx -v

5.4 第三步:编写反向代理配置#

5.4.1 配置文件位置说明#

Terminal window
# yum/apt 安装
主配置文件:/etc/nginx/nginx.conf
站点配置目录:/etc/nginx/conf.d/ 推荐在这里新建 .conf 文件
# 编译安装
主配置文件:/usr/local/nginx/conf/nginx.conf

推荐做法是不动主配置文件,在 conf.d/ 下新建独立的配置文件,主配置里有一行 include /etc/nginx/conf.d/*.conf; 会自动加载。

5.4.2 Flask 反代配置#

Terminal window
vim /etc/nginx/conf.d/flask.conf
server {
listen 80;
server_name _; # _ 匹配所有 IP/域名,也可以写具体域名
access_log /var/log/nginx/flask_access.log;
error_log /var/log/nginx/flask_error.log;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}

5.4.3 博客(同机器)反代配置#

以博客跑在本机 4000 端口为例(Hexo),其他博客程序换端口号即可:

Terminal window
vim /etc/nginx/conf.d/blog.conf
server {
listen 80;
server_name yourdomain.com; # 换成你的域名或服务器 IP
access_log /var/log/nginx/blog_access.log;
error_log /var/log/nginx/blog_error.log;
location / {
proxy_pass http://127.0.0.1:4000; # 博客程序监听的端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
}
# 静态资源让 Nginx 直接处理,不经过博客程序(可选,提升性能)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
proxy_pass http://127.0.0.1:4000;
expires 7d;
add_header Cache-Control "public";
}
}

5.4.4 博客(跨机器)反代配置#

博客在另一台服务器 192.168.1.100:8080

Terminal window
vim /etc/nginx/conf.d/blog_remote.conf
server {
listen 80;
server_name yourdomain.com;
access_log /var/log/nginx/blog_remote_access.log;
error_log /var/log/nginx/blog_remote_error.log;
location / {
proxy_pass http://192.168.1.100:8080;
# 跨机器时 Host 要设置成博客实际绑定的域名
proxy_set_header Host yourdomain.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 跨网络延迟可能更高,超时时间适当调大
proxy_connect_timeout 15s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}

跨机器反代的额外检查清单:

Terminal window
# 1. 确认从 Nginx 机器能访问到目标
curl http://192.168.1.100:8080
# 2. 确认目标服务器防火墙已放行(在目标服务器上执行)
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
# 3. 确认目标博客程序监听的是 0.0.0.0 而不是 127.0.0.1
ss -tlnp | grep :8080
# 正确:*:8080 或 0.0.0.0:8080
# 错误:127.0.0.1:8080(只允许本机访问,外部 Nginx 访问不到)

5.4.5 核心配置字段详解#

字段作用
listen 80Nginx 监听的端口
server_name匹配的域名或 IP,_ 表示匹配所有
location /匹配请求路径,/ 匹配所有路径
proxy_pass转发目标地址,核心指令
proxy_set_header Host保持原始 Host 头,后端能识别请求来源
X-Real-IP把真实客户端 IP 传给后端
X-Forwarded-For记录完整代理链路的 IP 列表
X-Forwarded-Proto告诉后端原始请求是 HTTP 还是 HTTPS
proxy_connect_timeout与后端建立连接的超时时间
proxy_read_timeout等待后端响应的超时时间

5.5 第四步:检查配置并启动#

5.5.1 语法检查#

每次修改配置后,启动或重载之前先检查语法:

Terminal window
# yum/apt 安装
nginx -t
# 编译安装
/usr/local/nginx/sbin/nginx -t
# 正确输出:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

5.5.2 启动与重载命令#

Terminal window
# yum/apt 安装,用 systemctl 管理
systemctl start nginx # 启动
systemctl stop nginx # 停止
systemctl restart nginx # 重启(会中断现有连接)
systemctl reload nginx # 重载配置(不中断连接,修改配置后用这个)
systemctl enable nginx # 设置开机自启
systemctl status nginx # 查看运行状态
# 编译安装,直接调用二进制
/usr/local/nginx/sbin/nginx # 启动
/usr/local/nginx/sbin/nginx -s reload # 重载配置
/usr/local/nginx/sbin/nginx -s stop # 停止
/usr/local/nginx/sbin/nginx -s quit # 优雅退出

查看是否正常运行:

Terminal window
ps aux | grep nginx
# 正常应该看到一个 master process 和至少一个 worker process
ss -tlnp | grep :80
# 确认 80 端口已经在监听

5.6 第五步:防火墙放行端口#

Terminal window
# CentOS / Rocky(firewalld)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
firewall-cmd --list-ports # 确认 80/tcp 在列表里
# Ubuntu(ufw)
ufw allow 80/tcp
ufw status
# 同时需要 HTTPS 时
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --reload

云服务器额外步骤:阿里云、腾讯云、AWS 等云平台除了系统防火墙外还有安全组规则,需要去控制台手动添加放行 80 端口的入站规则,否则外网依然无法访问。


5.7 第六步:验证反向代理效果#

本地验证:

Terminal window
# 通过 Nginx 的 80 端口访问,看能否拿到后端响应
curl http://127.0.0.1:80
curl http://127.0.0.1:80/api/info # Flask 方案

外部访问:

浏览器打开 http://你的服务器IP,应该看到后端服务返回的页面。

确认请求真的经过了 Nginx 转发:

Terminal window
# 查看 Nginx 访问日志,有记录说明请求经过了 Nginx
tail -f /var/log/nginx/flask_access.log
# 查看后端日志,IP 应该是 127.0.0.1(来自 Nginx 转发)
tail -f /opt/myapp/app.log

验证 X-Forwarded-For 头是否正确传递(Flask 方案):

访问 http://你的服务器IP/api/info,返回 JSON 里的 real_ip 字段应该显示你本机的真实出口 IP,说明 Nginx 正确把客户端 IP 传给了后端。


5.8 完整流程回顾#

方案一(Flask):
1. 启动 Flask python3 app.py(监听 127.0.0.1:5000)
2. 安装 Nginx yum/apt install nginx
3. 写反代配置 /etc/nginx/conf.d/flask.conf
4. 检查配置语法 nginx -t
5. 启动/重载 Nginx systemctl reload nginx
6. 防火墙放行 80 端口 firewall-cmd / ufw / 安全组
7. 浏览器访问 :80 看到 Flask 页面 = 搭建成功
方案二(博客同机器):
1. 确认博客运行端口 ss -tlnp | grep <端口>
2. 确认博客本地可访问 curl http://127.0.0.1:<端口>
3-7. 步骤同上,proxy_pass 换成博客的端口
方案三(博客跨机器):
1. 确认 Nginx 机器能访问目标 curl http://<目标IP>:<端口>
2. 确认目标服务器防火墙放行 firewall-cmd(在目标机器执行)
3. 确认博客监听 0.0.0.0 ss -tlnp(在目标机器执行)
4-7. 步骤同上,proxy_pass 换成 http://<目标IP>:<端口>

6 常用扩展配置#

6.1 负载均衡(多台后端 upstream)#

upstream backend_cluster {
server 127.0.0.1:5000 weight=3;
server 127.0.0.1:5001 weight=1;
server 127.0.0.1:5002 weight=1;
# 其他调度策略(三选一,默认轮询):
# ip_hash; 按客户端 IP hash,同一 IP 总是打到同一台
# least_conn; 优先转发给当前连接数最少的服务器
}
server {
listen 80;
location / {
proxy_pass http://backend_cluster;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

6.2 按路径路由到不同后端#

server {
listen 80;
location /api/ {
proxy_pass http://127.0.0.1:5000;
}
location /admin/ {
proxy_pass http://127.0.0.1:8080;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
}

6.3 添加 HTTPS(SSL 卸载)#

HTTPS 在 Nginx 层统一终止,后端服务只需要跑 HTTP,不用操心证书的事。

server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
# HTTP 自动跳转 HTTPS
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}

证书可以用 Let’s Encrypt 免费申请:certbot --nginx -d yourdomain.com,申请后会自动修改 Nginx 配置。

6.4 常用调试命令速查#

Terminal window
# 检查配置语法
nginx -t
# 修改配置后重载(不中断服务)
systemctl reload nginx
# 实时查看错误日志
tail -f /var/log/nginx/error.log
# 实时查看访问日志
tail -f /var/log/nginx/access.log
# 查看 Nginx 监听的端口
ss -tlnp | grep nginx
# 测试本地反代是否工作
curl -v http://127.0.0.1:80
# 查看 Nginx 进程
ps aux | grep nginx
# 查看 Nginx 配置文件位置
nginx -V 2>&1 | grep -o '\-\-conf-path=[^ ]*'
代理学习
https://fuwari.vercel.app/posts/proxy/
作者
BIG熙
发布于
2026-03-07
许可协议
CC BY-NC-SA 4.0