禁止〖 IP + 端口 〗访问〖 Docker 〗〖 非纯 IPv6 版 〗
摘要
之前提到过 Seafile 不支持原生形式的 IPv6 地址访问,类似的容器肯定不在少数,这些容器只能使用默认 Docker bridge 网络,然后借助服务器公网 IPv6 地址加端口的方式,可以实现 IPv6 访问,但是容器内部没有 IPv6 内网地址,这种方式,如果要实现禁止〖 IP + 端口 〗访问〖 Docker 〗之目的,就比较特殊,所以叫〖 非纯 IPv6 版 〗,因为尽管不是纯的,但是变相的可以通过 IPv6 访问。在定义规则时,需要把 IPv4 和 IPv6 分开处理,对于 IPv4 需要定义 iptables DOCKER-USER 规则,而 IPv6 需要直接定义 iptables INPUT 规则。关键点在于,需要定义容器的端口和宿主的端口,用来分别用于 DOCKER-USER 规则和 INPUT 规则。
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 44 45 46 47 48 49 50 51 52 |
#!/bin/bash # 获取容器的 IPv4 地址 get_container_ip() { local container_name=$1 docker inspect $container_name | jq -r '.[0].NetworkSettings.Networks["bridge"].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_bridge_ips &> /dev/null || ipset create allowed_bridge_ips hash:ip ipset list allowed_bridge_ipv6_ips &> /dev/null || ipset create allowed_bridge_ipv6_ips hash:ip family inet6 # 手动添加 IP 地址到 ipset 合集 ipset add allowed_bridge_ips IPv4地址 || true ipset add allowed_bridge_ipv6_ips IPv6地址 || true for container_name in "${!CONTAINERS[@]}"; do # 分离容器名称和端口 ports=${CONTAINERS[$container_name]} IFS=':' read -r container_port host_port <<< "$ports" # 获取容器的 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_bridge_ips src -d $CONTAINER_IP -p tcp --dport $container_port -j ACCEPT iptables -I DOCKER-USER 2 -d $CONTAINER_IP -p tcp --dport $container_port -j DROP ip6tables -A INPUT -p tcp -m multiport --dports $host_port \ -m set --match-set allowed_bridge_ipv6_ips src \ -m comment --comment "Allow access to port $host_port from allowed IPs" \ -j ACCEPT ip6tables -A INPUT -p tcp --dport $host_port \ -m comment --comment "Block access to port $host_port for all other sources" \ -j DROP done exit 0 fi sleep $INTERVAL TIME_WAITED=$((TIME_WAITED + INTERVAL)) done exit 1 |
THE END