Files
demo/examples/custom_dns_reverse_proxy/main.go
2025-03-14 18:50:49 +00:00

189 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"encoding/json"
"errors"
"flag"
"log/slog"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"github.com/darkit/goproxy/pkg/dns"
"github.com/darkit/goproxy/pkg/reverse"
)
// 命令行参数
var configFile = flag.String("config", "config.json", "配置文件路径")
// Config 配置文件结构
type Config struct {
DNS struct {
Records map[string][]string `json:"records"` // 普通记录和泛解析记录
Fallback bool `json:"fallback"` // 是否回退到系统DNS
TTL int `json:"ttl"` // 缓存TTL单位为秒
Strategy string `json:"strategy"` // 负载均衡策略round-robin, random, first-available
} `json:"dns" yaml:"dns" toml:"dns"`
}
func main() {
flag.Parse()
// 创建日志记录器
logger := slog.Default()
// 加载配置文件
config := &Config{}
if *configFile != "" {
data, err := os.ReadFile(*configFile)
if err != nil {
logger.Error("读取配置文件失败", "file", *configFile, "error", err)
os.Exit(1)
}
if err := json.Unmarshal(data, config); err != nil {
logger.Error("解析配置文件失败", "error", err)
os.Exit(1)
}
logger.Info("成功加载配置文件", "file", *configFile)
}
// 选择负载均衡策略
//var strategy dns.LoadBalanceStrategy
//switch config.DNS.Strategy {
//case "random":
// strategy = dns.Random
//case "first-available":
// strategy = dns.FirstAvailable
//default:
// strategy = dns.RoundRobin
//}
// 创建反向代理配置
cfg := reverse.DefaultConfig()
cfg.TargetAddr = "www.shabi.in"
//cfg.DNSResolver = dns.NewResolver(
// dns.WithFallback(config.DNS.Fallback), // 是否回退到系统DNS
// dns.WithLoadBalanceStrategy(strategy), // 使用配置的负载均衡策略
// dns.WithTTL(time.Duration(config.DNS.TTL)*time.Second), // 设置DNS缓存TTL
//) // 创建DNS解析器
// 添加DNS记录支持多个地址
for domain, addrs := range config.DNS.Records {
for _, addr := range addrs {
host, port, err := net.SplitHostPort(addr)
if err != nil {
// 地址没有端口将整个地址作为IP使用
if !dns.IsWildcardDomain(domain) {
cfg.DNSResolver.Add(domain, addr)
} else {
cfg.DNSResolver.AddWildcard(domain, addr)
}
} else {
tPort, err := strconv.Atoi(port)
if err != nil {
logger.Error("无效的端口", "domain", domain, "addr", addr, "port", port, "error", err)
continue
}
if !dns.IsWildcardDomain(domain) {
cfg.DNSResolver.AddWithPort(domain, host, tPort)
} else {
cfg.DNSResolver.AddWildcardWithPort(domain, host, tPort)
}
}
}
}
// 创建反向代理服务器
proxy, err := reverse.New(cfg)
if err != nil {
logger.Error("创建反向代理服务器失败", "error", err)
os.Exit(1)
}
// 创建HTTP服务器
server := &http.Server{
Addr: cfg.ListenAddr,
Handler: proxy,
}
// 启动服务器
go func() {
logger.Info("启动反向代理服务器", "addr", cfg.ListenAddr)
if err = server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Error("服务器运行错误", "error", err)
}
}()
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
// 优雅关闭
logger.Info("正在关闭服务器...")
if err := server.Close(); err != nil {
logger.Error("关闭服务器失败", "error", err)
}
}
// 示例配置文件 config.json:
/*
{
"dns": {
"records": {
"api.example.com": [
"192.168.1.1:8080",
"192.168.1.2:8080",
"192.168.1.3:8080"
],
"*.example.com": [
"192.168.1.1:8080",
"192.168.1.2:8080"
]
},
"fallback": true,
"ttl": 300,
"strategy": "round-robin"
}
}
*/
// 示例配置文件 config.yaml:
/*
dns:
records:
api.example.com:
- 192.168.1.1:8080
- 192.168.1.2:8080
- 192.168.1.3:8080
"*.example.com":
- 192.168.1.1:8080
- 192.168.1.2:8080
fallback: true
ttl: 300
strategy: round-robin
*/
// 示例配置文件 config.toml:
/*
[dns]
[dns.records]
api.example.com = [
"192.168.1.1:8080",
"192.168.1.2:8080",
"192.168.1.3:8080"
]
"*.example.com" = [
"192.168.1.1:8080",
"192.168.1.2:8080"
]
fallback = true
ttl = 300
strategy = round-robin
*/