Files
goproxy/internal/rule/loader.go
DarkiT 35f492b1c5 refactor(proxy): 重构反向代理配置转换逻辑
- 添加 convertToReverseConfig 函数,将 config.Config 转换为 reverse.Config
- 修正配置字段映射关系:
  - EnableHTTPS -> DecryptHTTPS
  - EnableWebSocket -> SupportWebSocketUpgrade
- 保持其他配置字段映射不变
- 优化代码格式和注释

BREAKING CHANGE: 反向代理配置结构发生变化,需要更新相关配置
2025-03-13 22:02:30 +08:00

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
}