我有一个包含以下内容的 docker compose 文件:
nginx-proxy:
image: nginx:1.18.0-alpine
restart: always
ports:
- "80:80"
- "443:443"
networks:
- internal-network
在我的域服务器块中,我添加了
allow MY_IP;
deny all;
但是访问域名时,我总是得到 403。检查日志,我可以看到我的 IP 被记录为121.0.0.0
而不是我的真实 IP 地址。如果我将日志添加到 nginx,add_header X-test "$remote_addr";
我可以看到标头返回,172.19.0.1
我相信这是 docker 内部 IP 地址。
我明白这是因为我正在使用自定义网络internal-network
。
docker 有没有什么办法可以将真正的客户端IP传递给 nginx 容器?
答案1
大多数问题都是因为 nginx 从上到下读取配置
IP限制
在你的例子中
allow MY_IP;
deny all;
看起来不错,因为
Nginx 手册说
ngx_http_access_module 模块允许限制对某些客户端地址的访问。
还可以通过密码、子请求结果或 JWT 来限制访问。通过地址和密码同时限制访问由 satish 指令控制。
示例配置
location / { deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; allow 2001:0db8::/32; deny all; }
按顺序检查规则,直到找到第一个匹配项。在此示例中,仅允许 IPv4 网络 10.1.1.0/16 和 192.168.1.0/24(不包括地址 192.168.1.1)以及 IPv6 网络 2001:0db8::/32 进行访问。如果规则很多,最好使用 ngx_http_geo_module 模块变量。
由于您使用容器,因此您必须在容器中验证哪个 IP 确实已被使用。我建议在验证了哪个 IP 已被使用后,提供一个像 /30 或 /28 这样的小子网来测试它是否只是 LAN-IP。
我以前使用的一些版本有一些固定的 bug,需要先使用拒绝所有行,然后再使用允许。我不确定这是由于自定义源还是我的机器内部的 bug。
基本密码验证
如果您的 IP 经常变化,那么下一种方法通常是更好的解决方案,而不是依赖 IP 认证。
Nginx 文档中关于基本身份验证的说明:
ngx_http_auth_basic_module 模块允许通过使用“HTTP 基本身份验证”协议验证用户名和密码来限制对资源的访问。
访问也可以通过地址、子请求结果或 JWT 进行限制。通过地址和密码同时限制访问由 satish 指令控制。
示例配置
location / { auth_basic "closed site"; auth_basic_user_file conf/htpasswd; }
此外,除了使用 IP 限制之外,根据您想要保护的内容,我建议结合使用密码验证作为更好的做法。
参考: https://nginx.org/en/docs/http/ngx_http_access_module.html https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html