IPv6 的地址空间很大,在 SLAAC 的配置下很难被外部主动扫到。但是通过自己的主动访问暴露,例如浏览恶意网站、运行 p2p 应用等,还是可能的。这种暴露的风险相比公网 IPv4 要小不少、而且设备自身的安全建设也更加根本,但如何采取其他措施加以预防也值得讨论。IPv4 时代的传统解决方案是防火墙,可是目前 IPv6 路由器的防火墙功能普遍残缺,即使有也需要固定机器的后缀。同时 PCP 等自动化机制也缺少应用,日常配置起来还是颇为麻烦。
楼主认为,IPv6 时代应该适应每台机器都是公网的零信任环境,不应该过度依赖网关和内网来保证安全。对于之前提到的暴露风险,如果转换思路,可以想到利用 IPv6 超大的地址空间,给 bt 、ipfs 这类应用分配独立的地址,从而仅把安全的、与敏感数据隔离的服务主动暴露给外部。搜了一下,IPv6 环境下一机多 IP 成熟的经验还比较少。虽然也存在一些麻烦,但个人感觉自动化的潜力比较很大。在此,楼主想分享在不同场景下非常初步的经验,希望可以起到抛砖引玉的作用:
一、服务器场景
提供 IPv6 的商家,有的是给一个子网随便玩,有的是需要论个申请但可以申请一堆,仅有少数是只能用一个的(如 Lightsail )。
由于服务端 IP 比较固定,通常比较好配置,同时可以沿用一些多公网 IPv4 的经验。
基本的玩法就是监听时不再写[::]:80 ,而是绑定[IPv6]:80 ,这样多个服务就可以分别通过独立的 IPv6 地址访问、解析。特别是当端口打架的时候,就不再需要基于 Host 或者 SNI 的反代来分流了。即使一个源站 IP 暴露了,相对不容易牵连其他服务,也便于换一个新的。
二、家用 PC 场景
在 Windows 下如何让一个应用的所有入站和出站都走指定的 IP 地址,除了虚拟机暂时没有想到很好的方法。
楼主在家宽环境下用 VMware 实测,当网络配置为桥接模式(不复制物理主机状态),虚拟机中的 Windows 和 Ubuntu 都可以获得独立于主机的 SLAAC IPv6 地址,且都可以被公网访问。traceroute 不会经过宿主的 IPv6 地址。其他虚拟化软件还未测试。
三、家用 NAS 场景
在 NAS 配置服务常用的是 Docker 。虽然 Docker 支持 IPv6 ,但相关的功能感觉还比较简单,很多时候需要固定的 CIDR 。楼主见过的 Docker+IPv6 玩法,一种是配 IPv6 私有地址然后做转发,还有一种是主机模式直接用宿主的地址。如果只是为了能用公网,后者相对简单。但想用独立的公网 IPv6 地址,就需要其他的方法。其中,bridge 模式虽然可行(需手动处理 NAP ),但会增加主机网关的一跳,从而暴露宿主的 IP 地址。所以这里以 IPvlan 模式为例,提供一个原理验证流程:
1.建立网桥
假设网卡为 eth0
docker network create -d ipvlan \ --ipv6 --subnet=$ip/80 \ -o parent=eth0 v6ipvlan1 其中$ip可以从公网 IP 裁切( curl -6 ip.sb ),也可以直接指定私网 IP ( fd00::)。无论那种,容器都可以额外从配置 SLAAC 的网关获得的公网 IPv6 地址。
2.运行一个能响应 Web 的 Docker
docker run --name socat --rm --net=v6ipvlan1\ alpine/socat -v -d -d \ TCP6-LISTEN:12080,crlf,reuseaddr,fork \ SYSTEM:" echo HTTP/1.1 200 OK; echo Content-Type\: text/plain; echo; echo \"Server: \$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT\"; echo \"Client: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\"; " 3.进到容器里看看
docker exec -it socat sh 查询本容器的公网 IPv6 (设为 2400:11:22:33:aa:bb:cc:dd )
ip addr 有时需要有主动的 IPv6 出站才能打通,例如:
ping6 240c::6666 至此,只要没有其他防火墙拦着,[2400:11:22:33:aa:bb:cc:dd]:12080 应该就可以从外部访问了。
由于地址独立于宿主生成,且 traceroute 不会经过宿主的一跳,或可以避免宿主和其他容器公网 IPv6 的暴露。
需要重申的是,以上仅是粗糙的原理验证,希望可以启发更多关于多 IP 玩法的讨论。
其他问题
-
动态 IP 下指定后缀
很多时候后缀直接用 SLAAC 的就完事了( bt 、ipfs ),也可以在 Docker 内跑个 DDNS ( crontab+sh 脚本)。
但如果确需要指定,因为 Shell 处理 IPv6 地址比较麻烦,且网桥可能还得重新建立,所以暂时还未有自动化方案。 -
公网 v6 的非预期暴露
从之前的 docker 命令可以看出,配置公网 IPv6 后,docker 内部对[::]的监听即是对公网的监听,不需要 -p 来映射。
但容器的制作和使用者仍可能延续 NAT 时代的惯性,默认内网安全,从而导致端口意外暴露在公网。
