639 lines
20 KiB
Go
639 lines
20 KiB
Go
// Package proxy 实现代理服务器功能
|
||
package proxy
|
||
|
||
import (
|
||
"context"
|
||
"encoding/base64"
|
||
"encoding/binary"
|
||
"errors"
|
||
"fmt"
|
||
"io"
|
||
"net"
|
||
"net/http"
|
||
"strings"
|
||
"sync"
|
||
"sync/atomic"
|
||
"time"
|
||
|
||
"s5/pkg/config"
|
||
"s5/pkg/logger"
|
||
)
|
||
|
||
// ServerConfig 代理服务器配置
|
||
type ServerConfig struct {
|
||
Socks5Addr string // SOCKS5 代理监听地址
|
||
HttpAddr string // HTTP 代理监听地址
|
||
BufferSize int // 数据传输缓冲区大小
|
||
}
|
||
|
||
// Server 代理服务器实例
|
||
type Server struct {
|
||
config ServerConfig // 服务器配置
|
||
socks5Listener net.Listener // SOCKS5 监听器
|
||
httpServer *http.Server // HTTP 服务器
|
||
done chan struct{} // 关闭信号
|
||
activeConns sync.WaitGroup // 活动连接计数
|
||
upstreamDialer *UpstreamDialer // 上游代理拨号器
|
||
shutdownTimeout time.Duration // 关闭超时时间
|
||
}
|
||
|
||
// NewServer 创建新的代理服务器实例
|
||
func NewServer(config ServerConfig, upstreamConfig config.UpstreamConfig) *Server {
|
||
log := logger.Get()
|
||
|
||
if !upstreamConfig.Enable {
|
||
log.Fatal("必须配置上游代理")
|
||
}
|
||
|
||
upstreamDialer := NewUpstreamDialer(upstreamConfig)
|
||
if upstreamDialer == nil {
|
||
log.Fatal("创建上游代理连接器失败")
|
||
}
|
||
|
||
return &Server{
|
||
config: config,
|
||
done: make(chan struct{}),
|
||
upstreamDialer: upstreamDialer,
|
||
shutdownTimeout: 30 * time.Second,
|
||
}
|
||
}
|
||
|
||
// Start 启动代理服务器
|
||
func (s *Server) Start(ctx context.Context) error {
|
||
log := logger.Get()
|
||
log.Debugf("[SERVER] =====================================================")
|
||
log.Infof("[SERVER] 代理服务器启动")
|
||
log.Debugf("[SERVER] 服务器配置:")
|
||
log.Debugf("[SERVER] - SOCKS5监听: %s", s.config.Socks5Addr)
|
||
log.Debugf("[SERVER] - HTTP监听: %s", s.config.HttpAddr)
|
||
log.Debugf("[SERVER] - 缓冲区大小: %s", formatBytes(int64(s.config.BufferSize)))
|
||
log.Debugf("[SERVER] - 上游代理: %s", s.upstreamDialer.config.Server)
|
||
log.Debugf("[SERVER] - 关闭超时: %v", s.shutdownTimeout)
|
||
log.Debugf("[SERVER] =====================================================")
|
||
|
||
// 启动 SOCKS5 服务器
|
||
var err error
|
||
s.socks5Listener, err = net.Listen("tcp", s.config.Socks5Addr)
|
||
if err != nil {
|
||
log.Errorf("[SERVER] 启动SOCKS5服务器失败: %v", err)
|
||
return fmt.Errorf("启动SOCKS5服务器失败: %v", err)
|
||
}
|
||
log.Infof("[SERVER] SOCKS5服务器启动成功: %s", s.config.Socks5Addr)
|
||
|
||
// 启动SOCKS5处理协程
|
||
go s.serveSocks5(ctx)
|
||
|
||
// 配置 HTTP 服务器
|
||
s.httpServer = &http.Server{
|
||
Addr: s.config.HttpAddr,
|
||
Handler: http.HandlerFunc(s.handleHTTP),
|
||
// 添加服务器超时配置
|
||
ReadTimeout: 30 * time.Second,
|
||
WriteTimeout: 30 * time.Second,
|
||
IdleTimeout: 120 * time.Second,
|
||
MaxHeaderBytes: 1 << 20, // 1MB
|
||
}
|
||
|
||
// 监听关闭信号
|
||
go func() {
|
||
<-ctx.Done()
|
||
log.Debugf("[SERVER] 收到关闭信号")
|
||
// 使用带超时的上下文进行关闭
|
||
shutdownCtx, cancel := context.WithTimeout(context.Background(), s.shutdownTimeout)
|
||
defer cancel()
|
||
s.Shutdown(shutdownCtx)
|
||
}()
|
||
|
||
log.Infof("[SERVER] HTTP服务器启动: %s", s.config.HttpAddr)
|
||
err = s.httpServer.ListenAndServe()
|
||
if err == http.ErrServerClosed {
|
||
log.Debugf("[SERVER] HTTP服务器正常关闭")
|
||
return nil
|
||
}
|
||
return err
|
||
}
|
||
|
||
// Shutdown 优雅关闭服务器
|
||
func (s *Server) Shutdown(ctx context.Context) error {
|
||
log := logger.Get()
|
||
log.Debugf("[SERVER] =====================================================")
|
||
log.Infof("[SERVER] 开始优雅关闭服务器...")
|
||
|
||
// 创建一个带超时的上下文
|
||
shutdownCtx, cancel := context.WithTimeout(ctx, s.shutdownTimeout)
|
||
defer cancel()
|
||
|
||
// 关闭 SOCKS5 监听器
|
||
if s.socks5Listener != nil {
|
||
log.Debugf("[SERVER] 关闭SOCKS5监听器")
|
||
s.socks5Listener.Close()
|
||
}
|
||
|
||
// 关闭 HTTP 服务器
|
||
if s.httpServer != nil {
|
||
log.Debugf("[SERVER] 开始关闭HTTP服务器")
|
||
if err := s.httpServer.Shutdown(shutdownCtx); err != nil {
|
||
log.Errorf("[SERVER] HTTP服务器关闭失败: %v", err)
|
||
}
|
||
}
|
||
|
||
// 等待所有活动连接完成
|
||
log.Debugf("[SERVER] 等待活动连接完成 (超时: %v)...", s.shutdownTimeout)
|
||
done := make(chan struct{})
|
||
go func() {
|
||
s.activeConns.Wait()
|
||
close(done)
|
||
}()
|
||
|
||
// 等待连接完成或超时
|
||
select {
|
||
case <-shutdownCtx.Done():
|
||
log.Warnf("[SERVER] 等待连接超时,强制关闭")
|
||
// 打印当前活动连接数
|
||
activeCount := 0
|
||
s.activeConns.Add(0) // 利用Add(0)获取当前值
|
||
log.Warnf("[SERVER] 剩余活动连接数: %d", activeCount)
|
||
return fmt.Errorf("关闭超时")
|
||
case <-done:
|
||
log.Infof("[SERVER] 所有连接已正常关闭")
|
||
}
|
||
|
||
log.Debugf("[SERVER] =====================================================")
|
||
return nil
|
||
}
|
||
|
||
// serveSocks5 处理SOCKS5连接
|
||
func (s *Server) serveSocks5(ctx context.Context) {
|
||
log := logger.Get()
|
||
for {
|
||
select {
|
||
case <-ctx.Done():
|
||
return
|
||
default:
|
||
client, err := s.socks5Listener.Accept()
|
||
if err != nil {
|
||
if !errors.Is(err, net.ErrClosed) {
|
||
log.Errorw("接受SOCKS5连接错误", "error", err)
|
||
}
|
||
continue
|
||
}
|
||
s.activeConns.Add(1)
|
||
go func() {
|
||
defer s.activeConns.Done()
|
||
s.handleSocks5Connection(client)
|
||
}()
|
||
}
|
||
}
|
||
}
|
||
|
||
// handleSocks5Connection 处理SOCKS5连接
|
||
func (s *Server) handleSocks5Connection(client net.Conn) {
|
||
log := logger.Get()
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
log.Debugf("[SOCKS5] 收到新的SOCKS5连接")
|
||
|
||
clientAddr := client.RemoteAddr().String()
|
||
startTime := time.Now()
|
||
upBytes := &atomic.Int64{}
|
||
downBytes := &atomic.Int64{}
|
||
|
||
log.Debugf("[SOCKS5] 连接信息:")
|
||
log.Debugf("[SOCKS5] - 客户端地址: %s", clientAddr)
|
||
log.Debugf("[SOCKS5] - 本地地址: %s", client.LocalAddr())
|
||
log.Debugf("[SOCKS5] - 开始时间: %s", startTime.Format("2006-01-02 15:04:05.000"))
|
||
|
||
defer func() {
|
||
client.Close()
|
||
duration := time.Since(startTime)
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
log.Infof("[SOCKS5] 连接统计 [%s]:", clientAddr)
|
||
log.Infof("[SOCKS5] - 连接时长: %v", duration.Round(time.Millisecond))
|
||
log.Infof("[SOCKS5] - 上行流量: %s", formatBytes(upBytes.Load()))
|
||
log.Infof("[SOCKS5] - 下行流量: %s", formatBytes(downBytes.Load()))
|
||
log.Infof("[SOCKS5] - 总流量: %s", formatBytes(upBytes.Load()+downBytes.Load()))
|
||
log.Infof("[SOCKS5] - 平均速度: %s/s", formatBytes(int64(float64(upBytes.Load()+downBytes.Load())/duration.Seconds())))
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
}()
|
||
|
||
// SOCKS5 握手
|
||
if err := s.handleSocks5Handshake(client); err != nil {
|
||
log.Errorf("[SOCKS5] 握手失败 [%s]: %v", clientAddr, err)
|
||
return
|
||
}
|
||
|
||
// 处理请求
|
||
target, targetAddr, err := s.handleSocks5Request(client)
|
||
if err != nil {
|
||
log.Errorf("[SOCKS5] 处理请求失败 [%s]: %v", clientAddr, err)
|
||
return
|
||
}
|
||
defer target.Close()
|
||
|
||
log.Infof("[SOCKS5] 成功建立连接:")
|
||
log.Infof("[SOCKS5] - 客户端: %s", clientAddr)
|
||
log.Infof("[SOCKS5] - 目标地址: %s", targetAddr)
|
||
log.Infof("[SOCKS5] - 上游代理: %s", s.upstreamDialer.config.Server)
|
||
|
||
// 双向数据转发
|
||
var wg sync.WaitGroup
|
||
wg.Add(2)
|
||
|
||
// 上行数据传输
|
||
go func() {
|
||
defer wg.Done()
|
||
log.Debugf("[SOCKS5] 开始上行数据传输: %s -> %s", clientAddr, targetAddr)
|
||
n, err := io.Copy(target, client)
|
||
upBytes.Add(n)
|
||
if err != nil {
|
||
log.Debugf("[SOCKS5] 上行传输错误 [%s -> %s]: %v", clientAddr, targetAddr, err)
|
||
}
|
||
log.Debugf("[SOCKS5] 上行传输完成: %s", formatBytes(n))
|
||
}()
|
||
|
||
// 下行数据传输
|
||
go func() {
|
||
defer wg.Done()
|
||
log.Debugf("[SOCKS5] 开始下行数据传输: %s -> %s", targetAddr, clientAddr)
|
||
n, err := io.Copy(client, target)
|
||
downBytes.Add(n)
|
||
if err != nil {
|
||
log.Debugf("[SOCKS5] 下行传输错误 [%s -> %s]: %v", targetAddr, clientAddr, err)
|
||
}
|
||
log.Debugf("[SOCKS5] 下行传输完成: %s", formatBytes(n))
|
||
}()
|
||
|
||
wg.Wait()
|
||
log.Debugf("[SOCKS5] 连接关闭: %s <-> %s", clientAddr, targetAddr)
|
||
}
|
||
|
||
// handleHTTP 处理HTTP代理请求
|
||
func (s *Server) handleHTTP(w http.ResponseWriter, r *http.Request) {
|
||
log := logger.Get()
|
||
log.Debugf("[HTTP] =====================================================")
|
||
log.Debugf("[HTTP] 收到新的HTTP代理请求")
|
||
log.Debugf("[HTTP] 代理链路: %s -> [HTTP:%s] -> [HTTPS:%s] -> %s",
|
||
r.RemoteAddr,
|
||
s.config.HttpAddr,
|
||
s.upstreamDialer.config.Server,
|
||
r.Host)
|
||
|
||
clientAddr := r.RemoteAddr
|
||
startTime := time.Now()
|
||
upBytes := &atomic.Int64{}
|
||
downBytes := &atomic.Int64{}
|
||
|
||
// 详细的请求信息
|
||
log.Debugf("[HTTP] 请求详情:")
|
||
log.Debugf("[HTTP] - 客户端地址: %s", clientAddr)
|
||
log.Debugf("[HTTP] - 请求方法: %s", r.Method)
|
||
log.Debugf("[HTTP] - 请求URL: %s", r.URL)
|
||
log.Debugf("[HTTP] - HTTP版本: %s", r.Proto)
|
||
log.Debugf("[HTTP] - Host头: %s", r.Host)
|
||
log.Debugf("[HTTP] - 远程地址: %s", r.RemoteAddr)
|
||
log.Debugf("[HTTP] - 请求URI: %s", r.RequestURI)
|
||
log.Debugf("[HTTP] - Content-Length: %d", r.ContentLength)
|
||
log.Debugf("[HTTP] - Transfer-Encoding: %v", r.TransferEncoding)
|
||
log.Debugf("[HTTP] - Close: %v", r.Close)
|
||
log.Debugf("[HTTP] - TLS: %v", r.TLS != nil)
|
||
|
||
// 打印所有请求头
|
||
log.Debugf("[HTTP] 请求头:")
|
||
for k, vs := range r.Header {
|
||
for _, v := range vs {
|
||
log.Debugf("[HTTP] %s: %s", k, v)
|
||
// 如果是认证头,解码并显示
|
||
if strings.EqualFold(k, "Proxy-Authorization") || strings.EqualFold(k, "Authorization") {
|
||
if strings.HasPrefix(v, "Basic ") {
|
||
if decoded, err := base64.StdEncoding.DecodeString(v[6:]); err == nil {
|
||
log.Debugf("[HTTP] %s (decoded): %s", k, string(decoded))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 打印Cookie信息
|
||
if cookies := r.Cookies(); len(cookies) > 0 {
|
||
log.Debugf("[HTTP] Cookies:")
|
||
for _, cookie := range cookies {
|
||
log.Debugf("[HTTP] - %s: %s", cookie.Name, cookie.Value)
|
||
}
|
||
}
|
||
|
||
s.activeConns.Add(1)
|
||
defer s.activeConns.Done()
|
||
|
||
if r.Method != http.MethodConnect {
|
||
log.Debugf("[HTTP] 不支持的请求方法: %s", r.Method)
|
||
http.Error(w, "仅支持CONNECT方法", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
hij, ok := w.(http.Hijacker)
|
||
if !ok {
|
||
log.Debugf("[HTTP] 当前连接不支持hijacking")
|
||
http.Error(w, "不支持hijacking", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
proxyClient, _, err := hij.Hijack()
|
||
if err != nil {
|
||
log.Debugf("[HTTP] Hijack失败: %v", err)
|
||
http.Error(w, err.Error(), http.StatusServiceUnavailable)
|
||
return
|
||
}
|
||
|
||
defer func() {
|
||
proxyClient.Close()
|
||
duration := time.Since(startTime)
|
||
log.Debugf("[HTTP] =====================================================")
|
||
log.Infof("[HTTP] 连接统计 [%s]:", clientAddr)
|
||
log.Infof("[HTTP] - 目标地址: %s", r.Host)
|
||
log.Infof("[HTTP] - 连接时长: %v", duration.Round(time.Millisecond))
|
||
log.Infof("[HTTP] - 上行流量: %s", formatBytes(upBytes.Load()))
|
||
log.Infof("[HTTP] - 下行流量: %s", formatBytes(downBytes.Load()))
|
||
log.Infof("[HTTP] - 总流量: %s", formatBytes(upBytes.Load()+downBytes.Load()))
|
||
log.Debugf("[HTTP] =====================================================")
|
||
}()
|
||
|
||
log.Debugf("[HTTP] 开始连接目标服务器: %s", r.Host)
|
||
target, err := s.dialTarget(r.Host)
|
||
if err != nil {
|
||
log.Errorf("[HTTP] 连接目标服务器失败: %v", err)
|
||
proxyClient.Write([]byte("HTTP/1.1 502 Bad Gateway\r\n\r\n"))
|
||
return
|
||
}
|
||
|
||
log.Debugf("[HTTP] 发送连接成功响应:")
|
||
respHeaders := "HTTP/1.1 200 Connection Established\r\n" +
|
||
"Proxy-Agent: Go-Proxy-Client\r\n" +
|
||
"Connection: keep-alive\r\n\r\n"
|
||
log.Debugf("[HTTP] 响应头:")
|
||
for _, line := range strings.Split(respHeaders, "\r\n") {
|
||
if line != "" {
|
||
log.Debugf("[HTTP] %s", line)
|
||
}
|
||
}
|
||
proxyClient.Write([]byte(respHeaders))
|
||
log.Infof("[HTTP] 成功建立连接: %s -> %s", clientAddr, r.Host)
|
||
|
||
var wg sync.WaitGroup
|
||
wg.Add(2)
|
||
|
||
// 上行数据传输
|
||
go func() {
|
||
defer wg.Done()
|
||
log.Debugf("[HTTP] 开始上行数据传输: %s -> %s", clientAddr, r.Host)
|
||
n, err := io.Copy(target, proxyClient)
|
||
upBytes.Add(n)
|
||
if err != nil {
|
||
log.Debugf("[HTTP] 上行传输错误 [%s -> %s]: %v", clientAddr, r.Host, err)
|
||
}
|
||
log.Debugf("[HTTP] 上行传输完成: %s", formatBytes(n))
|
||
}()
|
||
|
||
// 下行数据传输
|
||
go func() {
|
||
defer wg.Done()
|
||
log.Debugf("[HTTP] 开始下行数据传输: %s -> %s", r.Host, clientAddr)
|
||
n, err := io.Copy(proxyClient, target)
|
||
downBytes.Add(n)
|
||
if err != nil {
|
||
log.Debugf("[HTTP] 下行传输错误 [%s -> %s]: %v", r.Host, clientAddr, err)
|
||
}
|
||
log.Debugf("[HTTP] 下行传输完成: %s", formatBytes(n))
|
||
}()
|
||
|
||
wg.Wait()
|
||
log.Debugf("[HTTP] 连接关闭: %s <-> %s", clientAddr, r.Host)
|
||
}
|
||
|
||
// formatBytes 格式化字节数
|
||
func formatBytes(bytes int64) string {
|
||
const unit = 1024
|
||
if bytes < unit {
|
||
return fmt.Sprintf("%d B", bytes)
|
||
}
|
||
div, exp := int64(unit), 0
|
||
for n := bytes / unit; n >= unit; n /= unit {
|
||
div *= unit
|
||
exp++
|
||
}
|
||
return fmt.Sprintf("%.2f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
||
}
|
||
|
||
// handleSocks5Handshake 处理SOCKS5握手
|
||
func (s *Server) handleSocks5Handshake(client net.Conn) error {
|
||
log := logger.Get()
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
log.Debugf("[SOCKS5] 开始握手阶段")
|
||
|
||
// 读取客户端支持的认证方法
|
||
buf := make([]byte, 2)
|
||
if _, err := io.ReadFull(client, buf); err != nil {
|
||
log.Debugf("[SOCKS5] 读取认证方法失败: %v", err)
|
||
return fmt.Errorf("读取认证方法失败: %v", err)
|
||
}
|
||
|
||
log.Debugf("[SOCKS5] 收到握手请求:")
|
||
log.Debugf("[SOCKS5] - 版本号: SOCKS%d", buf[0])
|
||
log.Debugf("[SOCKS5] - 认证方法数量: %d", buf[1])
|
||
|
||
// 读取认证方法列表
|
||
methods := make([]byte, buf[1])
|
||
if _, err := io.ReadFull(client, methods); err != nil {
|
||
log.Debugf("[SOCKS5] 读取认证方法列表失败: %v", err)
|
||
return fmt.Errorf("读取认证方法列表失败: %v", err)
|
||
}
|
||
|
||
log.Debugf("[SOCKS5] 支持的认证方法:")
|
||
for _, method := range methods {
|
||
log.Debugf("[SOCKS5] - 0x%02x (%s)", method, socks5AuthMethodToString(method))
|
||
}
|
||
|
||
// 选择无认证方法
|
||
response := []byte{0x05, 0x00}
|
||
if _, err := client.Write(response); err != nil {
|
||
log.Debugf("[SOCKS5] 发送认证响应失败: %v", err)
|
||
return fmt.Errorf("发送认证响应失败: %v", err)
|
||
}
|
||
|
||
log.Debugf("[SOCKS5] 发送握手响应:")
|
||
log.Debugf("[SOCKS5] - 版本号: SOCKS5")
|
||
log.Debugf("[SOCKS5] - 选择的认证方法: 0x00 (NO AUTHENTICATION REQUIRED)")
|
||
log.Debugf("[SOCKS5] 握手完成")
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
|
||
return nil
|
||
}
|
||
|
||
// handleSocks5Request 处理SOCKS5请求
|
||
func (s *Server) handleSocks5Request(client net.Conn) (net.Conn, string, error) {
|
||
log := logger.Get()
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
log.Debugf("[SOCKS5] 开始处理请求")
|
||
log.Debugf("[SOCKS5] 代理链路: %s -> [SOCKS5:%s] -> [HTTPS:%s]",
|
||
client.RemoteAddr(),
|
||
s.config.Socks5Addr,
|
||
s.upstreamDialer.config.Server)
|
||
|
||
// 读取请求头
|
||
buf := make([]byte, 4)
|
||
if _, err := io.ReadFull(client, buf); err != nil {
|
||
log.Debugf("[SOCKS5] 读取请求头失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取请求头失败: %v", err)
|
||
}
|
||
|
||
log.Debugf("[SOCKS5] 收到请求头:")
|
||
log.Debugf("[SOCKS5] - 版本号: SOCKS%d", buf[0])
|
||
log.Debugf("[SOCKS5] - 命令: %s (0x%02x)", socks5CmdToString(buf[1]), buf[1])
|
||
log.Debugf("[SOCKS5] - 保留字节: 0x%02x", buf[2])
|
||
log.Debugf("[SOCKS5] - 地址类型: %s (0x%02x)", socks5AddrTypeToString(buf[3]), buf[3])
|
||
|
||
// 读取目标地址
|
||
var addr string
|
||
switch buf[3] {
|
||
case 0x01: // IPv4
|
||
ipv4 := make([]byte, 4)
|
||
if _, err := io.ReadFull(client, ipv4); err != nil {
|
||
log.Debugf("[SOCKS5] 读取IPv4地址失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取IPv4地址失败: %v", err)
|
||
}
|
||
addr = net.IP(ipv4).String()
|
||
log.Debugf("[SOCKS5] - IPv4地址: %s", addr)
|
||
|
||
case 0x03: // 域名
|
||
domainLen := make([]byte, 1)
|
||
if _, err := io.ReadFull(client, domainLen); err != nil {
|
||
log.Debugf("[SOCKS5] 读取域名长度失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取域名长度失败: %v", err)
|
||
}
|
||
domain := make([]byte, domainLen[0])
|
||
if _, err := io.ReadFull(client, domain); err != nil {
|
||
log.Debugf("[SOCKS5] 读取域名失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取域名失败: %v", err)
|
||
}
|
||
addr = string(domain)
|
||
log.Debugf("[SOCKS5] - 域名长度: %d", domainLen[0])
|
||
log.Debugf("[SOCKS5] - 域名: %s", addr)
|
||
|
||
case 0x04: // IPv6
|
||
ipv6 := make([]byte, 16)
|
||
if _, err := io.ReadFull(client, ipv6); err != nil {
|
||
log.Debugf("[SOCKS5] 读取IPv6地址失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取IPv6地址失败: %v", err)
|
||
}
|
||
addr = net.IP(ipv6).String()
|
||
log.Debugf("[SOCKS5] - IPv6地址: %s", addr)
|
||
}
|
||
|
||
// 读取端口
|
||
portBuf := make([]byte, 2)
|
||
if _, err := io.ReadFull(client, portBuf); err != nil {
|
||
log.Debugf("[SOCKS5] 读取端口失败: %v", err)
|
||
return nil, "", fmt.Errorf("读取端口失败: %v", err)
|
||
}
|
||
port := binary.BigEndian.Uint16(portBuf)
|
||
targetAddr := fmt.Sprintf("%s:%d", addr, port)
|
||
log.Debugf("[SOCKS5] 完整代理链路: %s -> [SOCKS5:%s] -> [HTTPS:%s] -> %s",
|
||
client.RemoteAddr(),
|
||
s.config.Socks5Addr,
|
||
s.upstreamDialer.config.Server,
|
||
targetAddr)
|
||
log.Debugf("[SOCKS5] - 端口: %d", port)
|
||
log.Debugf("[SOCKS5] - 完整目标地址: %s", targetAddr)
|
||
|
||
// 连接目标服务器
|
||
log.Debugf("[SOCKS5] 开始连接目标服务器...")
|
||
target, err := s.dialTarget(targetAddr)
|
||
if err != nil {
|
||
log.Debugf("[SOCKS5] 连接目标服务器失败: %v", err)
|
||
// 发送失败响应
|
||
resp := []byte{0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
log.Debugf("[SOCKS5] 发送失败响应: %x", resp)
|
||
client.Write(resp)
|
||
return nil, "", fmt.Errorf("连接目标服务器失败: %v", err)
|
||
}
|
||
|
||
// 发送成功响应
|
||
resp := []byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
log.Debugf("[SOCKS5] 发送成功响应: %x", resp)
|
||
client.Write(resp)
|
||
|
||
log.Debugf("[SOCKS5] 请求处理完成")
|
||
log.Debugf("[SOCKS5] =====================================================")
|
||
|
||
return target, targetAddr, nil
|
||
}
|
||
|
||
// 辅助函数:将SOCKS5认证方法转换为字符串
|
||
func socks5AuthMethodToString(method byte) string {
|
||
switch method {
|
||
case 0x00:
|
||
return "NO AUTHENTICATION REQUIRED"
|
||
case 0x01:
|
||
return "GSSAPI"
|
||
case 0x02:
|
||
return "USERNAME/PASSWORD"
|
||
case 0xff:
|
||
return "NO ACCEPTABLE METHODS"
|
||
default:
|
||
return fmt.Sprintf("UNKNOWN METHOD(0x%02x)", method)
|
||
}
|
||
}
|
||
|
||
// 辅助函数:将SOCKS5命令转换为字符串
|
||
func socks5CmdToString(cmd byte) string {
|
||
switch cmd {
|
||
case 0x01:
|
||
return "CONNECT"
|
||
case 0x02:
|
||
return "BIND"
|
||
case 0x03:
|
||
return "UDP ASSOCIATE"
|
||
default:
|
||
return fmt.Sprintf("UNKNOWN COMMAND(0x%02x)", cmd)
|
||
}
|
||
}
|
||
|
||
// 辅助函数:将SOCKS5地址类型转换为字符串
|
||
func socks5AddrTypeToString(addrType byte) string {
|
||
switch addrType {
|
||
case 0x01:
|
||
return "IPv4"
|
||
case 0x03:
|
||
return "DOMAIN"
|
||
case 0x04:
|
||
return "IPv6"
|
||
default:
|
||
return fmt.Sprintf("UNKNOWN ADDRESS TYPE(0x%02x)", addrType)
|
||
}
|
||
}
|
||
|
||
// dialTarget 连接目标服务器
|
||
func (s *Server) dialTarget(addr string) (net.Conn, error) {
|
||
log := logger.Get()
|
||
log.Debugf("[PROXY] =====================================================")
|
||
log.Debugf("[PROXY] 开始处理连接请求: %s", addr)
|
||
|
||
// 使用代理连接
|
||
log.Debugf("[PROXY] 使用代理连接:")
|
||
log.Debugf("[PROXY] - 上游代理: %s", s.upstreamDialer.config.Server)
|
||
log.Debugf("[PROXY] - 代理类型: %s", s.upstreamDialer.config.Type)
|
||
|
||
conn, err := s.upstreamDialer.Dial("tcp", addr)
|
||
if err != nil {
|
||
log.Errorf("[PROXY] 代理连接失败: %v", err)
|
||
log.Debugf("[PROXY] =====================================================")
|
||
return nil, err
|
||
}
|
||
|
||
log.Debugf("[PROXY] 代理连接成功")
|
||
log.Debugf("[PROXY] 连接详情:")
|
||
log.Debugf("[PROXY] - 本地地址: %s", conn.LocalAddr())
|
||
log.Debugf("[PROXY] - 远程地址: %s", conn.RemoteAddr())
|
||
log.Debugf("[PROXY] =====================================================")
|
||
|
||
return conn, nil
|
||
}
|