Nginx returns 404 当我使用 valid_referers

Nginx returns 404 When I use valid_referers

这是我的环境:

我在生产环境中有两个域。
一个是 fuga.com,它是用 rails 制作的,包含一些首页。

还有一个是hoge.com,是用next.js.

制作的

hoge.com 通常使用 http 请求从 fuga.com 获取数据。
但是,如果我使用浏览器访问 fuga.com/users_data,我会看到所有用户数据。
因为 api 是全局的?
反正安全方面真的很差

所以我想到了阻止 hoge.com 以外的所有域。 我在nginx中配置:

server {
    listen 80;
    server_name fuga.com hoge.com;
    root /var/www/xxx/current/public;

    location / {
        proxy_pass http://xxx;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }
    # ↓here↓
    location /admin {
      valid_referers none blocked server_names hoge\.com;
      if ($invalid_referer) { return 403; }
    }

}

我想阻止除 hoge.com 之外的所有域 /admin/~
所以我用了valid_referers none blocked
根据我的搜索,它是白名单,只能访问。

但是我从nginx的访问日志中得到了这个参数:

172.31.xx.xxx - - [10/May/2022:13:31:58 +0000] "POST /admin/auth/sign_in/ HTTP/1.1" 404 188 "https://hoge.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xxx.0.xxxx.54 Safari/xxx.36" "106.xx.xx.xxx" "-"

状态码为404

所以我尝试 allow 而不是 valid_referers,例如:

...
    location /admin {
      allow 172.xx.xx.xxx;
      deny all;
    }

但是 nginx returns:

172.xx.x.xxx - - [10/May/2022:13:34:12 +0000] "POST /admin/auth/sign_in/ HTTP/1.1" 403 187 "https://hoge.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xxx.x.xxxx.54 Safari/xxx.xx" "xxx.xx.xx.xxx" "-"

我不明白这是怎么回事...
我确定这完全是 nginx 设置的问题。
因为如果我删除 allowvalid_referers 它会正常工作。

我该如何解决这个问题..?

每个请求都在特定位置结束并使用该位置内容处理程序。你不能做类似

的事情
location / {
    ... some settings ruleset
}
location /admin {
    ... additional settings ruleset
}

并预计 /admin/... 请求将使用组合设置规则集。您的第一个位置使用使用 proxy_pass 指令声明的 http_proxy_module 内容处理程序(其他内容处理程序指令示例为 fastcgi_passuwsgi_pass 等)。由于在您的第二个位置没有明确声明任何内容处理程序,nginx 将使用 静态内容处理程序 来处理使用该位置处理的请求(换句话说,将尝试使用一些本地文件),并且因为这样的本地文件不存在,所以给你一个 HTTP 404 Not Found 响应。您可以将您的主要位置内容复制到您的第二个位置(不是最佳方式)或使用其他解决方案,例如 map block:

map $uri $deny {
    ~^/admin  $invalid_referer;
    # default value will be an empty string, so we can omit "default '';" here
}
server {
    ...
    location / {
        if ($deny) { return 403; }
        ... rest of the configuration
    }
}