diff --git a/README.md b/README.md index fefa375..cad55ef 100644 --- a/README.md +++ b/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) -📢 Docker Proxy-TG交流群 +📢 Docker Proxy-交流群 diff --git a/install/DockerProxy_Install.sh b/install/DockerProxy_Install.sh index ddeab3b..0592c20 100644 --- a/install/DockerProxy_Install.sh +++ b/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) - -BLACKLIST_CHAIN="IP_BLACKLIST" -WHITELIST_CHAIN="IP_WHITELIST" - -get_chain_name() { - local chain=$1 - case $chain in - $BLACKLIST_CHAIN) echo "黑名单" ;; - $WHITELIST_CHAIN) echo "白名单" ;; - *) echo "未知名单" ;; - esac -} - -create_chains() { - $IPTABLES -N $BLACKLIST_CHAIN 2>/dev/null - $IPTABLES -N $WHITELIST_CHAIN 2>/dev/null -} -create_chains - -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 -} - -ip_exists_in_chain() { - local ip=$1 - local chain=$2 - local action=$3 - $IPTABLES -C $chain -s $ip -j $action &>/dev/null - return $? -} - -clear_chain() { - local chain=$1 - $IPTABLES -F $chain -} - -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 -} - -# 白名单 -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 - 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 - else - WARN "无效IP: $ip" - 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 -} - -# 黑名单 -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 - else - return - 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 - else - WARN "无效IP: $ip" - 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 - -case $ipblack_choice in - 1) - handle_whitelist - ;; - 2) - handle_blacklist - ;; - 3) - main_menu - ;; - 0) + if ! command -v iptables &> /dev/null + then + WARN "iptables 未安装. 请安装后再运行此脚本." exit 1 - ;; - *) - WARN "输入了无效的选择。请重新${LIGHT_GREEN}选择0-3${RESET}的选项." - IP_BLACKWHITE_LIST - ;; -esac + 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 + } + + create_chains() { + $IPTABLES -N $BLACKLIST_CHAIN 2>/dev/null + $IPTABLES -N $WHITELIST_CHAIN 2>/dev/null + } + + 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 + } + + ip_exists_in_file() { + local ip=$1 + local file=$2 + grep -q "^$ip$" "$file" + return $? + } + + 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 + + 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 + } + + 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 + + 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 + } + + 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 + } + + 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 + INFO "白名单规则已经应用到 INPUT 链" + fi + apply_ip_list $WHITELIST_CHAIN $WHITELIST_FILE ACCEPT + ensure_default_deny_for_whitelist + return 0 + } + + 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 + switch_to_whitelist + whitelist_mode_active=true + whitelist_rules_applied=false + fi + + 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 + switch_to_blacklist + blacklist_mode_active=true + fi + + 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 + } + + 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}"