1 什么是代理
1.1 代理的概念与定位
代理服务器是客户端和服务器之间的”中间人”,所有的请求和响应都经它转手。根据代理站在哪一侧、服务于谁,分成正向代理和反向代理两种。
代理能做的事情很多:转发请求、缓存资源、过滤内容、做鉴权、负载均衡……核心思路都是——请求经过我这里,我就能对它做处理。
1.2 代理的基本请求流程
客户端 → 代理服务器 → 目标服务器客户端 ← 代理服务器 ← 目标服务器具体过程:
- 客户端按照代理协议与代理服务器建立连接
- 客户端告诉代理自己想访问哪里
- 代理去请求目标服务器
- 目标服务器返回响应给代理
- 代理把响应转发回客户端
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、Squid | Nginx、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:
pip3 install flask创建应用:
mkdir -p /opt/myapp && cd /opt/myappvim 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)后台启动:
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(静态博客):
# Hexo 本地预览默认跑在 4000 端口hexo server# 此时访问 127.0.0.1:4000 可以看到博客
# 查看 Hexo 实际监听的端口ss -tlnp | grep nodeWordPress:
# 如果用 PHP 内置服务器启动php -S 127.0.0.1:8080 -t /var/www/wordpress
# 查看端口ss -tlnp | grep :8080Ghost:
# Ghost 默认端口 2368ghost startss -tlnp | grep :2368确认博客本地可访问后,记下端口号,下一步配置 Nginx 时会用到。
# 用 curl 确认博客在本地能正常响应curl http://127.0.0.1:<博客端口>5.2.3 方案三:博客在其他服务器上(跨机器反代)
博客部署在另一台机器,想通过自己的服务器做一层反向代理入口。这种情况下 Nginx 不是转发给 127.0.0.1,而是转发给那台机器的 IP 和端口。
需要提前确认的信息:
# 在 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,推荐)
# CentOS 7yum install epel-release -yyum install nginx -y
# CentOS 8 / Rocky Linuxdnf install nginx -y
# 验证nginx -v5.3.2 apt 安装(Ubuntu / Debian)
apt updateapt install nginx -y
# 验证nginx -v5.3.3 编译安装(需要定制模块时使用)
# 安装依赖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.gztar -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/nginxmake && make install
# 验证/usr/local/nginx/sbin/nginx -v5.4 第三步:编写反向代理配置
5.4.1 配置文件位置说明
# 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 反代配置
vim /etc/nginx/conf.d/flask.confserver { 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),其他博客程序换端口号即可:
vim /etc/nginx/conf.d/blog.confserver { 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:
vim /etc/nginx/conf.d/blog_remote.confserver { 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; }}跨机器反代的额外检查清单:
# 1. 确认从 Nginx 机器能访问到目标curl http://192.168.1.100:8080
# 2. 确认目标服务器防火墙已放行(在目标服务器上执行)firewall-cmd --permanent --add-port=8080/tcpfirewall-cmd --reload
# 3. 确认目标博客程序监听的是 0.0.0.0 而不是 127.0.0.1ss -tlnp | grep :8080# 正确:*:8080 或 0.0.0.0:8080# 错误:127.0.0.1:8080(只允许本机访问,外部 Nginx 访问不到)5.4.5 核心配置字段详解
| 字段 | 作用 |
|---|---|
listen 80 | Nginx 监听的端口 |
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 语法检查
每次修改配置后,启动或重载之前先检查语法:
# 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 successful5.5.2 启动与重载命令
# 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 # 优雅退出查看是否正常运行:
ps aux | grep nginx# 正常应该看到一个 master process 和至少一个 worker process
ss -tlnp | grep :80# 确认 80 端口已经在监听5.6 第五步:防火墙放行端口
# CentOS / Rocky(firewalld)firewall-cmd --permanent --add-port=80/tcpfirewall-cmd --reloadfirewall-cmd --list-ports # 确认 80/tcp 在列表里
# Ubuntu(ufw)ufw allow 80/tcpufw status
# 同时需要 HTTPS 时firewall-cmd --permanent --add-port=443/tcpfirewall-cmd --reload云服务器额外步骤:阿里云、腾讯云、AWS 等云平台除了系统防火墙外还有安全组规则,需要去控制台手动添加放行 80 端口的入站规则,否则外网依然无法访问。
5.7 第六步:验证反向代理效果
本地验证:
# 通过 Nginx 的 80 端口访问,看能否拿到后端响应curl http://127.0.0.1:80curl http://127.0.0.1:80/api/info # Flask 方案外部访问:
浏览器打开 http://你的服务器IP,应该看到后端服务返回的页面。
确认请求真的经过了 Nginx 转发:
# 查看 Nginx 访问日志,有记录说明请求经过了 Nginxtail -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 nginx3. 写反代配置 /etc/nginx/conf.d/flask.conf4. 检查配置语法 nginx -t5. 启动/重载 Nginx systemctl reload nginx6. 防火墙放行 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 自动跳转 HTTPSserver { listen 80; server_name yourdomain.com; return 301 https://$host$request_uri;}证书可以用 Let’s Encrypt 免费申请:
certbot --nginx -d yourdomain.com,申请后会自动修改 Nginx 配置。
6.4 常用调试命令速查
# 检查配置语法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=[^ ]*'