# 出站规则管理系统 - 代码实现示例 ## 🔧 核心代码示例 ### 1. 数据结构示例 #### 规则库文件格式 (library.yaml) ```yaml metadata: version: "2.0" created: "2025-09-28T10:00:00Z" last_modified: "2025-09-28T10:30:00Z" total_rules: 3 rules: rule_1727515200_1234: id: "rule_1727515200_1234" name: "china_direct" type: "direct" description: "中国大陆IP直连,绕过代理" tags: ["direct", "china", "geoip"] created: "2025-09-28T10:00:00Z" modified: "2025-09-28T10:00:00Z" config: direct: mode: "auto" bindDevice: "eth0" bindIPv4: "192.168.1.100" rule_1727515260_5678: id: "rule_1727515260_5678" name: "global_proxy" type: "socks5" description: "全局SOCKS5代理服务器" tags: ["proxy", "socks5", "global"] created: "2025-09-28T10:01:00Z" modified: "2025-09-28T10:01:00Z" config: socks5: addr: "proxy.example.com:1080" username: "user123" password: "pass123" rule_1727515320_9999: id: "rule_1727515320_9999" name: "corp_http" type: "http" description: "企业HTTP代理" tags: ["proxy", "http", "corporate"] created: "2025-09-28T10:02:00Z" modified: "2025-09-28T10:02:00Z" config: http: url: "http://proxy.corp.com:8080" insecure: false ``` #### 应用状态文件格式 (applied.yaml) ```yaml metadata: version: "2.0" last_applied: "2025-09-28T10:30:00Z" hysteria_config: "/etc/hysteria/config.yaml" applied_rules: - rule_id: "rule_1727515200_1234" rule_name: "china_direct" applied_at: "2025-09-28T10:30:00Z" acl_rules: - "china_direct(geoip:cn)" - "china_direct(geosite:cn)" - rule_id: "rule_1727515260_5678" rule_name: "global_proxy" applied_at: "2025-09-28T10:25:00Z" acl_rules: - "global_proxy(all)" backup_config: backup_path: "/etc/hysteria/rules/backups/config_20250928_103000.yaml" created_at: "2025-09-28T10:30:00Z" ``` ### 2. 核心函数实现 #### 规则创建函数 ```bash #!/bin/bash # 创建新规则的完整实现 rule_create_interactive() { echo -e "${BLUE}=== 创建新的出站规则 ===${NC}" echo "" # 1. 获取规则基本信息 local rule_name rule_type rule_description while true; do read -p "规则名称 (唯一标识): " rule_name if [[ -z "$rule_name" ]]; then echo -e "${RED}规则名称不能为空${NC}" continue fi if rule_exists_by_name "$rule_name"; then echo -e "${RED}规则名称已存在,请选择其他名称${NC}" continue fi # 验证名称格式 if [[ ! "$rule_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then echo -e "${RED}规则名称只能包含字母、数字、下划线和连字符${NC}" continue fi break done read -p "规则描述: " rule_description [[ -z "$rule_description" ]] && rule_description="用户自定义规则" # 2. 选择规则类型 echo "" echo "选择规则类型:" echo "1. Direct (直连)" echo "2. SOCKS5 代理" echo "3. HTTP/HTTPS 代理" echo "" local type_choice while true; do read -p "请选择 [1-3]: " type_choice case $type_choice in 1) rule_type="direct"; break ;; 2) rule_type="socks5"; break ;; 3) rule_type="http"; break ;; *) echo -e "${RED}无效选择,请重新输入${NC}" ;; esac done # 3. 配置规则参数 local config_json case $rule_type in "direct") config_json=$(rule_create_direct_config) ;; "socks5") config_json=$(rule_create_socks5_config) ;; "http") config_json=$(rule_create_http_config) ;; esac if [[ -z "$config_json" ]]; then echo -e "${RED}配置创建失败${NC}" return 1 fi # 4. 显示配置预览 echo "" echo -e "${BLUE}=== 配置预览 ===${NC}" echo "规则名称: $rule_name" echo "规则类型: $rule_type" echo "规则描述: $rule_description" echo "配置详情:" echo "$config_json" | jq '.' echo "" # 5. 确认创建 read -p "确认创建此规则? [y/N]: " confirm if [[ ! $confirm =~ ^[Yy]$ ]]; then echo -e "${YELLOW}已取消创建${NC}" return 0 fi # 6. 执行创建 local rule_id rule_id=$(rule_create "$rule_name" "$rule_type" "$rule_description" "$config_json") if [[ $? -eq 0 ]]; then echo -e "${GREEN}规则创建成功!${NC}" echo "规则ID: $rule_id" echo "" # 询问是否立即应用 read -p "是否立即应用此规则? [y/N]: " apply_now if [[ $apply_now =~ ^[Yy]$ ]]; then rule_state_apply "$rule_id" fi else echo -e "${RED}规则创建失败${NC}" return 1 fi } # Direct类型配置创建 rule_create_direct_config() { echo "" echo -e "${BLUE}=== Direct 直连配置 ===${NC}" local bind_interface bind_ipv4 bind_ipv6 # 绑定网卡 read -p "是否绑定特定网卡? [y/N]: " bind_iface_choice if [[ $bind_iface_choice =~ ^[Yy]$ ]]; then echo "可用网卡:" ip link show | grep '^[0-9]' | awk -F': ' '{print " " $2}' | grep -v lo read -p "网卡名称: " bind_interface fi # 绑定IPv4 read -p "是否绑定特定IPv4地址? [y/N]: " bind_ipv4_choice if [[ $bind_ipv4_choice =~ ^[Yy]$ ]]; then while true; do read -p "IPv4地址: " bind_ipv4 if [[ "$bind_ipv4" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then break else echo -e "${RED}IPv4地址格式错误${NC}" fi done fi # 绑定IPv6 read -p "是否绑定特定IPv6地址? [y/N]: " bind_ipv6_choice if [[ $bind_ipv6_choice =~ ^[Yy]$ ]]; then read -p "IPv6地址: " bind_ipv6 fi # 生成JSON配置 local config=$(cat </dev/null 2>&1; then sync_issues+=("配置文件中不存在已应用的规则: $rule_name") fi done <<< "$applied_rules" # 2. 检查配置文件中的outbound是否都有对应的应用状态 echo "检查配置文件一致性..." local config_outbounds=$(yq eval '.outbounds[].name' "$HYSTERIA_CONFIG" 2>/dev/null) while IFS= read -r outbound_name; do [[ -z "$outbound_name" ]] && continue if ! rule_state_is_applied_by_name "$outbound_name"; then sync_issues+=("配置文件中的规则未记录在应用状态中: $outbound_name") fi done <<< "$config_outbounds" # 3. 报告结果 if [[ ${#sync_issues[@]} -eq 0 ]]; then echo -e "${GREEN}✅ 状态同步检查通过,未发现问题${NC}" else echo -e "${YELLOW}⚠️ 发现 ${#sync_issues[@]} 个同步问题:${NC}" for issue in "${sync_issues[@]}"; do echo " - $issue" done echo "" echo "修复选项:" echo "1. 自动修复同步问题" echo "2. 手动处理" echo "3. 忽略问题" read -p "请选择 [1-3]: " fix_choice case $fix_choice in 1) rule_state_auto_fix_sync ;; 2) echo -e "${BLUE}请手动检查并修复上述问题${NC}" ;; 3) echo -e "${YELLOW}已忽略同步问题${NC}" ;; esac fi echo "" read -p "按任意键继续..." -n 1 } # 自动修复同步问题 rule_state_auto_fix_sync() { echo -e "${BLUE}正在自动修复同步问题...${NC}" # 创建修复前的备份 rule_state_create_backup "before_sync_fix" # 重新构建应用状态文件 local temp_applied="/tmp/applied_fixed_$(date +%s).yaml" # 初始化新的状态文件 cat > "$temp_applied" </dev/null) while IFS= read -r outbound_name; do [[ -z "$outbound_name" ]] && continue # 尝试从规则库中找到对应的规则 local rule_id=$(rule_get_id_by_name "$outbound_name") if [[ -n "$rule_id" ]]; then # 添加到应用状态 local applied_entry=$(cat <