- 添加 convertToReverseConfig 函数,将 config.Config 转换为 reverse.Config - 修正配置字段映射关系: - EnableHTTPS -> DecryptHTTPS - EnableWebSocket -> SupportWebSocketUpgrade - 保持其他配置字段映射不变 - 优化代码格式和注释 BREAKING CHANGE: 反向代理配置结构发生变化,需要更新相关配置
218 lines
4.3 KiB
Go
218 lines
4.3 KiB
Go
package rule
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Loader 规则加载器
|
|
type Loader struct {
|
|
manager *Manager
|
|
logger *slog.Logger
|
|
}
|
|
|
|
// NewLoader 创建规则加载器
|
|
func NewLoader(manager *Manager, logger *slog.Logger) *Loader {
|
|
if logger == nil {
|
|
logger = slog.Default()
|
|
}
|
|
return &Loader{
|
|
manager: manager,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// LoadFromJSON 从JSON文件加载规则
|
|
func (l *Loader) LoadFromJSON(filename string) error {
|
|
data, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("读取规则文件失败: %w", err)
|
|
}
|
|
|
|
var config struct {
|
|
Rules []json.RawMessage `json:"rules"`
|
|
}
|
|
|
|
if err := json.Unmarshal(data, &config); err != nil {
|
|
return fmt.Errorf("解析规则文件失败: %w", err)
|
|
}
|
|
|
|
for _, ruleData := range config.Rules {
|
|
var baseRule BaseRule
|
|
if err := json.Unmarshal(ruleData, &baseRule); err != nil {
|
|
l.logger.Warn("解析规则基础信息失败",
|
|
"error", err.Error(),
|
|
"rule_data", string(ruleData),
|
|
)
|
|
continue
|
|
}
|
|
|
|
var rule Rule
|
|
switch baseRule.Type {
|
|
case RuleTypeDNS:
|
|
var dnsRule DNSRule
|
|
if err := json.Unmarshal(ruleData, &dnsRule); err != nil {
|
|
l.logger.Warn("解析DNS规则失败",
|
|
"error", err.Error(),
|
|
"rule_data", string(ruleData),
|
|
)
|
|
continue
|
|
}
|
|
rule = &dnsRule
|
|
case RuleTypeRewrite:
|
|
var rewriteRule RewriteRule
|
|
if err := json.Unmarshal(ruleData, &rewriteRule); err != nil {
|
|
l.logger.Warn("解析重写规则失败",
|
|
"error", err.Error(),
|
|
"rule_data", string(ruleData),
|
|
)
|
|
continue
|
|
}
|
|
rule = &rewriteRule
|
|
case RuleTypeRoute:
|
|
var routeRule RouteRule
|
|
if err := json.Unmarshal(ruleData, &routeRule); err != nil {
|
|
l.logger.Warn("解析路由规则失败",
|
|
"error", err.Error(),
|
|
"rule_data", string(ruleData),
|
|
)
|
|
continue
|
|
}
|
|
rule = &routeRule
|
|
default:
|
|
l.logger.Warn("未知的规则类型",
|
|
"type", string(baseRule.Type),
|
|
"rule_data", string(ruleData),
|
|
)
|
|
continue
|
|
}
|
|
|
|
if err := l.manager.AddRule(rule); err != nil {
|
|
l.logger.Error("添加规则失败",
|
|
"error", err.Error(),
|
|
"rule_id", rule.GetID(),
|
|
"rule_type", string(rule.GetType()),
|
|
)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadFromHosts 从hosts文件加载DNS规则
|
|
func (l *Loader) LoadFromHosts(filename string) error {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("打开hosts文件失败: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
lineNum := 0
|
|
for scanner.Scan() {
|
|
lineNum++
|
|
line := strings.TrimSpace(scanner.Text())
|
|
|
|
// 跳过空行和注释
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 2 {
|
|
l.logger.Warn("无效的hosts行",
|
|
"line_number", lineNum,
|
|
"line", line,
|
|
)
|
|
continue
|
|
}
|
|
|
|
// 解析IP和端口
|
|
ipStr := fields[0]
|
|
ip := ipStr
|
|
port := 0
|
|
|
|
if strings.Contains(ipStr, ":") {
|
|
parts := strings.Split(ipStr, ":")
|
|
if len(parts) != 2 {
|
|
l.logger.Warn("无效的IP:端口格式",
|
|
"line_number", lineNum,
|
|
"ip_port", ipStr,
|
|
)
|
|
continue
|
|
}
|
|
ip = parts[0]
|
|
if p, err := strconv.Atoi(parts[1]); err == nil {
|
|
port = p
|
|
} else {
|
|
l.logger.Warn("无效的端口号",
|
|
"line_number", lineNum,
|
|
"port", parts[1],
|
|
)
|
|
continue
|
|
}
|
|
}
|
|
|
|
// 验证IP地址
|
|
if net.ParseIP(ip) == nil {
|
|
l.logger.Warn("无效的IP地址",
|
|
"line_number", lineNum,
|
|
"ip", ip,
|
|
)
|
|
continue
|
|
}
|
|
|
|
// 处理每个域名
|
|
for _, domain := range fields[1:] {
|
|
// 跳过注释
|
|
if strings.HasPrefix(domain, "#") {
|
|
break
|
|
}
|
|
|
|
// 创建DNS规则
|
|
matchType := MatchTypeExact
|
|
if strings.Contains(domain, "*") {
|
|
matchType = MatchTypeWildcard
|
|
}
|
|
|
|
rule := &DNSRule{
|
|
BaseRule: BaseRule{
|
|
ID: fmt.Sprintf("hosts-%d-%s", lineNum, domain),
|
|
Type: RuleTypeDNS,
|
|
Priority: 100,
|
|
Pattern: domain,
|
|
MatchType: matchType,
|
|
Enabled: true,
|
|
},
|
|
Targets: []DNSTarget{
|
|
{
|
|
IP: ip,
|
|
Port: port,
|
|
},
|
|
},
|
|
}
|
|
|
|
if err := l.manager.AddRule(rule); err != nil {
|
|
l.logger.Error("添加hosts规则失败",
|
|
"error", err.Error(),
|
|
"domain", domain,
|
|
"ip", ip,
|
|
"port", port,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return fmt.Errorf("读取hosts文件失败: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|