Files
wecom_it_smart_desk/set-real-ip-patch.md
T

12 KiB

nginx 真实 IP 还原 — 生产部署(小白友好版)

术语速查:nginx = 你这台服务器的"门卫",负责把用户请求分发给后端 / 把静态文件返回给浏览器 配置 = nginx 的工作规则,改配置 = 改门卫的工作方式


我们要做啥(整体目标)

一句话目标:https://itsupport.servyou.com.cn/itadmin/ 之前返回 403(被门卫拦了),原因是门卫把"代理服务器 IP"当成了"用户 IP",而代理 IP 不在白名单里。这次我们改门卫的规则,让它从请求头里读"真实用户 IP"。

一共 7 个动作:

# 动作 大概多久 风险
1 PuTTY 连上服务器 1 分钟 无风险
2 备份当前配置 几秒 🟢 备份原文件,可还原
3 写入 13 行新规则 几秒 🟡 改配置,但有备份
4 确认写入正确 几秒 只读不写
5 检查配置语法 几秒 只读不写
6 让 nginx 重新读规则 1 秒 🟡 短暂重载,服务不中断
7 浏览器看效果 几秒 只读

总耗时:第一次大概 5-10 分钟;熟练了 2 分钟

整体风险:🟢 — 每一步都给了"回滚"按钮,改坏了随时能恢复


PuTTY 是啥?在哪儿打开?

PuTTY = 一个 SSH 客户端软件,作用是让你从你的 Windows 电脑远程连到公司的 Linux 服务器

打开方式:

  • Win 键 → 输入 putty → 回车
  • 或者开始菜单 → 找到 PuTTY 图标

打开后会看到一个灰底配置界面,我们要填 4 项:

┌──────────────────────────────────────┐
│  Host Name (or IP address)           │  ← 填: 10.212.189.210
│  Port                                │  ← 填: 2222
│  Connection type                     │  ← 选: SSH(默认就是)
│  Saved Sessions                      │  ← 填: wecom-bastion(起个名)
└──────────────────────────────────────┘

点 Save 保存 → 点 Open 开始连接

连接后会黑底白字,提示 login as: → 输入 sxn 回车 → 提示 password: → 输入你的堡垒机密码(输入时屏幕不显示,正常,输完回车就行)

注意:输错密码不会锁账号,直接重新输


动作 1:PuTTY 连服务器( 无风险)

为啥要连服务器?:改配置必须在服务器上操作,你 Windows 这边只是"遥控器"

连上堡垒机后,黑底白字会显示一个类似 sxn@jump-host:~$ 的提示符,说明你已经到堡垒机了。

决策树:

你现在看到了堡垒机提示符(类似 sxn@jump-host:~$)
   ├─ 是 → 在 PuTTY 里继续输入下面命令
   └─ 否 → 截图发给我,卡哪儿了

贴下面的命令(右键 = 粘贴,Enter = 执行):

# 从堡垒机跳到真正的生产服务器
ssh sxn@10.90.5.110

回车后可能要输密码(堡垒机和目标机密码可能不同,试一下你之前用过的那个)

成功长这样:

sxn@prod-server:~$

失败常见:

  • Permission denied → 密码错了,重输
  • Connection timed out → 网络问题,可能 VPN 没连
  • 卡住不动 → 可能需要输 yes 确认服务器指纹,看到 (yes/no/[fingerprint])? 就输 yes 回车

动作 2:备份当前配置(🟢 低风险,改坏了能还原)

为啥要备份?:运维铁律 — 改任何东西之前先备份,这样改坏了能用备份还原,不会把生产搞挂

# 进入 nginx 配置所在目录
cd /opt/wecom-it-desk/nginx

# 复制一份当前配置,文件名带当前时间(分),方便区分
sudo cp nginx.conf nginx.conf.bak-$(date +%H%M)

# 列出所有备份文件,确认刚才那行成功
ls -la nginx.conf.bak-*

为啥用 $(date +%H%M)?:这个写法会自动拼上当前时间(比如 1430 表示 14:30),每次备份文件名都不一样,不会覆盖之前的备份

成功长这样:

-rw-r--r-- 1 root root 4821 Jun 15 14:30 nginx.conf.bak-1430

失败常见:

  • cp: cannot stat 'nginx.conf' → 当前不在 nginx 目录,先 cd /opt/wecom-it-desk/nginx 进去
  • Permission denied → 缺 sudo,命令前面加 sudo 重试

