Files
goproxy/cmd/custom_port_proxy/main.go
2025-03-13 18:11:04 +08:00

175 lines
5.5 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 (
"flag"
"log"
"net/http"
"time"
"github.com/darkit/goproxy/internal/config"
"github.com/darkit/goproxy/internal/dns"
"github.com/darkit/goproxy/internal/proxy"
)
// CustomPortDelegate 自定义端口委托
type CustomPortDelegate struct {
proxy.DefaultDelegate
targetHost string
targetPort string
resolver dns.Resolver
}
// ModifyRequest 修改请求头
func (d *CustomPortDelegate) 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头
req.Host = d.targetHost
// 设置请求的URL方案为HTTPS
req.URL.Scheme = "https"
log.Printf("修改后的请求: %s %s", req.Method, req.URL.String())
}
// ModifyResponse 修改响应头
func (d *CustomPortDelegate) 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-CustomPort")
return nil
}
// ResolveBackend 解析后端服务器
func (d *CustomPortDelegate) ResolveBackend(req *http.Request) (string, error) {
// 从自定义端口解析获取目标地址
endpoint, err := d.resolver.ResolveWithPort(d.targetHost, 0)
if err != nil {
log.Printf("解析目标主机失败: %v, 使用默认端口: %s", err, d.targetPort)
return d.targetHost + ":" + d.targetPort, nil
}
// 优先使用解析得到的端口
if endpoint.Port > 0 {
address := endpoint.GetAddressWithDefaultPort(0)
log.Printf("连接到目标服务器(自定义端口): %s", address)
return address, nil
}
// 使用默认端口
address := endpoint.GetAddressWithDefaultPort(443)
log.Printf("连接到目标服务器(默认端口): %s", address)
return address, nil
}
func main() {
// 命令行参数
listenAddr := flag.String("listen", ":8080", "监听地址")
targetHost := flag.String("target", "example.com", "目标站点主机名")
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.AddWithPort("example.com", "93.184.216.34", 443)
resolver.AddWithPort("api.example.com", "93.184.216.34", 8443)
resolver.AddWithPort("dev.example.com", "127.0.0.1", 3000)
resolver.AddWithPort("api.dev.example.com", "127.0.0.1", 3001)
}
// 创建自定义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 := &CustomPortDelegate{
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,
}
// 获取目标主机的端口信息(如果有)
endpoint, err := resolver.ResolveWithPort(*targetHost, 443)
if err != nil {
log.Printf("获取目标主机端口信息失败,将使用默认端口: %s", *targetPort)
} else if endpoint.Port > 0 {
log.Printf("目标主机 %s 使用自定义端口: %d", *targetHost, endpoint.Port)
} else {
log.Printf("目标主机 %s 使用默认端口: %s", *targetHost, *targetPort)
}
// 启动HTTP服务器
log.Printf("自定义端口代理启动,监听地址: %s目标: %s", *listenAddr, *targetHost)
log.Printf("提示: 尝试访问 http://localhost%s 将被代理到 %s 的自定义端口", *listenAddr, *targetHost)
err = server.ListenAndServe()
if err != nil {
log.Fatalf("服务器启动失败: %v", err)
}
}