Files
goproxy/README_DNS.md
2025-03-13 18:11:04 +08:00

8.8 KiB
Raw Permalink Blame History

GoProxy自定义DNS解析功能

该功能允许GoProxy使用自定义DNS解析器实现以下功能

  • 自定义域名解析
  • 动态变更后端服务器IP
  • 自定义后端服务器端口
  • 泛解析(通配符域名)支持
  • 多后端服务器支持
    • 一个域名对应多个后端服务器
    • 支持多种负载均衡策略(轮询、随机、第一个可用)
    • 支持动态添加/删除后端服务器
  • 负载均衡和故障转移
  • 绕过DNS污染
  • 高效的DNS缓存

特性

  • 自定义记录直接设置域名到IP的映射
  • 自定义端口为每个域名指定自定义端口无需在URL中指定
  • 泛解析:支持通配符域名(如*.example.com)自动匹配多个子域名
  • 多级泛解析:支持复杂的通配符模式(如api.*.example.com
  • 多后端支持:支持一个域名配置多个后端服务器
  • 负载均衡:支持多种负载均衡策略
  • 备用解析在自定义记录未找到时可选择使用系统DNS
  • DNS缓存:缓存解析结果以提高性能
  • 自动重试:解析失败时可配置重试策略
  • 加载配置从JSON文件或hosts格式文件加载配置
  • 自定义拨号器与net标准库兼容的拨号器

安装

确保已安装Go建议1.22或更高版本):

git clone github.com/darkit/goproxy
cd goproxy
go build ./...

使用方法

1. HTTP代理自定义DNS

以下命令会启动一个HTTP代理监听端口8080它使用自定义DNS解析

go run cmd/custom_dns_proxy/main.go

2. 自定义端口代理

支持为不同域名指定不同端口的代理:

go run cmd/custom_port_proxy/main.go

3. 泛解析DNS代理

支持通配符域名解析的代理:

# 使用默认的示例泛解析规则
go run cmd/wildcard_dns_proxy/main.go

# 透明代理模式使用请求中的Host进行匹配
go run cmd/wildcard_dns_proxy/main.go -target ""

# 使用自定义配置文件
go run cmd/wildcard_dns_proxy/main.go -dns examples/wildcard_dns_config.json

# 使用hosts格式配置文件
go run cmd/wildcard_dns_proxy/main.go -hosts examples/wildcard_hosts.txt

参数说明

  • -listen: 监听地址,默认 :8080
  • -target: 目标主机名空字符串表示使用请求中的Host头
  • -port: 默认目标端口,默认 443
  • -dns: DNS配置文件JSON格式
  • -hosts: hosts格式配置文件

DNS配置格式

JSON格式

{
  "records": {
    "example.com": ["93.184.216.34", "93.184.216.35"],
    "api.example.com": ["93.184.216.35:8443", "93.184.216.36:8443"],
    
    "*.github.com": ["140.82.121.3", "140.82.121.4"],
    "github.com": ["140.82.121.4", "140.82.121.5"],
    
    "*.dev.local": ["127.0.0.1:3000", "127.0.0.1:3001"],
    "api.*.dev.local": ["127.0.0.1:3001", "127.0.0.1:3002"]
  },
  "use_fallback": true,
  "ttl": 300,
  "load_balance_strategy": "round_robin"
}

Hosts格式

# 精确匹配(多后端)
93.184.216.34 example.com
93.184.216.35 example.com
93.184.216.35:8443 api.example.com
93.184.216.36:8443 api.example.com

# 泛解析(多后端)
140.82.121.3 *.github.com
140.82.121.4 *.github.com
127.0.0.1:3000 *.dev.local
127.0.0.1:3001 *.dev.local
127.0.0.1:3001 api.*.dev.local
127.0.0.1:3002 api.*.dev.local

编程接口

使用DNS解析器

import "github.com/darkit/goproxy/internal/dns"

// 创建解析器
resolver := dns.NewResolver(
    dns.WithLoadBalanceStrategy(dns.RoundRobin), // 设置负载均衡策略
    dns.WithTTL(5*time.Minute),                 // 设置DNS缓存TTL
)

// 添加多个后端服务器
resolver.AddWithPort("api.example.com", "192.168.1.1", 8080)
resolver.AddWithPort("api.example.com", "192.168.1.2", 8080)
resolver.AddWithPort("api.example.com", "192.168.1.3", 8080)

// 添加泛解析记录(多后端)
resolver.AddWildcardWithPort("*.example.com", "192.168.1.1", 8080)
resolver.AddWildcardWithPort("*.example.com", "192.168.1.2", 8080)

// 解析域名(使用负载均衡策略选择后端)
endpoint, err := resolver.ResolveWithPort("api.example.com", 443)
if err != nil {
    log.Fatalf("解析失败: %v", err)
}
fmt.Printf("解析结果: IP=%s, 端口=%d\n", endpoint.IP, endpoint.Port)

// 动态添加/删除后端服务器
resolver.AddWithPort("api.example.com", "192.168.1.4", 8080)
resolver.RemoveEndpoint("api.example.com", "192.168.1.1", 8080)

