8.8 KiB
8.8 KiB
GoProxy自定义DNS解析功能
该功能允许GoProxy使用自定义DNS解析器,实现以下功能:
- 自定义域名解析
- 动态变更后端服务器IP
- 自定义后端服务器端口
- 泛解析(通配符域名)支持
- 多后端服务器支持
- 一个域名对应多个后端服务器
- 支持多种负载均衡策略(轮询、随机、第一个可用)
- 支持动态添加/删除后端服务器
- 负载均衡和故障转移
- 绕过DNS污染
- 高效的DNS缓存
特性
- 自定义记录:直接设置域名到IP的映射
- 自定义端口:为每个域名指定自定义端口,无需在URL中指定
- 泛解析:支持通配符域名(如
*.example.com)自动匹配多个子域名 - 多级泛解析:支持复杂的通配符模式(如
api.*.example.com) - 多后端支持:支持一个域名配置多个后端服务器
- 负载均衡:支持多种负载均衡策略
- 备用解析:在自定义记录未找到时可选择使用系统DNS
- DNS缓存:缓存解析结果以提高性能
- 自动重试:解析失败时可配置重试策略
- 加载配置:从JSON文件或hosts格式文件加载配置
- 自定义拨号器:与net标准库兼容的拨号器
安装
确保已安装Go(建议1.22或更高版本):
git clone https://github.com/ouqiang/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/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支持三种负载均衡策略:
-
轮询策略(Round Robin)
resolver := dns.NewResolver( dns.WithLoadBalanceStrategy(dns.RoundRobin), ) -
随机策略(Random)
resolver := dns.NewResolver( dns.WithLoadBalanceStrategy(dns.Random), ) -
第一个可用策略(First Available)
resolver := dns.NewResolver( dns.WithLoadBalanceStrategy(dns.FirstAvailable), )
使用DNS拨号器
import "github.com/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}
高级用法
多后端配置模式
多后端配置支持以下模式:
-
精确匹配多后端:
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) -
混合配置:
// 精确匹配优先于泛解析 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
注意事项
- 通配符域名只在我们的自定义DNS解析器中有效,不会影响系统DNS
- 泛解析规则的顺序会影响匹配结果,后添加的规则优先级更高
- 过多的泛解析规则可能会影响性能,建议合理组织规则
- 当域名同时匹配多个规则时,精确匹配优先于通配符匹配
- 自签名证书会导致浏览器警告,仅用于测试目的
- 多后端配置时,建议使用健康检查确保后端服务器可用性
- 负载均衡策略的选择应根据实际需求进行配置
- 动态添加/删除后端服务器时,需要考虑并发安全性