191 lines
6.0 KiB
Go
191 lines
6.0 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"log"
|
||
"net/http"
|
||
"time"
|
||
|
||
"github.com/goproxy/internal/config"
|
||
"github.com/goproxy/internal/dns"
|
||
"github.com/goproxy/internal/proxy"
|
||
)
|
||
|
||
// WildcardDNSDelegate 带有泛解析功能的委托
|
||
type WildcardDNSDelegate struct {
|
||
proxy.DefaultDelegate
|
||
targetHost string
|
||
targetPort string
|
||
resolver dns.Resolver
|
||
}
|
||
|
||
// ModifyRequest 修改请求头
|
||
func (d *WildcardDNSDelegate) ModifyRequest(req *http.Request) {
|
||
log.Printf("收到请求: %s %s", req.Method, req.URL.String())
|
||
|
||
// 设置标准浏览器请求头
|
||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/122.0.0.0 Safari/537.36")
|
||
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
|
||
req.Header.Set("Connection", "keep-alive")
|
||
|
||
// 保留原始Host头,便于泛解析匹配
|
||
// 只有当明确指定目标主机时才覆盖
|
||
if d.targetHost != "" && d.targetHost != "*" {
|
||
req.Host = d.targetHost
|
||
}
|
||
|
||
// 设置请求的URL方案为HTTPS
|
||
req.URL.Scheme = "https"
|
||
|
||
log.Printf("修改后的请求: %s %s (Host: %s)", req.Method, req.URL.String(), req.Host)
|
||
}
|
||
|
||
// ModifyResponse 修改响应头
|
||
func (d *WildcardDNSDelegate) ModifyResponse(resp *http.Response) error {
|
||
log.Printf("收到响应: %d %s", resp.StatusCode, resp.Status)
|
||
|
||
// 添加CORS头和代理标识
|
||
resp.Header.Set("Access-Control-Allow-Origin", "*")
|
||
resp.Header.Set("X-Proxied-By", "GoProxy-WildcardDNS")
|
||
|
||
return nil
|
||
}
|
||
|
||
// ResolveBackend 解析后端服务器
|
||
func (d *WildcardDNSDelegate) ResolveBackend(req *http.Request) (string, error) {
|
||
// 获取要解析的主机名
|
||
hostToResolve := req.Host
|
||
if d.targetHost != "" && d.targetHost != "*" {
|
||
hostToResolve = d.targetHost
|
||
}
|
||
|
||
// 从泛解析获取目标地址
|
||
endpoint, err := d.resolver.ResolveWithPort(hostToResolve, 0)
|
||
if err != nil {
|
||
log.Printf("解析主机 %s 失败: %v, 使用默认端口: %s", hostToResolve, err, d.targetPort)
|
||
return hostToResolve + ":" + d.targetPort, nil
|
||
}
|
||
|
||
// 优先使用解析得到的端口
|
||
if endpoint.Port > 0 {
|
||
address := endpoint.GetAddressWithDefaultPort(0)
|
||
log.Printf("泛解析主机 %s 到目标服务器(自定义端口): %s", hostToResolve, address)
|
||
return address, nil
|
||
}
|
||
|
||
// 使用默认端口
|
||
address := endpoint.GetAddressWithDefaultPort(443)
|
||
log.Printf("泛解析主机 %s 到目标服务器(默认端口): %s", hostToResolve, address)
|
||
return address, nil
|
||
}
|
||
|
||
func main() {
|
||
// 命令行参数
|
||
listenAddr := flag.String("listen", ":8080", "监听地址")
|
||
targetHost := flag.String("target", "", "目标站点主机名,留空表示使用请求中的Host")
|
||
targetPort := flag.String("port", "443", "默认目标端口")
|
||
dnsFile := flag.String("dns", "", "DNS配置文件路径 (JSON格式)")
|
||
hostsFile := flag.String("hosts", "", "Hosts文件路径")
|
||
flag.Parse()
|
||
|
||
// 创建DNS解析器
|
||
var resolver dns.Resolver
|
||
var err error
|
||
|
||
if *dnsFile != "" {
|
||
// 从JSON文件加载DNS配置
|
||
dnsConfig, err := dns.LoadFromJSON(*dnsFile)
|
||
if err != nil {
|
||
log.Printf("加载DNS配置文件失败: %v,将使用默认DNS解析器", err)
|
||
resolver = dns.NewResolver()
|
||
} else {
|
||
resolver = dns.NewResolverFromConfig(dnsConfig)
|
||
log.Printf("已加载DNS配置,包含 %d 条记录", len(dnsConfig.Records))
|
||
}
|
||
} else if *hostsFile != "" {
|
||
// 从hosts文件加载DNS配置
|
||
dnsConfig, err := dns.LoadFromHostsFile(*hostsFile)
|
||
if err != nil {
|
||
log.Printf("加载hosts文件失败: %v,将使用默认DNS解析器", err)
|
||
resolver = dns.NewResolver()
|
||
} else {
|
||
resolver = dns.NewResolverFromConfig(dnsConfig)
|
||
log.Printf("已加载hosts文件,包含 %d 条记录", len(dnsConfig.Records))
|
||
}
|
||
} else {
|
||
// 创建默认解析器并添加一些示例泛解析规则
|
||
resolver = dns.NewResolver()
|
||
|
||
// 通配符示例
|
||
resolver.AddWildcard("*.example.com", "93.184.216.34")
|
||
resolver.AddWildcardWithPort("*.api.example.com", "93.184.216.35", 8443)
|
||
resolver.AddWildcard("*.github.com", "140.82.121.3")
|
||
|
||
// 多级通配符示例
|
||
resolver.AddWildcardWithPort("*.dev.local", "127.0.0.1", 3000)
|
||
resolver.AddWildcardWithPort("api.*.dev.local", "127.0.0.1", 3001)
|
||
resolver.AddWildcardWithPort("db.*.dev.local", "127.0.0.1", 5432)
|
||
|
||
// 常规精确匹配
|
||
resolver.Add("example.com", "93.184.216.34")
|
||
resolver.Add("github.com", "140.82.121.4")
|
||
|
||
log.Printf("已创建默认解析器并添加示例泛解析规则")
|
||
}
|
||
|
||
// 创建自定义DNS拨号器
|
||
dnsDialer := dns.NewDialer(resolver)
|
||
|
||
// 创建配置
|
||
cfg := config.DefaultConfig()
|
||
cfg.ReverseProxy = true // 启用反向代理模式
|
||
cfg.DecryptHTTPS = false // 不解密HTTPS流量,避免TLS问题
|
||
cfg.IdleTimeout = 30 * time.Second // 连接空闲超时
|
||
cfg.AddXForwardedFor = true // 添加X-Forwarded-For头
|
||
cfg.AddXRealIP = true // 添加X-Real-IP头
|
||
cfg.SupportWebSocketUpgrade = true // 支持WebSocket升级
|
||
cfg.EnableCompression = false // 不启用压缩
|
||
cfg.EnableCORS = true // 启用CORS
|
||
cfg.EnableRetry = false // 关闭重试功能
|
||
cfg.EnableConnectionPool = false // 禁用连接池
|
||
|
||
// 创建自定义委托
|
||
delegate := &WildcardDNSDelegate{
|
||
targetHost: *targetHost,
|
||
targetPort: *targetPort,
|
||
resolver: resolver,
|
||
}
|
||
|
||
// 创建代理实例
|
||
p := proxy.New(&proxy.Options{
|
||
Config: cfg,
|
||
Delegate: delegate,
|
||
})
|
||
|
||
// 设置自定义拨号器
|
||
p.SetDialContext(dnsDialer.DialContext)
|
||
|
||
// 创建HTTP服务器
|
||
server := &http.Server{
|
||
Addr: *listenAddr,
|
||
Handler: p,
|
||
}
|
||
|
||
// 启动HTTP服务器
|
||
log.Printf("泛解析DNS代理启动,监听地址: %s", *listenAddr)
|
||
|
||
if *targetHost == "" {
|
||
log.Printf("透明代理模式:请求的Host将直接用于DNS解析")
|
||
log.Printf("提示: 尝试访问 http://localhost%s 并设置不同的Host头", *listenAddr)
|
||
} else {
|
||
log.Printf("目标主机模式:所有请求将被发送到 %s", *targetHost)
|
||
log.Printf("提示: 尝试访问 http://localhost%s", *listenAddr)
|
||
}
|
||
|
||
err = server.ListenAndServe()
|
||
if err != nil {
|
||
log.Fatalf("服务器启动失败: %v", err)
|
||
}
|
||
}
|