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

ipv6 访问 docker 最优雅的姿势是啥?

  •  
  •   sadfQED2 · 2023-07-25 09:34:28 +08:00 via Android · 6412 次点击
    这是一个创建于 492 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:我自己家里的 nas ,有 ipv6 ,没有公网 ipv4 ,在外想通过 ipv6 访问容器内的服务。

    问题:netstat 命令看了下,docker 只监听了 v4 端口,没监听 v6 端口。

    查到的方案:

    1.https://docs.docker.com/config/daemon/ipv6/ 开启 docker 的 ipv6 ,但这踏马竟然是实验性功能??? docker 这么成熟的东西,ipv6 的支持竟然还在实验?而且他这个支持,并不是我需要的,他这个是给每个容器分配不同的 ipv6 ,外网通过容器 ip 访问。那我人在外,我踏马怎么知道容器 ip 是多少啊

    2.通过 haproxy 转发一下,把 ipv6 端口流量转到 v4 端口上,增加了架构复杂度,以后维护麻烦。

    因此上来问问各种运维大哥,有没有什么优雅一点的姿势啊。

    @ssh 大哥(不记得你 id 了)

    第 1 条附言  ·  2023-07-25 16:24:38 +08:00
    不对,思路歪了,我本意是想如何让 docker 监听 v6 端口,结果变成了讨论使用哪种代理。

    我转念一想,既然都要使用代理了,那我直接把服务部署到物理机不就完事了。使用代理实在是本末倒置。
    49 条回复    2023-07-26 17:42:24 +08:00
    JensenQian
        1
    JensenQian  
       2023-07-25 09:44:41 +08:00
    前面放个 openwrt 的路由器
    然后直接端口转发
    Cabana
        2
    Cabana  
       2023-07-25 09:51:21 +08:00   ❤️ 1
    我的解决方案
    1. nginx 反代 ipv6 的流量到 docker 的 ipv4 端口
    2. docker 的网络路由配置为 host
    chenjia404
        3
    chenjia404  
       2023-07-25 09:59:09 +08:00
    2023 年了,docker 还不默认支持 ipv6
    c1273082756
        4
    c1273082756  
       2023-07-25 10:05:47 +08:00
    openwrt+socat 转发即可
    sadfQED2
        5
    sadfQED2  
    OP
       2023-07-25 10:27:21 +08:00
    @c1273082756
    @JensenQian 大佬,能否细说下,是在 openwrt ,网络->防火墙->端口转发这个地方设置吗。我对 openwrt 不太熟,这里的转发指的是啥?是指所以入站流量都转发吗?假设我需要把请求我 nas 123 端口的 v6 流量转发到 v4 的 123 端口,那我在这里配置”wan and wan6 123 端口 -> lan x.x.x.x 123 端口“ 这样吗? 他这个外部端口指的是对方发起连接的端口还是请求访问的端口呢? 另外,我这样转发,是不是把所有流量都转发了呀?比如请求我家里电脑的 123 端口的流量,也转发到 nas 了?
    sadfQED2
        6
    sadfQED2  
    OP
       2023-07-25 10:29:04 +08:00
    @Cabana nginx 转发跟我用 ha 转发都一样,挺麻烦的,还得多配一套东西。我不太想把服务部署到物理机上面,尽量都用 docker 维护,方便管理。

    我容器网络已经设置成 host 了,依然没监听 v6 端口
    hahasong
        7
    hahasong  
       2023-07-25 10:52:31 +08:00
    docker 不需要单独开启实验性 v6 支持。一是你的服务要支持 v6 ,监听 0.0.0.0 或者[::]:0 这种格式。二是 docker run 的时候指定 --network host 直接使用你 host 的 ip 地址
    villivateur
        8
    villivateur  
       2023-07-25 10:56:27 +08:00
    我来帮你 @ ssh 大哥

    @defunct9
    Cabana
        9
    Cabana  
       2023-07-25 11:17:36 +08:00
    @sadfQED2 #6 加了--network host 没道理不行的, 要么是你的服务本身就不支持 ipv6.
    我的跑 pt 的 Transmission 就是这么跑在 docker 的.
    150530
        10
    150530  
       2023-07-25 11:40:03 +08:00
    我的 docker 没有开 v6 支持,安装的青龙使用-p 映射的端口,可以使用 ipv6 访问,问题应该在于你容器中的应用有没有监听::就和 v4 监听 0.0.0.0 一样,可以用 netstat -atn 查询一下
    kaedeair
        11
    kaedeair  
       2023-07-25 11:40:03 +08:00
    那个 ipv6 是指容器内部的网络,正常使用搞个网关用 host 模式,根据域名分流就搞定了
    ice920
        12
    ice920  
       2023-07-25 12:16:13 +08:00
    docker 没监听 v6 端口,不知道你的 NAS 是不是群晖,应该群晖 DSM6 和 7.2 才支持监听 v6 端口,也可以 -p 映射出来是使用,否则用 Host 网络模式获得 IPv6
    OpenWrt 防火墙 - 通讯规则,开放 NAS 防火墙,限制地址:仅 IPv6 ,协议:TCP+UDP ,目标区域:LAN ,目标地址:::22cd/::ffff ,目标端口:8880 8443 (空格隔开)
    zmcity
        13
    zmcity  
       2023-07-25 13:40:16 +08:00
    需要任意端口入站,小规模部署——Host
    需要任意端口入站,大规模部署——固定前缀+Docker 开 v6 支持 (家宽肯定搞不定固定前缀)
    只需要指定端口入站——Docker 端口转发
    只需要指定端口入站,但希望局域网内可以用 v6 地址访问——Docker 端口转发+EUI 前缀+Docker 开 v6 支持。

    家用的话,像 PT 这种应用直接 Host 模式搞起,还能直接用 nas 的 ddns 访问。
    sadfQED2
        14
    sadfQED2  
    OP
       2023-07-25 13:44:16 +08:00 via Android
    @hahasong 我用的 docker compose ,我查了,说现在还不支持 v6
    sadfQED2
        15
    sadfQED2  
    OP
       2023-07-25 13:48:45 +08:00 via Android
    @ice920 我是 dsm6.2..3
    s1e42NxZVE484pwH
        16
    s1e42NxZVE484pwH  
       2023-07-25 13:49:09 +08:00 via iPhone
    用的软路由里面的 lucky
    ddns 可以直接将 ipv6 和 ipv4 绑定固定域名
    然后端口映射后就可以 ipv6 访问容器
    ttimasdf
        17
    ttimasdf  
       2023-07-25 15:08:02 +08:00
    敢把 NAS 直接放公网上,你也是头铁。

    docker network 最大的作用就是做隔离和 NAT ,你不让人家做 NAT 你不是把它活给抢了。所以对于开发者来说做 ipv6 support 没必要。本来 docker 环境做 firewall rule 就麻烦,现在还想在上面整花活……更没必要了

    上面提 openwrt + socat 的,都 openwrt 了直接从防火墙配置里端口转发梭一下就完事了,还整啥 socat ,还得手写个 init script 麻烦的要死。

    要我说,防火墙和访问控制是个极麻烦的东西,无论是 openwrt 的 fw4 生成还是手写 iptables ,都需要经验,既然你又没经验,我建议就在前面套个 openwrt ,openwrt 上装个 vpn ,openvpn 还是 softether 还是什么 swan 的,随便啥都行,这样攻击面就减小到 vpn 的暴露端口,用 softether 的 vpn over dns/icmp 你甚至一个端口都不用开,里面 NAS 你想 expose 多少个端口都没问题。

    如果不懂,就全部无脑 gui ,openwrt 有 luci ,openvpn 和 strongswan 在 openwrt 上也有 gui ,softether 有个独立管理软件。搞什么 haproxy socat 甚至还有说 nginx 的,真的,不懂就别上。那才是真真正正增加管理难度的
    sadfQED2
        18
    sadfQED2  
    OP
       2023-07-25 15:15:02 +08:00 via Android
    @ttimasdf 兄弟,你先别急,咱就说,有没有可能,我说可能,我 vpn 是通过 docker 安装在 nas 上面的,我现在就是需要把端口暴露到公网上。
    JensenQian
        19
    JensenQian  
       2023-07-25 15:15:14 +08:00
    @sadfQED2 #5
    我么看懂楼主的需求
    楼主是要外面 v6 也能访问你 ddns 家里的 docker 吗
    网络防火墙那边可以,我 lede 的固件没法用这个转发,装了个 socat
    外部访问啊就直接 ddns 的域名:端口就行
    [img][/img]
    不过这样子很不安全,我的建议是你搞个 openvpn 或者 wireguard 回家然后访问
    leonshaw
        20
    leonshaw  
       2023-07-25 15:21:05 +08:00
    还得做 NAT ,不光是 docker 的问题,IPv6 就没想明白公私域怎么解耦
    sadfQED2
        21
    sadfQED2  
    OP
       2023-07-25 15:35:51 +08:00 via Android
    @JensenQian 不是,我并不需要 ddns ,我不需要域名。我直接用 ipv6 的地址连回来就行了。

    我仔细研究了上面提到的路由器转发,这样结果变成了请求路由器 ip ,然后转发到 nas 。这样搞的话需要我访问 openwrt 地址,然后转发过去。

    但是我有注册中心,nas 会实时上报自己的 ip 到注册中心,我 vpn 实时从注册中心拉取地址,拉到的是 nas 地址,搞成路由器地址就废了
    sadfQED2
        22
    sadfQED2  
    OP
       2023-07-25 15:36:29 +08:00 via Android
    @leonshaw 是的,就是这个问题。我就是想问问有啥优雅的办法解决
    defunct9
        23
    defunct9  
       2023-07-25 15:51:54 +08:00
    听到有人在叫我。

    换我来干的话,也是前面架个 nginx+ipv6 ,因为 k8s 就这么干的,学就是了。

    那复杂一点的搞法就是用 wg 直连到我自己的 AS ,随便分点 ipv6 得了。
    AkibaSo
        24
    AkibaSo  
       2023-07-25 15:54:04 +08:00   ❤️ 1
    @sadfQED2 楼上说了 指定 network 为 host ,docker compose 同样可以指定 network_mode: 'host',这样就可以通过你 nas 的 ipv6 访问你的服务,实在不行你还可以用 ipv6 nat
    sadfQED2
        25
    sadfQED2  
    OP
       2023-07-25 15:57:44 +08:00 via Android
    @Cabana 我需要代理 tcp 流量,看了一眼我群晖上面的 nginx ,没有装 stream 模块,于是我尝试自己编译,又少了一万个依赖,吐了
    des
        26
    des  
       2023-07-25 15:57:54 +08:00
    看看这个 16 楼和 46 楼是不是你想要的 https://v2ex.com/t/955636
    sadfQED2
        27
    sadfQED2  
    OP
       2023-07-25 15:59:54 +08:00 via Android
    @defunct9 大哥你终于来了,nginx 没 stream 模块,自己编译又没依赖。

    又尝试装 ha ,结果 ha 也得自己编译,也没编译环境
    defunct9
        28
    defunct9  
       2023-07-25 16:02:03 +08:00
    @sadfQED2 不想编译就 traefik 、caddy
    sadfQED2
        29
    sadfQED2  
    OP
       2023-07-25 16:03:35 +08:00 via Android
    @des 这真的是,太太太复杂了,所以我才提问,有没有优雅一点的解决方案,这种方案,以后的维护成本简直上天,特别是半年一年以后,都忘了之前是咋配置的了,那时候排查问题,简直要命
    sadfQED2
        30
    sadfQED2  
    OP
       2023-07-25 16:12:31 +08:00
    @defunct9 #28 看了一下这 2 个的介绍,这两个似乎不支持 tcp 、udp 的代理吧,这两个好像都是 http 的代理。另外,用啥代理都不是啥大问题。大问题是,机器上没有 systemctl ,没有 supervisor ,服务没法保活。
    yinmin
        31
    yinmin  
       2023-07-25 16:51:25 +08:00 via iPhone
    @sadfQED2 #27 解决方法:docker 部署 nginx
    ice920
        32
    ice920  
       2023-07-25 17:20:33 +08:00
    @sadfQED2 #15 不知道你的问题是否是我理解的问题,看你的 docker 版本,20.10.3 是不能监听 v6 端口,貌似在 20.10.6 版本后解决,但群晖套件之前只有 20.10.3 和 18.09 ,以及现在最新的 DSM7.2 是 20.10.23
    sadfQED2
        33
    sadfQED2  
    OP
       2023-07-25 17:36:13 +08:00 via Android
    @ice920 有可能是 docker 版本太低的问题,打死都不监听 v6 端口。
    zygame
        34
    zygame  
       2023-07-25 17:40:14 +08:00
    所以这就是路由被误解之后造成的问题,NAT Gateway 本身就不是 Router
    v4 时代你们在 Gateway 上弄的那一套花活,根本不是在 Router 上用的,v6 有了公网 IP 你的所有策略都要改变。
    就算你 v6 无限制直接公布在网上,传统的扫描器扫一个 60 段的时间你算过么……而且是每次都会换的 60 段,你在担心什么?
    安啦
    blackmirror
        35
    blackmirror  
       2023-07-25 17:40:15 +08:00
    docker 不是默认 ipv6 优先的?
    AlanBrian
        36
    AlanBrian  
       2023-07-25 17:54:08 +08:00
    {
    "ipv6": true,
    "fixed-cidr-v6": "fc00:17:1:1::/64",
    "experimental": true,
    "ip6tables": true
    }
    我之前这么配置是可以通过宿主机的 ipv6 访问容器的。
    kaedeair
        37
    kaedeair  
       2023-07-25 18:02:54 +08:00
    上面已经简短介绍了一下方法,可能不够详细
    我来说一下我的方案吧,是已经实践成功,稳定运行半年的;希望对你有所帮助

    系统是 pve
    网关使用 docker 部署的 traefik ,网络模式使用 host(这里使用 host 的原因是因为我后面几个服务是 PT 和 BT 需要 ipv6 地址,容器网络也选择的是 host ,能不能 bridge 模式需要自行测试,理论上是可行的,因为我看到绑定宿主机 web 端口是监听 ipv6 的),后面几个不需要 ipv6 的服务是 bridge
    由于 docker 的 iptables 优先于 pve 的,我关闭了 docker 的 iptables ,同时增加了网络为 bridge 容器所在网段到 docker0 的 MASQUERADE(防止容器不能上网),这样我就只对外暴露了单个 web 端口
    对后面容器服务的访问控制是通过 traefik 里面域名规则配置的

    对楼上回复的补充:traefik 是支持 tcp 和 udp 的并不是只支持 http
    yylang1984
        38
    yylang1984  
       2023-07-25 18:21:18 +08:00
    用 host 模式就好了
    lovelylain
        39
    lovelylain  
       2023-07-25 18:30:48 +08:00 via Android
    通过 nginx 反代 ipv6 到容器 ipv4 ,nginx 跑在 host 容器或者宿主机上,对于容器内的 web 服务,通过 xff 传递客户端 ip ,非 web 服务暂时没想到什么办法传递 ip 。
    Jirajine
        40
    Jirajine  
       2023-07-25 18:38:12 +08:00
    这是 docker 的问题,docker 的网络非常垃圾,或者说是非常特化的,用 docker 就得 docker 按照它自己的方式为你管理地址,或者手动静态管理地址。
    任何非 docker 设计的标准网络使用,都不该用 docker ,与其对着 docker 一顿 hack ,不如直接 lxc ,想怎么配就怎么配。
    lentrody
        41
    lentrody  
       2023-07-25 19:05:15 +08:00
    你用的什么 DDNS ? docker 的 IPv6 地址是 EUI64 生成的固定后缀吗?
    如果是固定后缀那么就可以通过任意一个地址的前缀拼接得到其他所有设备的完整地址,有些 DDNS 服务商比如 dynv6 可以自动这样拼接地址并关联到子域名。
    whetherTsmile
        42
    whetherTsmile  
       2023-07-25 22:05:43 +08:00
    docker 只监听了 v4 端口,没监听 v6 端口
    你可以看下 io 和 docker0 端口有没有 inet6 ,然后看下 net.ipv6.conf.lo.disable_ipv6 开了没
    neroxps
        43
    neroxps  
       2023-07-25 22:25:28 +08:00 via iPhone
    @sadfQED2 dsm 7 已经支持了吧 dsm 6.2 内核是不支持 ipv6 nat 。用工具转发或是路由 66nat 吧
    iceheart
        44
    iceheart  
       2023-07-26 07:16:31 +08:00 via Android
    同意 #40 用 lxc+lxd 就完了,哪有这么多事
    wheat0r
        45
    wheat0r  
       2023-07-26 10:33:00 +08:00
    可以通过 docker compose 指定网络和容器的 ipv6 子网信息,但是你似乎没有办法让容器自动获取 RA 出来的地址。所以如果你的 ipv6 地址是运营商给的、每次拨号会变的地址,那就不用折腾了。
    vicv
        46
    vicv  
       2023-07-26 11:39:49 +08:00
    我和你的使用情景是一样的,移动有公网 IPv6 没有公网 IPv4 。我是群晖 NAS ,我的做法是这样的:光猫开启桥接模式,让主路由器进行拨号,这样的话路由器下的设备都可以拿到 IPv6 地址(这里其实有安全风险,但是一般很少人会扫描 IPv6 网络)。群晖的 docker 配置中启用 IPv6 支持,创建一个新的 docker 网络并使用 docker 的 macvlan 驱动桥接到群晖的物理网卡,然后使用了这个网络创建的容器就相当于在直接连接到路由器上的一个设备,可以获得路由器分配的一个内网 IPv4 地址以及公网的 IPv6 地址(不需要 IPv6 的容器不使用这个 docker 网络就可以了)。然后使用 jeessy/ddns-go 这个 docker 镜像来对容器的 IPv6 地址做 ddns 解析,然后在外网就可以愉快地通过域名访问内网的 IPv6 服务了。
    yzkos
        47
    yzkos  
       2023-07-26 15:06:22 +08:00
    我群晖现在就是通过 ipv6 访问的,但是完全没有配置过 ipv6 这些东西,只要 nas 有 ipv6 公网,开放的端口 ipv6 就能访问到。

    群晖 docker 软件界面有两个网络 bridge 和 host ,
    如果你的容器使用 bridge 用 ipv6 是访问不了的,可以在控制面板-》 synology 应用程序门户-》反向代理服务器,添加一个新的端口号对 docker 的端口反代就可以用 ipv6 访问了。例如 docker 映射端口是 5244 ,在反向代理里面新增一个 5243 反代到 http://localhost:5244 ,使用 ipv6:5243 就能公网访问了。
    如果是使用 host 里面就能 ipv6 加端口直接访问。

    我的两个里面显示都是 ipv6 已禁用,不耽误外网直接访问。
    tsanie
        48
    tsanie  
       2023-07-26 16:51:35 +08:00
    我的也是,群晖本身有 IPv6 ,没有修改过 docker 配置,网络里面 IPv6 都是 Disabled ,有些服务比如 gitea 用自带的反代到 localhost 映射出来的端口,有些服务比如 aria 设置的--network=host ,这些服务都能走外部由 IPv6 访问,例如手机流量。

    办公室没有 IPv6 就走的 zerotier 虚拟组网,另外又弄了个 cloudflare tunnel 作为备用线路。
    ttimasdf
        49
    ttimasdf  
       2023-07-26 17:42:24 +08:00
    好吧,我们分类讨论

    要解决你的需求,你既然容器里有 vpn 了,你也通过 vpn 访问,那直接把需要访问的容器拉个子网,通过 alias 访问即可

    要回答你的问题,非得暴露 ipv6 的话,SO 说行,https://serverfault.com/a/1054917
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5071 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:45 · PVG 17:45 · LAX 01:45 · JFK 04:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.