关于 Docker 容器获取真实 IP
使用portainer的stack部署容器的时候应该如何返回真实 IP ?
version: '3'
services:
webdav:
image: ghcr.io/hacdias/webdav
container_name: webdav
restart: always
ports:
- "10001:6065"
volumes: - /storage/docker_data/webdav/config.yml:/config.yml:ro
- /storage/docker_data/webdav/data:/data
command: -c /config.yml
使用 stack docker compose 部署容器的时候,docker 会自动生成一个以 stack 命名的网桥, 比如这个 stack 名叫 webdav
比如刚刚生成的容器就自己创建了一个自己的网桥,容器的 IP 地址是 172.19.0.2,网关是 172.19.0.1
Bridge:
Name
Stack LT
Driver
Attachable
IPAM Driver
IPV4 IPAM Subnet
IPV4 IPAM Gateway
webdav_default
webdav
bridge
false
default
172.19.0.0/16
172.19.0.1
location / {
proxy_pass 127.0.0.1:10001;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
用 nginx 进行反向代理的时候,我进入容器的后台发现2024-10-18T03:01:09.536Z INFO login attempt {"username": "aaaa", "remote_address": "172.19.0.1:57548"}
2024-10-18T03:01:09.536Z INFO user authorized {"username": "aaaa"}
2024-10-18T03:02:13.219Z INFO login attempt {"username": "aaaa", "remote_address": "172.19.0.1:56084"}
容器只能检测到它网关的信息,有老哥知道如何解决? 无法获得真正的 IP 地址
不仅仅是 webdav 其他的容器都是这样, 类似的还有 bitwarden 等等。。
network_mode: "host"
你需要的是 网关+ 服务发现 + 注册中心 + 应用服务注册
我的 nginx 这样是可以获取到真是 ip 的proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Referer $http_referer; #header_referer endproxy_set_header Host $host; #header_host end当然还需要容器本身支持这些 header 才行,有些容器还需要额外配置,例如 traefik 需要加 trustedIPs 配置才行。
macvlan 或者 host 吧,一般的容器本身都没有填写真实 IP 的环境变量
OP 的理解有误,webdav 本质上获取的是 nginx ip ,因为 wevdav 的 tcp 源地址是 nginx ,不是客户端 ip
目前想做到的是让容器获取客户端 IP 地址, 有没有什么优雅的方式?目前尝试了以下两种方案:docker compose .... restart: always ports: - target: 6065 # 容器内部端口 published: 10001 # 主机端口 protocol: tcp mode: host # 使用 host 模式发布端口 ....log 与一开始的完全相同docker-compose .... restart: always network_mode: host # 将网络模式设置为 host ....修改成 host 获取到的就是 127.0.0.1 了log2024-10-18T04:06:58.316Z INFO listening {"address": "[::]:6065"}2024-10-18T04:07:03.282Z INFO login attempt {"username": "kivvi", "remote_address": "127.0.0.1:53372"}2024-10-18T04:07:03.282Z INFO user authorized {"username": "kivvi"}
你把 docker 理解成一个虚拟机就行了,
host 模式
到底是获取真实 IP 地址还是返回真实 IP 地址?
nginx 配置改这行试试proxy_set_header X-Forwarded-For $remote_addr;
搭楼问问 docker 的 host 模式一般用于解决什么问题?
使用宿主机网络的场景,比如获取宿主机的网络详情,见 node exporter
nginx 里这样设置看看: real_ip_header proxy_protocol; real_ip_recursive on; set_real_ip_from 桥接的网关 ip;
两个问题:第一,你的 nginx 是怎么部署的?从你的描述来看,我猜你的 nginx 也是通过容器部署的?第二,你 webdav 使用 host 网络模式的时候,客户端是怎么请求的?直接请求 webdav 容器的端口,还是依然请求的 nginx 的端口?我猜你仍然是请求的 nginx 的端口?
程序无关tcp 协议要用 proxy_protocol 或者 toa (放 tcp option 里)之类的技术http 协议就用 X-Forwarded-For header
让你的反向代理服务器设置 X-Forwarded-For参考: github.com/hacdias/webdav/blob/a5777e18eec8db635657e972940fa8e545876bca/lib/handler.go#L169
获取到了的吧,获取请求头 X-Real-IP 的信息,不要取 remot_addr
做个代理就好了。
修正日志格式
我这种懒 b 最爱
你的部署环境是什么样的,nginx 是在物理机上吗?如果是在虚拟环境中,情况又不一样了。假定你的 nginx 在物理机上,可以这么先排查下:1.起个 whoami 容器,看看 X-Forwarded-For 里有没有真实 ip 。2.如果没有,去检查 nginx 有没有拿到真实 ip ,再排查 nginx 配置文件。3.如果有,就是容器本身的问题,容器没有从 X-Forwarded-For 获取 ip ,而是从 remote_addr 拿到网关了地址。找找容器没有对应的变量或设置之类的。只要 nginx 配置正确,容器本身有从 X-Forwarded-For 获取 ip 的设置,docker 不需要做什么设置,真实 ip 都能正常传递进去,用不用 host 模式,都是可以获取真实 ip 的。
解决了,X-Forwarded-For 配置的有问题,谢谢老哥们
#22 佬,最后咋配的 nginx ,配置贴一下
如题,现在是两块 18T 组的 RAID1 ,现在想购置新硬盘,原本想 RAID1 升级 RAID5 ,看到了好多 RAID5 炸盘后重建炸裂的问题,我的数据没什么重要的,大多…
作为一个 java 后端,现在在上手公司的 vue3 项目,对象基本靠 log 来查看理解。感觉好不习惯... 没看懂.. 没啥说法,大多数原因是时间不够呗。。。如果时间足…
一个葡萄牙的学生写了一篇文章 《How much GNU is there in GNU/Linux?》 – GNU/Linux下有多少是GNU的。他的这篇文章主要…
合速度