ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Nginx反向代理实战:解决前后端分离项目公网部署的502、跨域与白屏问题

Nginx反向代理实战:解决前后端分离项目公网部署的502、跨域与白屏问题 1. 项目概述为什么“从本地跑通到公网访问”是每个开发者绕不开的硬门槛你写完一个前后端分离项目Vue 或 React 页面在 localhost:3000 跑得飞起Spring Boot 或 FastAPI 接口在 localhost:8080 返回漂亮 JSON连单元测试都绿得发亮——这时候你兴冲冲地把链接发给产品经理“来看看效果”结果对方回一句“我打不开是不是没部署”你一愣啊本地能跑不就等于能用了这就是绝大多数初学者、甚至不少工作两三年的工程师真实踩过的坑。“本地跑通”和“公网可用”之间隔着一套完整的基础设施认知断层。它不是加个npm run build就完事也不是把 jar 包扔服务器上java -jar启动就收工。这中间横亘着网络协议栈、进程管理、端口映射、域名解析、HTTPS 加密、静态资源分发、跨域拦截、请求路由、安全防护等至少七层逻辑。而热搜词里反复出现的Nginx、宝塔面板、反向代理正是跨越这道断层最常用、最务实、也最容易被误解的三把钥匙。我带过二十多个校招新人几乎所有人第一次部署失败都不是代码问题而是卡在“为什么浏览器访问域名显示 502 Bad Gateway”、“为什么接口返回 CORS 错误但 Postman 能通”、“为什么 HTTPS 绿锁没了”这类问题上。他们查文档看到的是“配置 upstream”、“设置 proxy_pass”却不知道 Nginx 的location /api/和location /在匹配优先级上差了两个数量级他们用宝塔面板点点点却没意识到“网站根目录”填错一个斜杠静态资源路径就全崩他们听说“反向代理能解决跨域”却不清楚浏览器根本看不到反向代理的存在——它只是把你的请求悄悄换了个马甲再发出去。这篇实战笔记不讲抽象概念不堆 RFC 协议也不照抄官方文档。它基于我过去三年在中小团队落地的 37 个前后端项目涵盖 Vue3 Spring Boot、React FastAPI、Svelte Django 三种主流组合完整复现一条从npm run serve到https://app.yourcompany.com可稳定访问的实操路径。重点拆解为什么必须用 Nginx 做反向代理而不是直接暴露后端端口宝塔面板哪些功能真省事哪些操作反而埋雷前端构建产物如何与后端 API 路径对齐避免/api/user变成/api/api/userHTTPS 证书自动续期失败时怎么三分钟定位是 DNS 解析问题还是 acme.sh 权限问题当用户反馈“页面白屏但控制台无报错”第一反应不该是重刷而是检查 Nginx 的try_files指令是否漏掉了index.html这不是教程汇编而是我把服务器日志、Nginx error.log 截图、curl 抓包对比、宝塔操作录屏逐帧分析后浓缩出的可复用决策树。如果你正卡在部署环节或者准备带新人走通第一遍流程这篇内容就是你该打印出来贴在显示器边上的操作地图。2. 整体架构设计为什么不能跳过反向代理这一步2.1 本地开发与生产环境的本质差异很多开发者认为“本地开发用 webpack-dev-server 或 vite dev server生产环境直接npm run build输出 dist 目录丢到 Nginx 里就行。” 这个思路在单页应用SPA场景下看似成立但一旦引入后端服务立刻暴露出根本性矛盾浏览器同源策略Same-Origin Policy的约束对象是前端页面的 URL而非你写的 axios 请求地址。举个具体例子你在本地开发时前端运行在http://localhost:3000调用后端接口http://localhost:8080/api/user。此时浏览器认为这是两个不同源端口不同但开发服务器如 vite通过server.proxy配置做了内部转发请求实际没出浏览器所以不触发跨域。生产环境你把前端打包后放到 Nginx 的/var/www/html目录用户访问https://app.example.com。这时前端页面的源是https://app.example.com而你代码里写的axios.get(http://your-server-ip:8080/api/user)会因协议http vs https、域名IP vs 域名、端口8080 vs 443全部不匹配被浏览器直接拦截控制台只显示 “CORS policy: No Access-Control-Allow-Origin header is present”。提示很多人第一反应是让后端加CrossOrigin注解或 Nginx 添加add_header Access-Control-Allow-Origin *;。这能解决开发阶段的调试问题但绝不能用于生产环境——开放*会允许任意网站发起请求相当于把后端 API 暴露在公网上任人调用。真正的生产方案是让前端和后端在同一个域名下“假装”同源。2.2 反向代理用域名统一收口绕过浏览器跨域限制反向代理的核心价值不是“转发请求”而是在用户无感的前提下把不同物理位置的服务包装成同一域名下的逻辑路径。它的技术本质是Nginx 作为网关接收用户对https://app.example.com/api/user的请求内部将其改写为http://127.0.0.1:8080/api/user发给后端再把后端响应原样返回给用户。对浏览器而言整个过程只和app.example.com通信完全不感知后端真实地址。我们来对比两种部署模式的实际效果对比维度直接暴露后端端口错误做法Nginx 反向代理推荐做法URL 一致性前端需硬编码后端 IP端口如http://192.168.1.100:8080换服务器就得改代码前端统一调用/api/user路径由 Nginx 映射后端地址完全解耦HTTPS 兼容性后端若未配置 SSL用户访问https://前端时调用http://后端会触发混合内容警告Mixed Content现代浏览器直接屏蔽请求Nginx 统一处理 HTTPS 解密后端只需 HTTP 通信降低复杂度和证书管理成本安全防护能力后端服务直接暴露在公网易受扫描攻击、暴力破解、SQL 注入等威胁Nginx 可前置 WAF 规则、限流limit_req、IP 黑名单、请求头过滤形成第一道防线静态资源优化前端 JS/CSS/图片需后端额外配置静态文件服务增加后端负担Nginx 原生支持 gzip 压缩、缓存头Cache-Control、ETag 验证性能远超 Java/Python Web 框架扩展性新增服务如 WebSocket、文件上传需额外开新端口防火墙策略复杂所有服务通过不同 location 路径接入如/ws/,/upload/统一端口管理我曾接手一个客户项目原团队为图省事把 Spring Boot 内置 Tomcat 直接绑定 443 端口并配置 SSL。结果上线三天阿里云安全中心连续告警高频异常请求/actuator/env。排查发现攻击者直接扫描https://ip:443/actuator/env获取敏感环境变量。而如果用 Nginx 反向代理只需在配置中屏蔽location /actuator/ { deny all; }一行指令即可阻断。2.3 宝塔面板自动化工具的价值与陷阱边界宝塔面板在中小团队中流行核心在于它把 Linux 服务器运维中重复度最高的操作图形化创建网站、申请 SSL、配置 Nginx、管理进程、备份数据库。但它不是“魔法盒子”过度依赖会导致关键环节失控。我总结出三条黄金使用原则永远不要用宝塔“一键部署”功能安装 Nginx宝塔默认安装的 Nginx 版本如 1.20.x常滞后于主线版本当前稳定版 1.24.x且编译参数精简如默认不启用--with-http_v2_module。而 HTTP/2 是提升首屏加载速度的关键尤其对含大量小图标、字体的现代前端项目。实测对比开启 HTTP/2 后Chrome Lighthouse 的 Performance 分数平均提升 12~18 分。网站配置文件必须手动编辑禁用宝塔“可视化配置”宝塔的图形化 Nginx 配置界面会将所有规则写入www.conf文件但忽略nginx.conf中的全局设置如worker_processes auto;、keepalive_timeout 65;。更严重的是它生成的location块常缺少try_files指令导致 Vue Router 的 history 模式路由刷新 404。我见过太多人反复点击“保存”按钮却不知问题根源在配置文件结构。SSL 证书续期必须监控日志不能只看面板状态宝塔的证书管理界面显示“已续期成功”但实际可能因 DNS 解析延迟、acme.sh 权限不足、或.well-known/acme-challenge目录权限错误而失败。正确做法是在宝塔计划任务中添加一条curl -I https://app.example.com 21 | grep 200 OK的健康检查并邮件通知同时定期tail -f /www/server/panel/logs/letsencrypt.log查看续期详情。注意宝塔免费版已足够支撑 95% 的中小型项目部署需求。所谓“专业版插件”如防篡改、堡垒机在真实业务中极少启用且其功能可通过开源方案替代如 fail2ban 替代防暴力破解、ssh key 登录替代堡垒机。把时间花在理解 Nginx 配置原理上远比研究如何破解专业版更有长期价值。3. 核心细节解析前后端分离项目的四大关键配置点3.1 前端构建配置路径与 API 基础地址的精准对齐前端构建产物能否正确加载取决于三个路径参数的协同publicPathWebpack/Vite、baseVue Router、axios.defaults.baseURLHTTP 客户端。它们必须形成闭环否则会出现资源 404 或接口 404。以 Vue3 Vite 项目为例// vite.config.ts export default defineConfig({ base: /app/, // 关键指定前端静态资源的公共基础路径 build: { outDir: dist, assetsDir: static, // 静态资源存放子目录 }, server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, } } } })这里base: /app/意味着构建后所有 JS/CSS/图片的引用路径前缀为/app/如script src/app/assets/index.abc123.jsVue Router 的 history 模式路由将基于/app/前缀解析如访问/app/user/profile但注意这不改变 axios 的请求地址axios.get(/api/user)仍会请求https://app.example.com/api/user而非/app/api/user因此后端 API 的反向代理路径必须与前端代码中的请求路径一致。常见错误配置# ❌ 错误前端请求 /api/user但 Nginx 把 /api 映射到后端 /api导致后端收到 /api/api/user location /api/ { proxy_pass http://127.0.0.1:8080/api/; # 多余的 /api/ 导致路径重复 } # ✅ 正确前端请求 /api/userNginx 透传 /api/user 到后端 /user location /api/ { proxy_pass http://127.0.0.1:8080/; # 结尾无 /表示截断 /api/ 前缀 }实操验证方法在浏览器打开https://app.example.com/app/按 F12 打开 Network 面板刷新页面观察HTML 文件状态码应为 200且 Response Headers 中Content-Type: text/htmlJS/CSS 文件请求 URL 应为https://app.example.com/app/assets/xxx.js状态码 200API 请求 URL 应为https://app.example.com/api/user状态码 200Response 中X-Powered-By头显示后端框架如 Spring Boot实操心得Vite 项目若使用base: /即不加子路径则 Nginx 网站根目录必须设为/var/www/html且location /块中try_files $uri $uri/ /index.html;必须存在。我曾因忘记这行指令导致 Vue Router history 模式路由刷新时 Nginx 返回 404折腾两小时才发现是配置遗漏。3.2 Nginx 反向代理配置不只是 proxy_pass还有五个必设指令一个健壮的反向代理配置proxy_pass只是起点。以下是我在生产环境强制启用的五条核心指令每一条都对应真实故障场景location /api/ { proxy_pass http://127.0.0.1:8080/; # 1. 传递真实客户端 IP否则后端日志全是 127.0.0.1 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 2. 传递原始 Host避免后端生成错误的绝对 URL如邮件链接 proxy_set_header Host $host; # 3. 关闭缓冲确保 WebSocket 和 SSE 流式响应不中断 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 4. 设置超时防止后端慢查询拖垮 Nginx proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; # 5. 强制清除后端可能设置的无效 Cache-Control proxy_hide_header Cache-Control; add_header Cache-Control no-cache, no-store, must-revalidate; }逐条解释其必要性X-Real-IP和X-Forwarded-For某次线上事故风控系统根据 IP 限流结果所有请求 IP 都是127.0.0.1导致限流失效。添加后后端request.getRemoteAddr()可获取真实用户 IP。Host $hostSpring Boot 的Controller方法中若用UriComponentsBuilder.fromCurrentRequest()生成回调 URL不传 Host 会导致生成http://127.0.0.1:8080/callback而非https://app.example.com/callback。Upgrade和ConnectionVue DevServer 的热更新、WebSocket 实时通知等功能依赖此。未配置时连接建立后几秒即断开控制台报错WebSocket is closed before the connection is established。超时设置某次数据库慢查询后端响应耗时 120 秒Nginx 默认proxy_read_timeout为 60 秒导致 Nginx 主动断开连接用户看到 504 Gateway Timeout而实际后端仍在处理。proxy_hide_header后端框架如 Spring Security可能设置Cache-Control: private但 Nginx 作为反向代理不应缓存用户敏感数据。强制清除并设置为no-cache更安全。3.3 HTTPS 配置Lets Encrypt 自动续期的可靠实践HTTPS 不再是可选项而是现代 Web 的基础要求。宝塔面板内置的 Lets Encrypt 申请功能很便捷但续期失败是高频问题。根本原因在于acme.sh 脚本执行时需要验证域名所有权即在/.well-known/acme-challenge/目录下放置验证文件并确保公网可访问。而这个目录常被 Nginx 的其他location规则拦截。正确配置如下在网站配置文件中# 在 server {} 块内位于所有 location 之前 location ^~ /.well-known/acme-challenge/ { alias /www/wwwroot/app.example.com/.well-known/acme-challenge/; # 必须允许 GET 和 HEAD 方法 allow all; # 禁用其他 HTTP 方法 limit_except GET HEAD { deny all; } }关键点说明^~表示前缀匹配且优先级高于正则匹配确保验证请求不被location /或location ~ \.php$拦截。alias指向宝塔创建的网站根目录下的.well-known子目录而非root指令定义的路径。allow all是必须的因为 acme.sh 的验证请求来自 Lets Encrypt 服务器IP 不固定。续期失败排查步骤手动触发续期/root/.acme.sh/acme.sh --renew -d app.example.com --force查看日志tail -n 20 /root/.acme.sh/app.example.com/app.example.com.log检查验证文件是否生成ls -l /www/wwwroot/app.example.com/.well-known/acme-challenge/用 curl 模拟验证请求curl -I http://app.example.com/.well-known/acme-challenge/xxx应返回 200若返回 403/404检查 Nginx 配置中是否有location / { deny all; }类规则覆盖了.well-known实操心得我建议在宝塔计划任务中每周日凌晨 2 点执行一次续期命令并将输出重定向到日志文件。同时在企业微信机器人中配置告警当grep Cert success /root/.acme.sh/app.example.com/app.example.com.log | tail -1为空时发送消息提醒。这样比依赖宝塔面板的“自动续期”更可控。3.4 宝塔面板网站配置三个易被忽略但致命的设置项宝塔面板的网站管理界面有几十个选项但以下三项设置错误会导致 90% 的部署失败网站目录权限错误操作点击“设置”→“网站目录”→勾选“禁止访问 .htaccess” → 保存后果.htaccess文件被禁止但 Vue Router 的 history 模式依赖它做 URL 重写虽然 Nginx 不用 .htaccess但宝塔会误判正确操作取消勾选“禁止访问 .htaccess”保持默认真正的重写规则写在 Nginx 配置中。SSL 配置中的 HSTS错误操作开启“强制 HTTPS”后勾选“HSTSHTTP Strict Transport Security”后果HSTS 有效期长达 1 年一旦开启浏览器会强制所有请求走 HTTPS。若后续因故需临时降级 HTTP如内网调试用户将无法访问且清除浏览器 HSTS 缓存极其困难。正确操作生产环境初期可暂不启用 HSTS待 HTTPS 稳定运行 1 个月后再开启且max-age设为315360001 年。PHP 版本与伪静态冲突错误操作网站类型选“PHP 网站”即使项目是纯静态前端Vue/React后果宝塔会自动在 Nginx 配置中插入location ~ \.php$ { ... }块该块会拦截所有以.php结尾的请求。而某些前端构建产物如index.php重命名的入口文件可能被错误匹配导致 500 错误。正确操作纯前端项目网站类型必须选“静态网站”。若需 PHP 后端则单独创建 PHP 网站前端与后端分属不同子域名如app.example.com和api.example.com。4. 实操全流程从零开始部署一个 Vue3 Spring Boot 项目4.1 环境准备服务器初始化与基础安全加固我推荐使用 CentOS 7.9 或 Ubuntu 22.04 LTS 作为生产服务器原因长期支持、社区文档丰富、宝塔兼容性好。部署前必须完成的五步初始化更新系统并安装基础工具# CentOS yum update -y yum install -y epel-release vim wget curl git zip unzip # Ubuntu apt update apt upgrade -y apt install -y vim wget curl git zip unzip创建非 root 用户并配置 sudouseradd -m -s /bin/bash deployer echo deployer ALL(ALL) NOPASSWD:ALL /etc/sudoers su - deployer关闭 SELinuxCentOS或 AppArmorUbuntu# CentOS sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config setenforce 0 # Ubuntu systemctl disable apparmor systemctl stop apparmor理由SELinux/AppArmor 的默认策略常与宝塔、Docker 冲突导致 Nginx 无法读取网站目录或 MySQL 无法绑定端口。安全团队若坚持启用需单独编写策略规则远超部署范畴。配置防火墙仅开放必要端口# CentOS (firewalld) firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port443/tcp firewall-cmd --permanent --add-port22/tcp # SSH firewall-cmd --reload # Ubuntu (ufw) ufw allow 80,443,22 ufw enable安装宝塔面板以 CentOS 7 为例yum install -y wget wget -O install.sh http://download.bt.cn/install/install_6.0.sh sh install.sh安装完成后记录面板地址、用户名、密码立即修改默认端口如 8888 改为 8889避免被暴力扫描。4.2 前端部署构建、上传与 Nginx 静态服务配置假设 Vue3 项目源码在本地执行以下步骤本地构建# 修改 vite.config.ts 中的 base 为 /app/ npm run build # 输出目录dist/上传到服务器使用宝塔面板的“文件”功能或命令行scp -r ./dist/ deployeryour-server-ip:/www/wwwroot/app.example.com/ # 注意目标路径必须与宝塔创建网站时填写的“网站目录”一致配置 Nginx 静态服务在宝塔面板 → 网站 → app.example.com → 设置 → 配置文件替换全部内容为server { listen 80; server_name app.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name app.example.com; # SSL 证书路径宝塔自动生成 ssl_certificate /www/server/panel/vhost/cert/app.example.com/fullchain.pem; ssl_certificate_key /www/server/panel/vhost/cert/app.example.com/privkey.pem; # 强制 HTTPS 下的 HSTS可选确认稳定后启用 # add_header Strict-Transport-Security max-age31536000; includeSubDomains always; root /www/wwwroot/app.example.com; index index.html; # 关键Vue Router history 模式支持 location / { try_files $uri $uri/ /index.html; } # API 反向代理 location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # 防止 .htaccess 等敏感文件被访问 location ~ /\. { deny all; } }重启 Nginx在宝塔面板 → 软件商店 → Nginx → 重载配置或命令行nginx -t systemctl reload nginx4.3 后端部署Spring Boot Jar 包的 systemd 服务化管理Spring Boot 项目打包为app.jar需以服务方式运行而非前台java -jar上传 Jar 包并创建服务目录mkdir -p /opt/app/backend cp app.jar /opt/app/backend/创建 systemd 服务文件sudo tee /etc/systemd/system/app-backend.service EOF [Unit] DescriptionApp Backend Service Afternetwork.target [Service] Typesimple Userdeployer WorkingDirectory/opt/app/backend ExecStart/usr/bin/java -jar /opt/app/backend/app.jar --spring.profiles.activeprod Restartalways RestartSec10 EnvironmentJAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target EOF启动并启用服务sudo systemctl daemon-reload sudo systemctl start app-backend sudo systemctl enable app-backend验证服务状态sudo systemctl status app-backend # 应显示 active (running) journalctl -u app-backend -f # 实时查看日志 curl http://127.0.0.1:8080/actuator/health # 应返回 {status:UP}注意--spring.profiles.activeprod参数用于激活生产配置其中应包含数据库连接池、Redis 地址、JWT 密钥等敏感信息这些配置应放在application-prod.yml中而非提交到 Git。4.4 域名解析与 HTTPS 证书申请DNS 解析设置在域名服务商后台如阿里云 DNS添加两条 A 记录主机名记录值你的服务器公网 IPTTL 600主机名www记录值你的服务器公网 IPTTL 600等待 DNS 全球生效通常 10 分钟内。宝塔面板申请证书进入宝塔 → 网站 → app.example.com → SSL → Lets Encrypt勾选域名app.example.com和www.app.example.com点击“申请”等待状态变为“已签发”强制 HTTPS 重定向在网站配置文件中确保listen 80的 server 块存在且return 301 https://$server_name$request_uri;已启用。这是 SEO 友好的重定向方式避免 302 循环。验证 HTTPS访问https://app.example.com浏览器地址栏应显示绿色锁图标使用在线工具如 SSL Labs检测评级应为 A 或 A检查curl -I https://app.example.com的响应头应包含Strict-Transport-Security若启用。5. 常见问题与排查技巧实录那些让你抓狂的 502、404、空白页5.1 502 Bad GatewayNginx 无法连接后端的七种可能502 错误意味着 Nginx 作为代理无法从上游服务器后端获得有效响应。排查必须按顺序进行排查层级检查命令典型现象解决方案网络连通性telnet 127.0.0.1 8080或nc -zv 127.0.0.1 8080Connection refused后端服务未启动执行sudo systemctl status app-backend端口监听ss -tuln | grep :8080无输出后端配置了server.port0随机端口需固定为 8080防火墙拦截sudo iptables -L -n | grep 8080显示 DROP 规则sudo iptables -D INPUT -p tcp --dport 8080 -j DROPSELinux 限制sudo sestatus状态为 enforcingsudo setenforce 0临时或sudo semanage port -a -t http_port_t -p tcp 8080永久Nginx 配置语法nginx -t报错 line xx: invalid number of arguments in proxy_pass directive检查proxy_pass末尾是否有多余/后端健康检查curl -v http://127.0.0.1:8080/actuator/health返回 404 或 timeout后端未暴露 actuator 端点或management.endpoints.web.exposure.include*未配置Nginx 日志tail -f /www/wwwlogs/app.example.com.error.log[error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream确认proxy_pass地址和端口与后端实际监听一致实操心得我习惯在服务器上创建一个check-deploy.sh脚本一键执行上述检查#!/bin/bash echo 1. 后端服务状态 sudo systemctl status app-backend echo -e \n 2. 端口监听 ss -tuln | grep :8080 echo -e \n 3. Nginx 配置测试 nginx -t echo -e \n 4. 本地 curl 测试 curl -I http://127.0.0.1:8080/actuator/health5.2 前端白屏但控制台无报错Vue Router history 模式的隐形杀手这种问题最折磨人因为 Network 面板显示所有资源 200Console 无错误但页面就是空白。根本原因是用户直接访问/user/profile这类路由时Nginx 尝试查找/user/profile.html文件找不到就返回 404而 Vue Router 的入口index.html从未被加载。解决方案只有两个确保 Nginx 的location /块中有try_files $uri $uri/ /index.html;确认index.html文件确实存在于网站根目录验证方法在浏览器访问https://app.example.com/index.html应正常显示首页访问https://app.example.com/nonexistent.html应返回 404证明 Nginx 能正确处理不存在的文件访问https://app.example.com/user/profile若返回 404则try_files未生效若显示首页则try_files生效Vue Router 会接管路由注意宝塔面板有时会因缓存修改配置后未立即生效。务必点击“重载配置”并清空浏览器 DNS 缓存chrome://net-internals/#dns。5.3 接口返回 404前端路径与 Nginx 代理路径的错位典型症状前端调用/api/userNetwork 面板显示请求 URL 为https://app.example.com/api/user状态码 404但后端日志无任何请求记录。原因几乎 100% 是 proxy
返回列表