只开一个洞:在 IP 白名单的 Nginx 站点里开放静态子目录

举报
yd_238022924 发表于 2026/10/23 01:41:03 2026/10/23
【摘要】 整站用 allow/deny 锁成只允许固定 IP,还要对外放一个静态作品页,怎么办?只加一个 ^~ 前缀的 location 就够了:alias 与 root 的区别、allow all 如何覆盖 server 级 deny、以及用 127.0.0.1 测试时 Host 不匹配导致的假 404。

做过一次小型部署之后我发现,真正麻烦的不是"把页面放上去",而是"既要对外开放,又不能把整站的门打开"。

我的场景很典型:一台云服务器上跑着个人测试站点,nginx 里用 allow/deny 把全站锁成只允许自己家的公网 IP 访问;现在需要额外放一个静态作品页(一个 2048 小游戏),要求任何人在公网上都能打开。直觉做法是把 deny all 去掉,但那等于把整站暴露出来。正确的做法是只为一个路径开洞。

一、先看清 nginx 的匹配顺序

nginx 的 location 匹配优先级是:= 精确 > ^~ 前缀(命中后不再匹配正则)> 正则 ~/~* > 普通前缀 > /。

关键点是 ^~:一旦命中这个前缀,就不会再去匹配正则表达式。这一点在"站点里有一堆安全正则(比如禁止访问 .git、.env、*.bak)"的环境里很重要——用 ^~ 能让你的路径不受那些正则影响,行为可预期。

二、最小改动:加一个 location

假设站点根是 /www/wwwroot/site,要把 /hc-activity/ 对外开放:

location ^~ /hc-activity/ {
    alias /www/wwwroot/hc-activity/;
    allow all;
    index index.html;
    limit_except GET { deny all; }
}

四个细节值得说清楚:

  1. alias 而不是 root。root 会拼成 /根路径/hc-activity/index.html,alias 则是直接替换前缀,变成 /www/wwwroot/hc-activity/index.html。目录和 URI 不同名时必须用 alias。
  2. allow all 能覆盖 server 级的 deny all。nginx 的 access 模块是"就近替换":location 里只要出现了任何 allow/deny 指令,就整套替换掉从 server 继承的那一组,而不是追加。所以不需要先把 server 的 deny all 删掉。
  3. limit_except GET { deny all; } 把方法限制成只读,顺手挡掉 PUT/DELETE 这类将来可能被加进来的方法。
  4. 如果站点还有 HTTP→HTTPS 的跳转逻辑(location / 里 try_files 再 return 301),这个新 location 必须写在它前面,否则永远跳不到。

三、改之前先备份,改完先测语法

cp -a site.conf site.conf.bak.$(date +%Y%m%d-%H%M%S)
nginx -t && nginx -s reload

nginx -t 一定要跑。alias 少写一个斜杠、location 写错括号,都会让 reload 之后整站 404——而 -t 能提前拦住。

四、一个很坑的验证方式

改完在服务器上执行:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/hc-activity/index.html

如果返回 404,先别急着改配置——很可能是因为 Host 头不匹配。nginx 按 server_name 选虚拟主机,用 127.0.0.1 访问时 Host 是 127.0.0.1,匹配不到 server_name 你的IP 的那个 server 块,于是落到了默认站点,当然 404。

带上 Host 再测就对了:

curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: 你的IP' http://127.0.0.1/hc-activity/index.html

五、最终验收要看两件事

  1. 新路径能开:从一台不在白名单里的机器(比如手机流量)访问,应该 200,且内容正确;
  2. 原有防护没破:访问站点根路径,应该仍然是被拒的状态。

两条都通过,才算真的"只开了一个洞"。

六、小结

deny all 加一个 ^~ 前缀的 location,是这种"整站受限 + 局部公开"需求里改动最小的方案:不用动证书、不用动 443、不用动原有业务配置,出问题回滚一个文件就行。真正的风险不在写法,而在验证方式——用 127.0.0.1 测出 404 就以为配置错了,是最容易浪费时间的地方。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。