فهرست منبع

fix: IP blacklist and whitelist logic, optimize performance.

dqzboy 1 سال پیش
والد
کامیت
df5027cb98
2فایلهای تغییر یافته به همراه347 افزوده شده و 147 حذف شده
  1. 1 1
      README.md
  2. 346 146
      install/DockerProxy_Install.sh

+ 1 - 1
README.md

@@ -20,7 +20,7 @@
 [![GitHub license](https://img.shields.io/github/license/dqzboy/Docker-Proxy)](https://github.com/dqzboy/Docker-Proxy/blob/main/LICENSE)
 
 
-📢 <a href="https://t.me/+ghs_XDp1vwxkMGU9" style="font-size: 15px;">Docker Proxy-TG交流群</a> 
+📢 <a href="https://t.me/+ghs_XDp1vwxkMGU9" style="font-size: 15px;">Docker Proxy-交流群</a>
 
 </div>
 

+ 346 - 146
install/DockerProxy_Install.sh

@@ -3064,172 +3064,372 @@ esac
 
 # IP 黑白名单
 function IP_BLACKWHITE_LIST() {
-if ! command -v iptables &> /dev/null
-then
-    WARN "iptables 未安装. 请安装后再运行此脚本."
-    exit 1
-fi
-IPTABLES=$(which iptables)
+    if ! command -v iptables &> /dev/null
+    then
+        WARN "iptables 未安装. 请安装后再运行此脚本."
+        exit 1
+    fi
+    IPTABLES=$(which iptables)
+
+    BLACKLIST_CHAIN="IP_BLACKLIST"
+    WHITELIST_CHAIN="IP_WHITELIST"
+    WHITELIST_FILE="/etc/firewall/whitelist.txt"
+    BLACKLIST_FILE="/etc/firewall/blacklist.txt"
+
+    # 确保文件存在
+    mkdir -p /etc/firewall
+    touch $WHITELIST_FILE $BLACKLIST_FILE
+
+    get_chain_name() {
+        local chain=$1
+        case $chain in
+            $BLACKLIST_CHAIN) echo "黑名单" ;;
+            $WHITELIST_CHAIN) echo "白名单" ;;
+            *) echo "未知名单" ;;
+        esac
+    }
 
-BLACKLIST_CHAIN="IP_BLACKLIST"
-WHITELIST_CHAIN="IP_WHITELIST"
+    create_chains() {
+        $IPTABLES -N $BLACKLIST_CHAIN 2>/dev/null
+        $IPTABLES -N $WHITELIST_CHAIN 2>/dev/null
+    }
 
-get_chain_name() {
-    local chain=$1
-    case $chain in
-        $BLACKLIST_CHAIN) echo "黑名单" ;;
-        $WHITELIST_CHAIN) echo "白名单" ;;
-        *) echo "未知名单" ;;
-    esac
-}
+    check_ip() {
+        local ip=$1
+        local ipv4_regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
+        local ipv6_regex='^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$'
+        
+        if [[ $ip =~ $ipv4_regex ]] || [[ $ip =~ $ipv6_regex ]]; then
+            return 0
+        else
+            return 1
+        fi
+    }
 
-create_chains() {
-    $IPTABLES -N $BLACKLIST_CHAIN 2>/dev/null
-    $IPTABLES -N $WHITELIST_CHAIN 2>/dev/null
-}
-create_chains
+    ip_exists_in_file() {
+        local ip=$1
+        local file=$2
+        grep -q "^$ip$" "$file"
+        return $?
+    }
 
