禁止〖 IP + 端口 〗访问〖 Docker 〗〖 纯 IPv4 版 〗
摘要
这就又回到不可避免的情况,之前 Searxng 和 Seafile 就属于这种,无论怎么弄,都无法从本地服务器的 IPv6 地址把服务构建出去,只能通过另外一台服务器反向代理实现 IPv6 访问,当然反代服务器必须支持 IPv6 地址才行,通过 NAT 映射出去的 IPv6 可以通过反代 upstream 块的方式负载均衡到 IPv6 或者 IPv4 地址,而且不浪费本地服务器原生支持 IPv6 的现状,而且由于是 NAT 转发 IPv6 地址,自然安全方面更容易管理,通过〖 非纯 IPv6 版 〗方式的话,也可以负载均衡,也没有浪费原生现状,但是安全方面天生不具备优势,那么,〖 纯 IPv4 版 〗相比较而言,无法负载均衡,而且浪费原生现状,安全的话可以直接选择不去映射 IPv6 端口,也就是通过 "0.0.0.0:映射端口:容器端口" 的方式实现仅暴露 IPv4 地址的效果,从而避免可能存在的潜在安全隐患,这也算是唯一的可圈之处,防火墙规则的话,只需要设定 IPv4 iptables DOCKER-USER 规则即可,不用再去考虑 IPv6 规则,同时获取 IP 地址时,不需要再指定容器所在的网络,因为是直接默认网络启动的容器,这种情况,有可能容器启动后是 Docker 默认的 bridge 网络,也可能会自动创建一个基于 bridge 的网络,无论哪种情况,都只会造成容器启动后仅有一个网络,所以,不用在脚本中指定网络名称。但是话说回来,除非是特别中意的容器项目,否则真心不想这样使用,太浪费原生 IPv6 地址的支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#!/bin/bash # 获取容器的 IPv4 地址 get_container_ip() { local container_name=$1 docker inspect $container_name | jq -r '.[0].NetworkSettings.Networks | to_entries | .[0].value.IPAddress' } # 最大等待时间为 240 秒,每 1 秒检查一次 MAX_WAIT=240 INTERVAL=1 TIME_WAITED=0 # 定义容器名称和端口映射 declare -A CONTAINERS CONTAINERS=( ["容器名称-容器端口"]="容器端口" # 添加更多容器和端口 ) # 等待 iptables DOCKER-USER 链可用 while [ $TIME_WAITED -lt $MAX_WAIT ]; do if iptables -L DOCKER-USER &> /dev/null; then # 创建 ipset 地址合集(如果不存在) ipset list allowed_ipv4_ips &> /dev/null || ipset create allowed_ipv4_ips hash:ip # 手动添加 IP 地址到 ipset 合集 ipset add allowed_ipv4_ips 放行的 IPv4 地址 || true for key in "${!CONTAINERS[@]}"; do # 分离容器名称和端口 container_name=$(echo $key | sed 's/-[0-9]*$//') port=${CONTAINERS[$key]} # 获取容器的 IPv4 地址 CONTAINER_IP=$(get_container_ip $container_name) if [ -z "$CONTAINER_IP" ]; then continue fi # 定义规则 iptables -I DOCKER-USER 1 -m set --match-set allowed_ipv4_ips src -d $CONTAINER_IP -p tcp --dport $port -j ACCEPT iptables -I DOCKER-USER 2 -d $CONTAINER_IP -p tcp --dport $port -j DROP done exit 0 fi sleep $INTERVAL TIME_WAITED=$((TIME_WAITED + INTERVAL)) done exit 1 |
THE END