• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ztfot
V2EX  ›  程序员

关于 Docker 容器获取真实 IP

  •  
  •   ztfot · Oct 18, 2024 · 8773 views
    This topic created in 585 days ago, the information mentioned may be changed or developed.

    使用portainerstack部署容器的时候应该如何返回真实 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 http://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 等等。。
    23 replies    2024-10-20 21:30:23 +08:00
    asuraa
        1
    asuraa  
       Oct 18, 2024
    network_mode: "host"
    yuanxing008
        2
    yuanxing008  
       Oct 18, 2024
    你需要的是 网关+ 服务发现 + 注册中心 + 应用服务注册
    Curtion
        3
    Curtion  
       Oct 18, 2024
    我的 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 end
    proxy_set_header Host $host; #header_host end


    当然还需要容器本身支持这些 header 才行,有些容器还需要额外配置,例如 traefik 需要加 trustedIPs 配置才行。
    long1and
        4
    long1and  
       Oct 18, 2024
    macvlan 或者 host 吧,一般的容器本身都没有填写真实 IP 的环境变量
    yinmin
        5
    yinmin  
       Oct 18, 2024 via iPhone
    OP 的理解有误,webdav 本质上获取的是 nginx ip ,因为 wevdav 的 tcp 源地址是 nginx ,不是客户端 ip
    ztfot
        6
    ztfot  
    OP
       Oct 18, 2024
    目前想做到的是让容器获取客户端 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 了
    ```log
    2024-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"}
    ```
    asuraa
        7
    asuraa  
       Oct 18, 2024
    你把 docker 理解成一个虚拟机就行了,
    Tink
        8
    Tink  
    PRO
       Oct 18, 2024
    host 模式
    wheat0r
        9
    wheat0r  
       Oct 18, 2024
    到底是获取真实 IP 地址还是返回真实 IP 地址?
    yinmin
        10
    yinmin  
       Oct 18, 2024 via iPhone
    nginx 配置改这行试试

    proxy_set_header X-Forwarded-For $remote_addr;
    gvdlmjwje
        11
    gvdlmjwje  
       Oct 18, 2024
    搭楼问问 docker 的 host 模式一般用于解决什么问题?
    bigbugbag
        12
    bigbugbag  
       Oct 18, 2024   ❤️ 1
    @gvdlmjwje 使用宿主机网络的场景,比如获取宿主机的网络详情,见 node exporter
    handwork
        13
    handwork  
       Oct 18, 2024
    nginx 里这样设置看看:

    real_ip_header proxy_protocol;
    real_ip_recursive on;
    set_real_ip_from 桥接的网关 ip;
    execute
        14
    execute  
       Oct 18, 2024
    两个问题:第一,你的 nginx 是怎么部署的?从你的描述来看,我猜你的 nginx 也是通过容器部署的?第二,你 webdav 使用 host 网络模式的时候,客户端是怎么请求的?直接请求 webdav 容器的端口,还是依然请求的 nginx 的端口?我猜你仍然是请求的 nginx 的端口?
    rrfeng
        15
    rrfeng  
       Oct 18, 2024   ❤️ 1
    程序无关
    tcp 协议要用 proxy_protocol 或者 toa (放 tcp option 里)之类的技术
    http 协议就用 X-Forwarded-For header
    Hardrain
        16
    Hardrain  
       Oct 18, 2024   ❤️ 1
    GG668v26Fd55CP5W
        17
    GG668v26Fd55CP5W  
       Oct 18, 2024 via iPhone
    获取到了的吧,获取请求头 X-Real-IP 的信息,不要取 remot_addr
    lelehub
        18
    lelehub  
       Oct 18, 2024
    做个代理就好了。
    GG668v26Fd55CP5W
        19
    GG668v26Fd55CP5W  
       Oct 18, 2024 via iPhone
    修正日志格式
    duzhuo
        20
    duzhuo  
       Oct 18, 2024
    @gvdlmjwje 我这种懒 b 最爱
    anciusone
        21
    anciusone  
       Oct 19, 2024
    你的部署环境是什么样的,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 的。
    ztfot
        22
    ztfot  
    OP
       Oct 19, 2024
    解决了,X-Forwarded-For 配置的有问题,谢谢老哥们
    DaFengChe
        23
    DaFengChe  
       Oct 20, 2024
    @ztfot #22 佬,最后咋配的 nginx ,配置贴一下
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1009 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 72ms · UTC 19:14 · PVG 03:14 · LAX 12:14 · JFK 15:14
    ♥ Do have faith in what you're doing.