-check_ip() {
-    local ip=$1
-    local ipv4_regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
-    local ipv6_regex='^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$'
-    
-    if [[ $ip =~ $ipv4_regex ]] || [[ $ip =~ $ipv6_regex ]]; then
-        return 0
-    else
-        return 1
-    fi
-}
+    add_ips_to_file() {
+        local ips=("$@")
+        local file="${ips[-1]}"
+        unset 'ips[-1]'
+        local chain_name=$(get_chain_name $([[ $file == $WHITELIST_FILE ]] && echo $WHITELIST_CHAIN || echo $BLACKLIST_CHAIN))
+        local added=()
+        local skipped=()
+
+        for ip in "${ips[@]}"; do
+            if ! ip_exists_in_file $ip $file; then
+                echo $ip >> "$file"
+                added+=("$ip")
+            else
+                skipped+=("$ip")
+            fi
+        done
 
-ip_exists_in_chain() {
-    local ip=$1
-    local chain=$2
-    local action=$3
-    $IPTABLES -C $chain -s $ip -j $action &>/dev/null
-    return $?
-}
+        if [ ${#added[@]} -gt 0 ]; then
+            INFO "${LIGHT_BLUE}${added[*]}${RESET} ${LIGHT_GREEN}已添加${RESET}到$chain_name"
+        fi
+        if [ ${#skipped[@]} -gt 0 ]; then
+            WARN "${LIGHT_BLUE}${skipped[*]}${RESET} ${LIGHT_YELLOW}已存在${RESET}于$chain_name,跳过添加"
+        fi
+    }
 
-clear_chain() {
-    local chain=$1
-    $IPTABLES -F $chain
-}
+    remove_ips_from_file() {
+        local ips=("$@")
+        local file="${ips[-1]}"
+        unset 'ips[-1]'
+        local chain_name=$(get_chain_name $([[ $file == $WHITELIST_FILE ]] && echo $WHITELIST_CHAIN || echo $BLACKLIST_CHAIN))
+        local removed=()
+        local not_found=()
+
+        for ip in "${ips[@]}"; do
+            if ip_exists_in_file $ip $file; then
+                sed -i "/^$ip$/d" "$file"
+                removed+=("$ip")
+            else
+                not_found+=("$ip")
+            fi
+        done
 
-add_ip_to_chain() {
-    local ip=$1
-    local chain=$2
-    local action=$3
-    local chain_name=$(get_chain_name $chain)
-    if ! ip_exists_in_chain $ip $chain $action; then
-        $IPTABLES -A $chain -s $ip -j $action
-        INFO "${LIGHT_BLUE}$ip${RESET} ${LIGHT_GREEN}已添加${RESET}到$(get_chain_name $chain)"
-    else
-        WARN "${LIGHT_BLUE}$ip${RESET} ${LIGHT_YELLOW}已存在${RESET}于$(get_chain_name $chain),跳过添加"
-    fi
-}
+        if [ ${#removed[@]} -gt 0 ]; then
+            INFO "${LIGHT_BLUE}${removed[*]}${RESET} ${LIGHT_RED}已从${RESET}$chain_name${LIGHT_RED}移除${RESET}"
+        fi
+        if [ ${#not_found[@]} -gt 0 ]; then
+            WARN "${LIGHT_BLUE}${not_found[*]}${RESET} ${LIGHT_YELLOW}不存在${RESET}于$chain_name,无需移除"
+        fi
+    }
 
-# 白名单
-handle_whitelist() {
-    if ! $IPTABLES -L $WHITELIST_CHAIN >/dev/null 2>&1; then
-        $IPTABLES -N $WHITELIST_CHAIN
-    fi
-    
-    if $IPTABLES -C INPUT -j $BLACKLIST_CHAIN >/dev/null 2>&1; then
-        read -e -p "$(WARN "${LIGHT_YELLOW}当前使用黑名单模式${RESET},${LIGHT_CYAN}是否切换到白名单模式?(y/n)${RESET}: ")" switch
-        if [[ $switch == "y" ]]; then
-            $IPTABLES -D INPUT -j $BLACKLIST_CHAIN
-            clear_chain $BLACKLIST_CHAIN
-            $IPTABLES -D INPUT -j $WHITELIST_CHAIN 2>/dev/null
-        else
-            return
+    list_ips_in_file() {
+        local file=$1
+        local chain_name=$(get_chain_name $([[ $file == $WHITELIST_FILE ]] && echo $WHITELIST_CHAIN || echo $BLACKLIST_CHAIN))
+
+        echo "---------------------------------------------------------------"
+        echo "当前${chain_name}中的IP列表:"
+        cat "$file"
+    }
+
+    apply_ip_list() {
+        local chain=$1
+        local file=$2
+        local action=$3
+
+        # 清空链
+        $IPTABLES -F $chain
+
+        # 使用 iptables-restore 批量应用规则
+        {
+            echo "*filter"
+            echo ":$chain - [0:0]"
+            while IFS= read -r ip; do
+                echo "-A $chain -s $ip -j $action"
+            done < "$file"
+            echo "COMMIT"
+        } | $IPTABLES-restore -n
+    }
+
+    ensure_default_deny_for_whitelist() {
+        if ! $IPTABLES -C $WHITELIST_CHAIN -j DROP &>/dev/null; then
+            $IPTABLES -A $WHITELIST_CHAIN -j DROP
         fi
-    fi
-    clear_chain $WHITELIST_CHAIN
-    
-    add_ip_to_chain 127.0.0.1 $WHITELIST_CHAIN ACCEPT
-    
-    read -e -p "$(INFO "${LIGHT_CYAN}请输入白名单IP (用逗号分隔多个IP)${RESET}: ")" ips
-    IFS=',' read -ra ip_array <<< "$ips"
-    
-    for ip in "${ip_array[@]}"; do
-        if check_ip $ip; then
-            add_ip_to_chain $ip $WHITELIST_CHAIN ACCEPT
+    }
+
+    whitelist_is_empty() {
+        [ ! -s "$WHITELIST_FILE" ]
+    }
+
+    apply_whitelist() {
+        if whitelist_is_empty; then
+            WARN "白名单为空,不应用白名单规则以避免锁定系统。"
+            return 1
+        fi
+        
+        if ! $IPTABLES -C INPUT -j $WHITELIST_CHAIN &>/dev/null; then
+            $IPTABLES -I INPUT 1 -j $WHITELIST_CHAIN
+            INFO "已将白名单规则应用到 INPUT 链"
         else
-            WARN "无效IP: $ip"
+            INFO "白名单规则已经应用到 INPUT 链"
         fi
-    done
-    
-    $IPTABLES -A $WHITELIST_CHAIN -j DROP
-    $IPTABLES -D INPUT -j $WHITELIST_CHAIN 2>/dev/null
-    $IPTABLES -I INPUT 1 -j $WHITELIST_CHAIN
-    
-    INFO "${LIGHT_YELLOW}白名单已更新${RESET},只有指定的IP和本地回环可以访问"
-    IP_BLACKWHITE_LIST
-}
+        apply_ip_list $WHITELIST_CHAIN $WHITELIST_FILE ACCEPT
+        ensure_default_deny_for_whitelist
+        return 0
+    }
 
-# 黑名单
-handle_blacklist() {
-    if ! $IPTABLES -L $BLACKLIST_CHAIN >/dev/null 2>&1; then
-        $IPTABLES -N $BLACKLIST_CHAIN
-    fi
-    
-    if $IPTABLES -C INPUT -j $WHITELIST_CHAIN >/dev/null 2>&1; then
-        read -e -p "$(WARN "${LIGHT_YELLOW}当前使用白名单模式${RESET},${LIGHT_CYAN}是否切换到黑名单模式?(y/n)${RESET}: ")" switch
-        if [[ $switch == "y" ]]; then
-            $IPTABLES -D INPUT -j $WHITELIST_CHAIN
-            clear_chain $WHITELIST_CHAIN
-            $IPTABLES -D INPUT -j $BLACKLIST_CHAIN 2>/dev/null
+    switch_to_whitelist() {
+        $IPTABLES -D INPUT -j $BLACKLIST_CHAIN 2>/dev/null
+        INFO "${LIGHT_YELLOW}已切换到白名单模式,请注意:请在添加IP后手动应用规则${RESET}"
+    }
+
+    switch_to_blacklist() {
+        $IPTABLES -D INPUT -j $WHITELIST_CHAIN 2>/dev/null
+        $IPTABLES -I INPUT 1 -j $BLACKLIST_CHAIN
+        apply_ip_list $BLACKLIST_CHAIN $BLACKLIST_FILE DROP
+        INFO "${LIGHT_YELLOW}已切换到黑名单模式${RESET}"
+    }
+
+    handle_whitelist() {
+        create_chains
+        
+        local whitelist_mode_active=false
+        local whitelist_rules_applied=false
+
+        if $IPTABLES -C INPUT -j $WHITELIST_CHAIN &>/dev/null; then
+            whitelist_mode_active=true
+            whitelist_rules_applied=true
+        elif $IPTABLES -C INPUT -j $BLACKLIST_CHAIN &>/dev/null; then
+            read -e -p "$(WARN "${LIGHT_YELLOW}当前使用黑名单模式${RESET},${LIGHT_CYAN}是否切换到白名单模式?(y/n)${RESET}: ")" switch
+            if [[ $switch == "y" ]]; then
+                switch_to_whitelist
+                whitelist_mode_active=true
+                whitelist_rules_applied=false
+            else
+                WARN "保持在黑名单模式,返回主菜单。"
+                return
+            fi
         else
-            return
+            switch_to_whitelist
+            whitelist_mode_active=true
+            whitelist_rules_applied=false
         fi
-    fi
-    
-    read -e -p "$(INFO "${LIGHT_CYAN}请输入黑名单IP (用逗号分隔多个IP)${RESET}: ")" ips
-    IFS=',' read -ra ip_array <<< "$ips"
-    
-    for ip in "${ip_array[@]}"; do
-        if check_ip $ip; then
-            add_ip_to_chain $ip $BLACKLIST_CHAIN DROP
+
+        while true; do
+            echo "---------------------------------------------------------------"
+            echo -e "1) ${BOLD}添加IP到白名单${RESET}"
+            echo -e "2) ${BOLD}从白名单移除IP${RESET}"
+            echo -e "3) ${BOLD}查看当前白名单${RESET}"
+            echo -e "4) ${BOLD}应用白名单规则${RESET}"
+            echo -e "5) ${BOLD}返回上一级${RESET}"
+            echo "---------------------------------------------------------------"
+            read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" whitelist_choice
+
+            case $whitelist_choice in
+                1)
+                    read -e -p "$(INFO "${LIGHT_CYAN}请输入要添加到白名单的IP (用逗号分隔多个IP)${RESET}: ")" ips
+                    IFS=',' read -ra ip_array <<< "$ips"
+                    valid_ips=()
+                    for ip in "${ip_array[@]}"; do
+                        if check_ip $ip; then
+                            valid_ips+=("$ip")
+                        else
+                            WARN "无效IP: $ip"
+                        fi
+                    done
+                    if [ ${#valid_ips[@]} -gt 0 ]; then
+                        add_ips_to_file "${valid_ips[@]}" "$WHITELIST_FILE"
+                        whitelist_rules_applied=false
+                    fi
+                    ;;
+                2)
+                    read -e -p "$(INFO "${LIGHT_CYAN}请输入要从白名单移除的IP (用逗号分隔多个IP)${RESET}: ")" ips
+                    IFS=',' read -ra ip_array <<< "$ips"
+                    valid_ips=()
+                    for ip in "${ip_array[@]}"; do
+                        if check_ip $ip; then
+                            valid_ips+=("$ip")
+                        else
+                            WARN "无效IP: $ip"
+                        fi
+                    done
+                    if [ ${#valid_ips[@]} -gt 0 ]; then
+                        remove_ips_from_file "${valid_ips[@]}" "$WHITELIST_FILE"
+                        whitelist_rules_applied=false
+                    fi
+                    ;;
+                3)
+                    list_ips_in_file $WHITELIST_FILE
+                    ;;
+                4)
+                    if apply_whitelist; then
+                        whitelist_rules_applied=true
+                        INFO "${LIGHT_GREEN}白名单规则已成功应用${RESET}"
+                    else
+                        WARN "${LIGHT_YELLOW}无法应用白名单规则${RESET}"
+                    fi
+                    ;;
+                5)
+                    if ! $whitelist_rules_applied; then
+                        read -e -p "$(WARN "${LIGHT_YELLOW}白名单规则尚未应用。您确定要退出吗?${RESET} (y/n): ")" confirm
+                        if [[ $confirm != "y" ]]; then
+                            continue
+                        fi
+                    fi
+                    return
+                    ;;
+                *)
+                    WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择1-5${RESET}的选项."
+                    ;;
+            esac
+        done
+    }
+
+    handle_blacklist() {
+        create_chains
+        
+        local blacklist_mode_active=false
+        if $IPTABLES -C INPUT -j $BLACKLIST_CHAIN &>/dev/null; then
+            blacklist_mode_active=true
+        elif $IPTABLES -C INPUT -j $WHITELIST_CHAIN &>/dev/null; then
+            read -e -p "$(WARN "${LIGHT_YELLOW}当前使用白名单模式${RESET},${LIGHT_CYAN}是否切换到黑名单模式?(y/n)${RESET}: ")" switch
+            if [[ $switch == "y" ]]; then
+                switch_to_blacklist
+                blacklist_mode_active=true
+            else
+                WARN "保持在白名单模式,返回主菜单。"
+                return
+            fi
         else
-            WARN "无效IP: $ip"
+            switch_to_blacklist
+            blacklist_mode_active=true
         fi
-    done
-    
-    $IPTABLES -D INPUT -j $BLACKLIST_CHAIN 2>/dev/null
-    $IPTABLES -I INPUT 1 -j $BLACKLIST_CHAIN
-    
-    INFO "${LIGHT_YELLOW}黑名单已更新${RESET},黑名单里的IP将无法访问"
-    IP_BLACKWHITE_LIST
-}
-
 
-SEPARATOR "设置IP黑白名单"
-echo -e "1) ${BOLD}设置${LIGHT_GREEN}白名单${RESET}"
-echo -e "2) ${BOLD}设置${LIGHT_CYAN}黑名单${RESET}"
-echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
-echo -e "0) ${BOLD}退出脚本${RESET}"
-echo "---------------------------------------------------------------"
-read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" ipblack_choice
+        while true; do
+            echo "---------------------------------------------------------------"
+            echo -e "1) ${BOLD}添加IP到黑名单${RESET}"
+            echo -e "2) ${BOLD}从黑名单移除IP${RESET}"
+            echo -e "3) ${BOLD}查看当前黑名单${RESET}"
+            echo -e "4) ${BOLD}返回上一级${RESET}"
+            echo "---------------------------------------------------------------"
+            read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" blacklist_choice
+
+            case $blacklist_choice in
+                1)
+                    read -e -p "$(INFO "${LIGHT_CYAN}请输入要添加到黑名单的IP (用逗号分隔多个IP)${RESET}: ")" ips
+                    IFS=',' read -ra ip_array <<< "$ips"
+                    valid_ips=()
+                    for ip in "${ip_array[@]}"; do
+                        if check_ip $ip; then
+                            valid_ips+=("$ip")
+                        else
+                            WARN "无效IP: $ip"
+                        fi
+                    done
+                    if [ ${#valid_ips[@]} -gt 0 ]; then
+                        add_ips_to_file "${valid_ips[@]}" "$BLACKLIST_FILE"
+                        apply_ip_list $BLACKLIST_CHAIN $BLACKLIST_FILE DROP
+                    fi
+                    ;;
+                2)
+                    read -e -p "$(INFO "${LIGHT_CYAN}请输入要从黑名单移除的IP (用逗号分隔多个IP)${RESET}: ")" ips
+                    IFS=',' read -ra ip_array <<< "$ips"
+                    valid_ips=()
+                    for ip in "${ip_array[@]}"; do
+                        if check_ip $ip; then
+                            valid_ips+=("$ip")
+                        else
+                            WARN "无效IP: $ip"
+                        fi
+                    done
+                    if [ ${#valid_ips[@]} -gt 0 ]; then
+                        remove_ips_from_file "${valid_ips[@]}" "$BLACKLIST_FILE"
+                        apply_ip_list $BLACKLIST_CHAIN $BLACKLIST_FILE DROP
+                    fi
+                    ;;
+                3)
+                    list_ips_in_file $BLACKLIST_FILE
+                    ;;
+                4)
+                    return
+                    ;;
+                *)
+                    WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择1-4${RESET}的选项."
+                    ;;
+            esac
+        done
+    }
 
-case $ipblack_choice in
-    1)
-        handle_whitelist
-        ;;
-    2)
-        handle_blacklist
-        ;;
-    3)
-        main_menu
-        ;;
-    0)
-        exit 1
-        ;;
-    *)
-        WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
-        IP_BLACKWHITE_LIST
-        ;;
-esac
+    while true; do
+        SEPARATOR "设置IP黑白名单"
+        echo -e "1) ${BOLD}管理${LIGHT_GREEN}白名单${RESET}"
+        echo -e "2) ${BOLD}管理${LIGHT_CYAN}黑名单${RESET}"
+        echo -e "3) ${BOLD}返回${LIGHT_RED}主菜单${RESET}"
+        echo -e "0) ${BOLD}退出脚本${RESET}"
+        echo "---------------------------------------------------------------"
+        read -e -p "$(INFO "输入${LIGHT_CYAN}对应数字${RESET}并按${LIGHT_GREEN}Enter${RESET}键 > ")" ipblack_choice
+
+        case $ipblack_choice in
+            1)
+                handle_whitelist
+                ;;
+            2)
+                handle_blacklist
+                ;;
+            3)
+                main_menu
+                ;;
+            0)
+                exit 0
+                ;;
+            *)
+                WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项."
+                ;;
+        esac
+    done
 }
 
+
 # 其他工具
 function OtherTools() {
 echo -e "1) 设置${BOLD}${YELLOW}系统命令${RESET}"