动作 3:写入 13 行新规则(🟡 中风险,但有备份兜底)

写入啥?:13 行 nginx 配置,告诉 nginx"从请求头 X-Forwarded-For 里读真实用户 IP"

为啥要这样做?:用户通过公司 WAF/堡垒机访问,WAF 会把真实 IP 放在 X-Forwarded-For 请求头里,但 nginx 默认只看直连 IP,所以才误判 403

重要:把下面cat > /tmp/patch.pyPYEOF整段一次性粘贴进 PuTTY(右键 = 粘贴)。整段会作为一条命令执行。

# 创建一个 python 脚本到 /tmp/patch.py
cat > /tmp/patch.py << 'PYEOF'
fp = '/opt/wecom-it-desk/nginx/nginx.conf'
with open(fp) as f:
    c = f.read()
patch = '''
    # ------------------------------------------------------------------
    # 真实 IP 还原(2026-06-15 v0.5.1 修复)
    # ------------------------------------------------------------------
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    set_real_ip_from 10.212.0.0/16;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;
'''
old = 'error_log  /var/log/nginx/error.log warn;'
new = old + patch
new_c = c.replace(old, new, 1)
with open(fp, 'w') as f:
    f.write(new_c)
print('patched, +{} bytes'.format(len(new_c) - len(c)))
PYEOF

# 运行这个 python 脚本,它会自动把上面那 13 行插入到 nginx.conf
sudo python3 /tmp/patch.py

术语解释:

  • cat > /tmp/patch.py → 创建一个文件,内容是后面所有内容
  • << 'PYEOF' ... PYEOF → 这种写法叫 heredoc(直译"这里是文档"),作用是把多行文字原样写入文件
  • sudo → 以管理员身份运行(改系统文件需要权限)

成功长这样:

patched, +492 bytes

失败常见:

  • Permission denied → 缺 sudo,或者 nginx.conf 不存在
  • NameError: name 'fp' is not defined → heredoc 没贴完整,最末尾的 PYEOF 没贴上
  • 没任何输出 → python 没运行,看光标有没有新行,可能没回车

动作 4:确认写入正确( 无风险,只读)

为啥要确认?:虽然脚本说写入了,但人眼看到才真的算。这步只读不写,放心跑

# 在 nginx.conf 里搜索"真实 IP 还原"关键字,并显示后面 13 行
sudo grep -A 13 "真实 IP 还原" /opt/wecom-it-desk/nginx/nginx.conf

成功长这样(应该看到完整 13 行):

    # 真实 IP 还原(2026-06-15 v0.5.1 修复)
    # ------------------------------------------------------------------
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    set_real_ip_from 10.212.0.0/16;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;

失败:

  • 啥也没输出 → 写入失败,回到动作 3 重做
  • 只输出一两行 → heredoc 没贴全,需要回滚后重来

动作 5:检查配置语法( 无风险,只读不执行)

为啥要检查?:这个命令 nginx 会"假装"按新配置启动,只检查语法,不会真的重启。通过 = 配置写得对,放心用;不通过 = 写得有问题,继续走会出问题

# 在 nginx 容器(就是跑 nginx 服务的那个小 Linux)内,做配置语法检查
docker compose exec nginx nginx -t

术语解释:

  • docker compose → 管理这台服务器上所有"容器"的命令
  • exec → "钻进"某个容器里执行命令
  • nginx -t → nginx 自带的"语法检查"工具(全称 --test)

成功长这样:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

失败(test is successful 没出现):

  • unexpected "}" / unknown directive → 写错字了,回去动作 4 看看哪里对不上
  • 直接停下,不要继续 → 复制错误信息贴回给我

动作 6:让 nginx 重新读规则(🟡 中风险,但服务不中断)

"重新读"是啥意思?:nginx 现在用的还是旧配置,我们让 nginx 不用重启(不会断服务)就把新配置加载进来。这个动作叫"热加载"或 "reload"

会断网吗?:不会,reload 是无缝的,用户那边无感知

# 通知 nginx 容器内的 master 进程重新读配置
docker compose exec nginx nginx -s reload

术语解释:-s reload = 发信号(英文 signal)给 nginx,告诉它"重读配置"

成功长这样(没报错即成功):