负载均衡策略

GoProxy支持三种负载均衡策略

  1. 轮询策略Round Robin

    resolver := dns.NewResolver(
        dns.WithLoadBalanceStrategy(dns.RoundRobin),
    )
    
  2. 随机策略Random

    resolver := dns.NewResolver(
        dns.WithLoadBalanceStrategy(dns.Random),
    )
    
  3. 第一个可用策略First Available

    resolver := dns.NewResolver(
        dns.WithLoadBalanceStrategy(dns.FirstAvailable),
    )
    

使用DNS拨号器

import "github.com/darkit/goproxy/internal/dns"

// 创建解析器
resolver := dns.NewResolver(
    dns.WithLoadBalanceStrategy(dns.RoundRobin),
)
resolver.AddWithPort("example.com", "192.168.1.1", 8080)
resolver.AddWithPort("example.com", "192.168.1.2", 8080)
resolver.AddWildcardWithPort("*.example.com", "192.168.1.3", 8080)
resolver.AddWildcardWithPort("*.example.com", "192.168.1.4", 8080)

// 创建拨号器
dialer := dns.NewDialer(resolver)

// 使用拨号器连接(会自动应用负载均衡)
conn, err := dialer.Dial("tcp", "api.example.com:443")
if err != nil {
    log.Fatalf("连接失败: %v", err)
}
defer conn.Close()

// 或者获取用于http.Transport的拨号上下文函数
transport := &http.Transport{
    DialContext: dialer.DialContext,
}
client := &http.Client{Transport: transport}

高级用法

多后端配置模式

多后端配置支持以下模式:

  1. 精确匹配多后端

    resolver.AddWithPort("api.example.com", "192.168.1.1", 8080)
    resolver.AddWithPort("api.example.com", "192.168.1.2", 8080)
    resolver.AddWithPort("api.example.com", "192.168.1.3", 8080)
    
  2. 泛解析多后端

    resolver.AddWildcardWithPort("*.example.com", "192.168.1.1", 8080)
    resolver.AddWildcardWithPort("*.example.com", "192.168.1.2", 8080)
    
  3. 混合配置

    // 精确匹配优先于泛解析
    resolver.AddWithPort("api.example.com", "192.168.1.1", 8080)
    resolver.AddWildcardWithPort("*.example.com", "192.168.1.2", 8080)
    

动态管理后端服务器

// 添加新的后端服务器
resolver.AddWithPort("api.example.com", "192.168.1.4", 8080)

// 删除特定的后端服务器
resolver.RemoveEndpoint("api.example.com", "192.168.1.1", 8080)

// 删除整个域名记录
resolver.Remove("api.example.com")

// 清除所有记录
resolver.Clear()

健康检查集成

可以结合健康检查功能,自动剔除不健康的后端服务器:

// 创建健康检查器
healthChecker := healthcheck.NewChecker(
    healthcheck.WithCheckInterval(30*time.Second),
    healthcheck.WithTimeout(5*time.Second),
)

// 添加健康检查
healthChecker.Add("api.example.com", "192.168.1.1:8080")
healthChecker.Add("api.example.com", "192.168.1.2:8080")

// 在解析器中使用健康检查结果
resolver.SetHealthChecker(healthChecker)

应用场景

高可用部署

使用多后端配置实现高可用:

# 主备模式
192.168.1.1 api.example.com  # 主服务器
192.168.1.2 api.example.com  # 备用服务器

# 负载均衡模式
192.168.1.1 api.example.com  # 服务器1
192.168.1.2 api.example.com  # 服务器2
192.168.1.3 api.example.com  # 服务器3

多环境部署

为不同环境配置不同的后端服务器组:

# 测试环境
192.168.1.10 *.test.example.com
192.168.1.11 *.test.example.com

# 预发布环境
192.168.1.20 *.staging.example.com
192.168.1.21 *.staging.example.com

# 生产环境
192.168.1.30 *.production.example.com
192.168.1.31 *.production.example.com

微服务架构

为不同类型的微服务配置多个后端:

# 认证服务
10.0.0.1:8001 *.auth.internal
10.0.0.2:8001 *.auth.internal

# 用户服务
10.0.0.3:8002 *.user.internal
10.0.0.4:8002 *.user.internal

# 支付服务
10.0.0.5:8003 *.payment.internal
10.0.0.6:8003 *.payment.internal

注意事项

  1. 通配符域名只在我们的自定义DNS解析器中有效不会影响系统DNS
  2. 泛解析规则的顺序会影响匹配结果,后添加的规则优先级更高
  3. 过多的泛解析规则可能会影响性能,建议合理组织规则
  4. 当域名同时匹配多个规则时,精确匹配优先于通配符匹配
  5. 自签名证书会导致浏览器警告,仅用于测试目的
  6. 多后端配置时,建议使用健康检查确保后端服务器可用性
  7. 负载均衡策略的选择应根据实际需求进行配置
  8. 动态添加/删除后端服务器时,需要考虑并发安全性