V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Aliberter
V2EX  ›  Docker

求助大佬们, docker 内的 springboot 项目如何获取 http 请求的真实 ip?

  •  
  •   Aliberter · 2021-11-26 09:19:03 +08:00 · 2581 次点击
    这是一个创建于 1101 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现有代码如下:

        public static String getIpAddress(HttpServletRequest request) {
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            return ip;
        }
    

    目前测试服务器,没有 Nginx ,没有域名解析,直接请求服务器的 ip+端口的,实际最后都是走到 ip = request.getRemoteAddr(),然后取到的是 172 开头的 docker 内网 ip ,试了试--net=host 也不管用,访问不通了就,不太懂 docker 网络这块,求助大佬们。

    14 条回复    2021-11-26 12:19:02 +08:00
    Aliberter
        1
    Aliberter  
    OP
       2021-11-26 09:30:41 +08:00
    我看百度上,大部分都是在外边加一层 nginx ,提前配置好代码里这些请求头啥的,然后后面走到代码里也就能直接取取来请求头的值,就是用户的真实 ip 了,不知道是否可行~
    hopingtop
        2
    hopingtop  
       2021-11-26 09:46:36 +08:00
    remoteAddr 是真正连接你服务端的 IP ,但是往往一次网络请求可能会经过几层网络代理,那么你渠道的 IP 就是最后一层代理,并不是真的 ClientIP 。
    因为 Docker 他有网络模式,默认情况下( bridge )所以他其实就是相当于一层代理了。
    hopingtop
        3
    hopingtop  
       2021-11-26 09:47:54 +08:00
    @hopingtop 但是 HOST 网络模式应该和宿主机共享 Namespace ,如果中间没有其他代理,按理能取到 IP
    hopingtop
        4
    hopingtop  
       2021-11-26 09:48:53 +08:00   ❤️ 1
    @hopingtop ..... 按了几次 CTRL 回车,导致就没有回答完。。。狗头。。。

    Docker 使用了 Linux 的 Namespaces 技术来进行资源隔离,如 PID Namespace 隔离进程,Mount Namespace 隔离文件系统,Network Namespace 隔离网络等。一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、Iptable 规则等都与其他的 Network Namespace 隔离。

    host 模式类似于 Vmware 的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。一个 Docker 容器一般会分配一个独立的 Network Namespace 。但如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace ,而是和宿主机共用一个 Network Namespace 。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
    wolfie
        5
    wolfie  
       2021-11-26 09:54:05 +08:00   ❤️ 1
    一般都从 x-forwarded-for 拿,多个网关会包含多个 ip ,逗号分隔。
    也有 x-real-ip 的情况。
    rationa1cuzz
        6
    rationa1cuzz  
       2021-11-26 10:06:21 +08:00   ❤️ 1
    --net=host 按道理应该使用宿主机的 ip 端口,访问不通是不是端口被占用了?
    Aliberter
        7
    Aliberter  
    OP
       2021-11-26 10:09:13 +08:00
    @hopingtop 多谢大佬,我拜读一下
    Aliberter
        8
    Aliberter  
    OP
       2021-11-26 10:10:51 +08:00
    @rationa1cuzz 对,解决了,--net=host 确实管用,我重新给防火墙开了这个端口才通了,但是有个疑问就是,之前一直用端口映射的时候,我记得我加过防火墙,而且也一直是通的,能用的,改成这个模式后,又加了一遍才通,真搞不懂。
    xueyuanh
        9
    xueyuanh  
       2021-11-26 10:48:59 +08:00
    @rationa1cuzz 用了--net=host 容器是不是就会把机器的 80 端口给占用了,之前用 docker 启一个 nginx ,一直占用 80 端口,但是 nginx 的默认监听端口已经被我换成别的了,最后去掉--net=host 才正常
    rationa1cuzz
        10
    rationa1cuzz  
       2021-11-26 11:15:27 +08:00
    @xueyuanh 是的,你可以 lsof 或者 netstat 看一下就知道了,你可以看看这个 https://docs.docker.com/network/
    pixiaotiao
        11
    pixiaotiao  
       2021-11-26 12:16:23 +08:00 via Android
    一层一层传过来
    yangyaofei
        12
    yangyaofei  
       2021-11-26 12:16:55 +08:00
    不知道这个可以不可以, 当时 https nginx 转发的时候也会遇到这个问题, 加这个配置解决的:

    ```yaml
    server:
    port: 8080
    address: 0.0.0.0
    # Enable HTTPS When Running behind a Proxy Server
    # https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.security.enable-https
    tomcat:
    remoteip:
    remote-ip-header: "x-forwarded-for"
    protocol-header: "x-forwarded-proto"

    ```
    yangyaofei
        13
    yangyaofei  
       2021-11-26 12:18:39 +08:00
    ```
    server:
    port: 8080
    address: 0.0.0.0
    # Enable HTTPS When Running behind a Proxy Server
    tomcat:
    remoteip:
    remote-ip-header: "x-forwarded-for"
    protocol-header: "x-forwarded-proto"

    ```
    yangyaofei
        14
    yangyaofei  
       2021-11-26 12:19:02 +08:00
    这个 markdown 不好用啊 😂😂😂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2861 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:33 · PVG 20:33 · LAX 04:33 · JFK 07:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.