2026/06/15 14:35:12 [notice] 1#1: signal process started

失败:

  • nginx: [error] 开头 → 配置没通过,回去动作 5 看哪里没对
  • 啥也没输出 → 命令没执行,看光标位置

动作 7:浏览器看效果( 无风险)

为啥这步是浏览器而不是 curl?:curl 看响应头,浏览器看真实页面。人眼看到才作数

操作步骤:

  1. 打开浏览器
  2. 开隐身模式(Ctrl + Shift + N,Chrome / Edge 都是这个快捷键)
    • 为啥要隐身?:隐身模式不读本地缓存,看到的就是 nginx 当下返回的
  3. 地址栏输入 https://itsupport.servyou.com.cn/itadmin/
  4. 按回车

成功长这样:

  • 页面正常显示
  • F12 打开开发者工具 → Network 选项卡 → 顶部那一行状态码是 200(不是 403)

失败:

  • 仍然是 403 → 见下面"如果还是 403"段
  • 502 / 504 → nginx 后面那个服务挂了,贴错误给我
  • 页面打不开(连接被拒) → DNS 没配,联系 IT 运维

如果还是 403 — 看 WAF 出口 IP(诊断)

啥是 WAF?:公司部署在 nginx 前面的"统一入口",所有用户请求先经过 WAF 再到 nginx。WAF 自己的 IP 不一定在你写的 4 段内网里,所以还得加

# 看 nginx 最后 20 条访问日志,找 $remote_addr 是不是 WAF 的 IP
docker compose exec nginx tail -20 /var/log/nginx/access.log

日志长这样:

10.80.5.123 - - [15/Jun/2026:14:35:45 +0800] "GET /itadmin/ HTTP/1.1" 403 ...
^^^^^^^
这就是 $remote_addr

把那个 IP 数字(比如 10.80.5.123)贴回给我,我会:

  1. 给你追加一行 set_real_ip_from 10.80.5.123;
  2. 让你重跑动作 5 + 动作 6

如果改坏了 — 回滚(啥时候都能用)

啥时候用?:任何一个动作出问题,你都可以直接回滚到动作 2 备份的版本

# 列出所有备份,挑最近的一个
ls -la /opt/wecom-it-desk/nginx/nginx.conf.bak-*
# 用最近那个备份覆盖当前配置(把 1430 换成上面列出的真实时间)
sudo cp /opt/wecom-it-desk/nginx/nginx.conf.bak-1430 /opt/wecom-it-desk/nginx/nginx.conf
# 重新加载回滚后的配置
docker compose exec nginx nginx -s reload

回滚后页面应该回到改之前的状态(403 回来),说明回滚成功


一张图看懂流程

PuTTY 连服务器
    │
    ▼
备份原配置
    │
    ▼
写入 13 行新规则
    │
    ▼
确认写入正确 ──→ ❌ 不对 ──→ 重做写入 / 回滚
    │ ✅
    ▼
检查配置语法 ──→ ❌ 语法错 ──→ 复制错误贴回给我,不要继续
    │ ✅
    ▼
重载 nginx ─────→ ❌ 报错 ──→ 检查容器状态 / 找 Claude
    │ ✅
    ▼
浏览器看效果 ──→ ❌ 还是 403 ──→ 看 WAF 出口 IP,贴给 Claude
    │ ✅
    ▼
🎉 完成

我建议你第一次做

第一次建议:动作 1 → 动作 2 → 停一下,截图发给我 → 我确认备份成功 → 你再继续动作 3 之后

熟练了以后:一口气跑完动作 1-7,中间不打断


关联

  • 评审报告:review-p0-security-2026-06-14.md P0-3
  • 待办:ip-whitelist-trust-proxies-todo.md — v1.0 前必须收窄 4 段 → 4 个 IP
  • 本地配置:deploy-server/nginx/nginx.conf(已包含 patch,下次重打包自动带)
  • 服务器 IP 变更:project-production-server-ip-2026-06-15.md — 10.80.0.136 已下线,用 10.90.5.110
  • 客户端约束:feedback-putty-not-openssh.md — 用 PuTTY,不用 ssh -J
  • 命令行规范:feedback-cmd-step-by-step.md — 每行一条 + 中文注释
  • 小白引导规范:feedback-beginner-friendly-guide.md — 讲清目标+风险、术语解释、出错兜底