我公司有大量的边缘设备部署在各个地方，但是边缘设备没有公网ip无法直接连接，所以帮我用golang实现个适用于生产环境的反向代理

业务描述:

服务端运行在中转服务器上，客户端运行在边缘设备上，
服务端运行后会监听3个端口，10101端口用于和客户端连接，10102端口监听的是http代理服务,10103监听的是socks5代理服务
客户端运行后就主动连上服务端,
然后通过服务端的代理端口来请求，实际的出口ip是边缘设备，通过不同的代理认证的账户来对应不同的设备
比如中转服务器的公网ip为1.1.1.1，边缘设备1的id为test1,公网ip为119.29.29.29
那么curl -x socks5://test1:123456@1.1.1.1:10103 ifconfig.me ，显示的结果就是119.29.29.29，使用别的代理账户就对应到该id的盒子上，
也可以使用http代理,curl -x http://test1:123456@1.1.1.1:10102 ifconfig.me

所以服务端和客户端之间的数据转发是不是可以用零拷贝这种性能最高的方式

必须要做到的点:
客户端:
1.客户端运行时会接收一个 -id 参数，连接服务端后会将该id参数传递给服务端,这个id就是对应的代理认证的账户名
2.需要有断线重连的机制，不论是自己掉线，还是服务端连不上，都需要有自动重连
3.客户端需要考虑到同时连接到多个不同的中转服务器，封装成函数，参数为服务端地址，方便随时调用，执行后就一直保持和服务端连接并断开重连
4.客户端需要有一个主动与某个服务端断开连接的函数，程序中不会调用，但是得准备一个让我自己二次开发去调用，参数也为服务端地址，执行后就彻底和服务端断开了，除非重新执行连接到服务端的函数
服务端:
1.http和socks5的代理认证密码暂时都固定为123456
2.http和socks5代理功能可以用合适的第三方库，socks5代理一定要支持udp,所以在选在第三方socks5代理库的时候就直接找支持udp的， 3.代码设计,需要考虑到超高并发的情况
4.如果代理请求的账户没有对应的客户端或者没检测到代理账户或者密码不正确，都需要中止代理请求返回空

两部分代码都必须需要做到的点:
1.代码尽量在提升稳定性和支持超高并发上作出尽可能多的优化，比如利用多核、连接池等，满足稳定和性能后最后考虑代码的精简
2.不要发我有bug的代码，发之前好好检查下有无bug，确保发送给我的是能直接跑通的代码
3.不要给我留todo、待完善的代码，直接发我实现我所有需求的完善的代码


——————————————————————————————————————————————————————
上面是我的需求



------------------------------------server.go--------------------------------------------------------------------------


// server.go
package main

import (
    "bufio"
    "context"
    "encoding/base64"
    "errors"
    "github.com/txthinking/socks5"
    "github.com/xtaci/smux"
    "io"
    "log"
    "net"
    "net/http"
    "strings"
    "sync"
    "time"
)

const (
    CMD_CONNECT       = 1
    CMD_UDP_ASSOCIATE = 3
    password          = "123456"
)

var (
    clients    sync.Map // map[id]*smux.Session
    clientsUDP sync.Map // map[id]*net.UDPConn
)

func main() {
    go acceptClients()

    go startSocks5Proxy()

    startHTTPProxy()
}

// 接受客户端连接
func acceptClients() {
    ln, err := net.Listen("tcp", ":10101")
    if err != nil {
        log.Fatalf("Failed to listen on 10101: %v", err)
    }
    log.Println("Listening for clients on :10101")
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Printf("Failed to accept client connection: %v", err)
            continue
        }
        go handleClient(conn)
    }
}

func handleClient(conn net.Conn) {
    reader := bufio.NewReader(conn)
    idLine, err := reader.ReadString('\n')
    if err != nil {
        log.Printf("Failed to read id from client: %v", err)
        conn.Close()
        return
    }
    id := strings.TrimSpace(idLine)
    if id == "" {
        log.Printf("Client sent empty id")
        conn.Close()
        return
    }
    log.Printf("Client connected with id: %s", id)

    session, err := smux.Server(conn, nil)
    if err != nil {
        log.Printf("Failed to create smux session: %v", err)
        conn.Close()
        return
    }

    clients.Store(id, session)

    // 保持会话，直到会话关闭
    for {
        if session.IsClosed() {
            break
        }
        time.Sleep(time.Second)
    }

    log.Printf("Session with id %s closed", id)
    clients.Delete(id)
}

// 启动SOCKS5代理
func startSocks5Proxy() {
    server := socks5.NewServer(&socks5.Config{
        AuthMethods: []socks5.Authenticator{
            &socks5.UserPassAuthenticator{
                User:     validateUser,
                Password: validatePassword,
            },
        },
        CredentialsOptional: false,
        BindIP:              net.ParseIP("0.0.0.0"),
        BindPort:            10103,
        EnableUDP:           true,
        UDPIdleTime:         60 * time.Second,
        Handler:             customSocks5Handler,
    })

    log.Println("SOCKS5 proxy listening on :10103")
    if err := server.ListenAndServe("tcp", "0.0.0.0:10103"); err != nil {
        log.Fatalf("SOCKS5 server error: %v", err)
    }
}

// 验证用户名
func validateUser(username string) bool {
    _, ok := clients.Load(username)
    return ok
}

// 验证密码
func validatePassword(providedPassword string) bool {
    return providedPassword == password
}

// 自定义处理器
func customSocks5Handler(conn net.Conn, req *socks5.Request) error {
    username := req.AuthContext.User
    sessionI, ok := clients.Load(username)
    if !ok {
        return errors.New("no client session for user")
    }
    session := sessionI.(*smux.Session)

    switch req.Cmd {
    case socks5.CmdConnect:
        return handleSocks5Connect(conn, req, session)
    case socks5.CmdUDPAssociate:
        return handleSocks5UDPAssociate(conn, req, session)
    default:
        return socks5.ErrCmdNotSupported
    }
}

func handleSocks5Connect(conn net.Conn, req *socks5.Request, session *smux.Session) error {
    stream, err := session.OpenStream()
    if err != nil {
        return err
    }
    defer stream.Close()

    // 发送命令和地址给客户端
    command := []byte{CMD_CONNECT}
    addrBytes := []byte(req.DestAddr.Address())
    addrLen := byte(len(addrBytes))
    buf := append(command, addrLen)
    buf = append(buf, addrBytes...)
    _, err = stream.Write(buf)
    if err != nil {
        return err
    }

    // 双向复制数据
    go func() {
        io.Copy(stream, conn)
        conn.Close()
    }()
    io.Copy(conn, stream)
    return nil
}

func handleSocks5UDPAssociate(conn net.Conn, req *socks5.Request, session *smux.Session) error {
    udpConn, err := net.ListenUDP("udp", req.DestAddr.Address().(*net.UDPAddr))
    if err != nil {
        return err
    }
    defer udpConn.Close()

    // 将 UDP 连接保存起来
    username := req.AuthContext.User
    clientsUDP.Store(username, udpConn)

    buf := make([]byte, 65535)
    for {
        n, addr, err := udpConn.ReadFromUDP(buf)
        if err != nil {
            log.Printf("UDP read error: %v", err)
            continue
        }

        // 处理 UDP 数据包
        go handleUDPDatagram(buf[:n], addr, session)
    }
}

func handleUDPDatagram(data []byte, addr *net.UDPAddr, session *smux.Session) {
    stream, err := session.OpenStream()
    if err != nil {
        log.Printf("Failed to open stream for UDP: %v", err)
        return
    }
    defer stream.Close()

    // 发送命令和地址到客户端
    command := []byte{CMD_UDP_ASSOCIATE}
    destAddr := addr.String()
    destAddrBytes := []byte(destAddr)
    destAddrLen := uint16(len(destAddrBytes))

    header := make([]byte, 2)
    header[0] = byte(destAddrLen >> 8)
    header[1] = byte(destAddrLen & 0xff)
    header = append(header, destAddrBytes...)

    packet := append(command, header...)
    packet = append(packet, data...)
    _, err = stream.Write(packet)
    if err != nil {
        log.Printf("Failed to write to stream: %v", err)
        return
    }

    // 从客户端读取回复
    reply := make([]byte, 65535)
    n, err := stream.Read(reply)
    if err != nil {
        log.Printf("Failed to read from stream: %v", err)
        return
    }

    // 发送回复到 UDP 客户端
    if value, ok := clientsUDP.Load(session); ok {
        udpConn := value.(*net.UDPConn)
        _, err = udpConn.WriteToUDP(reply[:n], addr)
        if err != nil {
            log.Printf("Failed to write to UDP client: %v", err)
            return
        }
    }
}

// 启动 HTTP 代理
func startHTTPProxy() {
    handler := &ProxyHandler{}
    server := &http.Server{
        Addr:    ":10102",
        Handler: handler,
    }
    log.Println("HTTP proxy listening on :10102")
    err := server.ListenAndServe()
    if err != nil {
        log.Fatalf("HTTP proxy server error: %v", err)
    }
}

type ProxyHandler struct{}

func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // 基本认证
    username, suppliedPassword, ok := basicAuth(r)
    if !ok || suppliedPassword != password {
        w.Header().Set("Proxy-Authenticate", "Basic realm=\"Proxy Authorization\"")
        http.Error(w, "Unauthorized", http.StatusProxyAuthRequired)
        return
    }

    // 检查客户端是否已连接
    sessionI, ok := clients.Load(username)
    if !ok {
        http.Error(w, "No client found for user", http.StatusBadGateway)
        return
    }
    session := sessionI.(*smux.Session)

    if r.Method == http.MethodConnect {
        // 处理 HTTPS 隧道
        h.handleTunnel(w, r, session)
    } else {
        // 处理 HTTP 请求
        h.handleHTTP(w, r, session)
    }
}

func basicAuth(r *http.Request) (username, password string, ok bool) {
    auth := r.Header.Get("Proxy-Authorization")
    if auth == "" {
        return "", "", false
    }
    const prefix = "Basic "
    if !strings.HasPrefix(auth, prefix) {
        return "", "", false
    }
    payload, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
    if err != nil {
        return "", "", false
    }
    s := string(payload)
    parts := strings.SplitN(s, ":", 2)
    if len(parts) != 2 {
        return "", "", false
    }
    return parts[0], parts[1], true
}

func (h *ProxyHandler) handleTunnel(w http.ResponseWriter, r *http.Request, session *smux.Session) {
    // 劫持连接
    hijacker, ok := w.(http.Hijacker)
    if !ok {
        http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
        return
    }
    clientConn, _, err := hijacker.Hijack()
    if err != nil {
        http.Error(w, err.Error(), http.StatusServiceUnavailable)
        return
    }
    defer clientConn.Close()

    // 通过客户端连接目标地址
    targetAddr := r.Host
    stream, err := session.OpenStream()
    if err != nil {
        http.Error(w, "Failed to open stream", http.StatusServiceUnavailable)
        return
    }
    defer stream.Close()

    // 发送命令和地址给客户端
    command := []byte{CMD_CONNECT}
    addrBytes := []byte(targetAddr)
    addrLen := byte(len(addrBytes))
    buf := append(command, addrLen)
    buf = append(buf, addrBytes...)
    _, err = stream.Write(buf)
    if err != nil {
        http.Error(w, "Failed to send command to client", http.StatusServiceUnavailable)
        return
    }

    // 发送 200 Connection Established
    _, err = clientConn.Write([]byte("HTTP/1.1 200 Connection Established\r\n\r\n"))
    if err != nil {
        return
    }

    // 数据交换
    go func() {
        io.Copy(stream, clientConn)
        stream.Close()
    }()
    io.Copy(clientConn, stream)
}

func (h *ProxyHandler) handleHTTP(w http.ResponseWriter, r *http.Request, session *smux.Session) {
    // 创建新的请求
    req, err := http.NewRequest(r.Method, r.RequestURI, r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    req.Header = r.Header.Clone()

    // 移除代理认证头
    req.Header.Del("Proxy-Authorization")

    // 通过客户端发送请求
    transport := &http.Transport{
        DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
            stream, err := session.OpenStream()
            if err != nil {
                return nil, err
            }
            // 发送命令和地址给客户端
            command := []byte{CMD_CONNECT}
            addrBytes := []byte(addr)
            addrLen := byte(len(addrBytes))
            buf := append(command, addrLen)
            buf = append(buf, addrBytes...)
            _, err = stream.Write(buf)
            if err != nil {
                stream.Close()
                return nil, err
            }
            return &streamConn{Stream: stream}, nil
        },
    }
    resp, err := transport.RoundTrip(req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusServiceUnavailable)
        return
    }
    defer resp.Body.Close()

    // 将响应复制回客户端
    copyHeader(w.Header(), resp.Header)
    w.WriteHeader(resp.StatusCode)
    io.Copy(w, resp.Body)
}

func copyHeader(dst, src http.Header) {
    for k, vv := range src {
        for _, v := range vv {
            dst.Add(k, v)
        }
    }
}

type streamConn struct {
    *smux.Stream
}

func (s *streamConn) LocalAddr() net.Addr {
    return s.Stream.LocalAddr()
}

func (s *streamConn) RemoteAddr() net.Addr {
    return s.Stream.RemoteAddr()
}

func (s *streamConn) SetDeadline(t time.Time) error {
    err1 := s.Stream.SetReadDeadline(t)
    err2 := s.Stream.SetWriteDeadline(t)
    if err1 != nil {
        return err1
    }
    return err2
}

func (s *streamConn) SetReadDeadline(t time.Time) error {
    return s.Stream.SetReadDeadline(t)
}

func (s *streamConn) SetWriteDeadline(t time.Time) error {
    return s.Stream.SetWriteDeadline(t)
}




------------------------------------client.go--------------------------------------------------------------------------



// client.go
package main

import (
    "flag"
    "fmt"
    "github.com/xtaci/smux"
    "io"
    "log"
    "net"
    "os"
    "strings"
    "sync"
    "time"
)

const (
    CMD_CONNECT       = 1
    CMD_UDP_ASSOCIATE = 3
)

type ServerConnection struct {
    address string
    session *smux.Session
    conn    net.Conn
}

var (
    serverConnections = sync.Map{} // map[string]*ServerConnection
)

func main() {
    id := flag.String("id", "", "client ID")
    serverAddrs := flag.String("servers", "", "comma-separated list of server addresses")
    flag.Parse()

    if *id == "" || *serverAddrs == "" {
        flag.Usage()
        os.Exit(1)
    }

    servers := strings.Split(*serverAddrs, ",")

    for _, server := range servers {
        go connectToServer(server+":10101", *id)
    }

    // 等待，保持程序运行
    select {}
}

func connectToServer(serverAddr string, id string) {
    for {
        err := connect(serverAddr, id)
        if err != nil {
            log.Printf("Failed to connect to server %s: %v", serverAddr, err)
        }
        time.Sleep(5 * time.Second)
    }
}

func connect(serverAddr string, id string) error {
    conn, err := net.Dial("tcp", serverAddr)
    if err != nil {
        return err
    }
    defer conn.Close()

    // 发送id
    _, err = conn.Write([]byte(id + "\n"))
    if err != nil {
        return err
    }

    // 设置smux会话
    session, err := smux.Server(conn, nil)
    if err != nil {
        return err
    }
    defer session.Close()

    serverConnections.Store(serverAddr, &ServerConnection{
        address: serverAddr,
        session: session,
        conn:    conn,
    })

    log.Printf("Connected to server %s", serverAddr)

    for {
        stream, err := session.AcceptStream()
        if err != nil {
            return err
        }
        go handleStream(stream)
    }
}

// 主动断开与某个服务端的连接函数
func disconnectFromServer(serverAddr string) {
    value, ok := serverConnections.Load(serverAddr)
    if ok {
        sc := value.(*ServerConnection)
        sc.session.Close()
        sc.conn.Close()
        serverConnections.Delete(serverAddr)
        log.Printf("Disconnected from server %s", serverAddr)
    }
}

func handleStream(stream *smux.Stream) {
    defer stream.Close()

    // 读取命令
    var cmd [1]byte
    _, err := io.ReadFull(stream, cmd[:])
    if err != nil {
        log.Printf("Failed to read command: %v", err)
        return
    }

    switch cmd[0] {
    case CMD_CONNECT:
        handleConnect(stream)
    case CMD_UDP_ASSOCIATE:
        handleUDPAssociate(stream)
    default:
        log.Printf("Unknown command: %d", cmd[0])
    }
}

func handleConnect(stream *smux.Stream) {
    // 读取地址长度
    var addrLen [1]byte
    _, err := io.ReadFull(stream, addrLen[:])
    if err != nil {
        log.Printf("Failed to read addrLen: %v", err)
        return
    }

    addr := make([]byte, addrLen[0])
    _, err = io.ReadFull(stream, addr)
    if err != nil {
        log.Printf("Failed to read addr: %v", err)
        return
    }

    targetAddr := string(addr)
    log.Printf("Connecting to %s", targetAddr)

    targetConn, err := net.Dial("tcp", targetAddr)
    if err != nil {
        log.Printf("Failed to connect to target %s: %v", targetAddr, err)
        stream.Close()
        return
    }
    defer targetConn.Close()

    // 双向复制
    go func() {
        _, _ = io.Copy(targetConn, stream)
        targetConn.Close()
    }()
    _, _ = io.Copy(stream, targetConn)
}

func handleUDPAssociate(stream *smux.Stream) {
    defer stream.Close()

    // 读取目标地址长度
    var destAddrLen [2]byte
    _, err := io.ReadFull(stream, destAddrLen[:])
    if err != nil {
        log.Printf("Failed to read destAddrLen: %v", err)
        return
    }
    length := uint16(destAddrLen[0])<<8 | uint16(destAddrLen[1])
    destAddrBytes := make([]byte, length)
    _, err = io.ReadFull(stream, destAddrBytes)
    if err != nil {
        log.Printf("Failed to read destAddr: %v", err)
        return
    }
    destAddr := string(destAddrBytes)

    log.Printf("UDP Associate to %s", destAddr)

    // 读取数据
    data, err := io.ReadAll(stream)
    if err != nil {
        log.Printf("Failed to read UDP data: %v", err)
        return
    }

    // 发送UDP数据到目标
    udpAddr, err := net.ResolveUDPAddr("udp", destAddr)
    if err != nil {
        log.Printf("Failed to resolve UDP addr %s: %v", destAddr, err)
        return
    }
    conn, err := net.DialUDP("udp", nil, udpAddr)
    if err != nil {
        log.Printf("Failed to dial UDP %s: %v", destAddr, err)
        return
    }
    defer conn.Close()
    _, err = conn.Write(data)
    if err != nil {
        log.Printf("Failed to send UDP to target %s: %v", destAddr, err)
        return
    }

    // 读取回应
    buf := make([]byte, 65535)
    n, _, err := conn.ReadFromUDP(buf)
    if err != nil {
        log.Printf("Failed to read UDP reply: %v", err)
        return
    }

    // 回应服务器
    _, err = stream.Write(buf[:n])
    if err != nil {
        log.Printf("Failed to send UDP reply back to server: %v", err)
        return
    }
}












上面分别是服务端和客户端的源码，现在服务端代码编译报错

root@VM-4-17-ubuntu:/opt/hzsrv# /usr/local/go/bin/go build -ldflags "-w -s" -o server server.go 
# command-line-arguments
./server.go:95:22: undefined: socks5.NewServer
./server.go:95:40: undefined: socks5.Config
./server.go:96:31: undefined: socks5.Authenticator
./server.go:97:21: undefined: socks5.UserPassAuthenticator
./server.go:129:21: req.AuthContext undefined (type *socks5.Request has no field or method AuthContext)
./server.go:139:17: undefined: socks5.CmdUDPAssociate
./server.go:142:23: undefined: socks5.ErrCmdNotSupported
./server.go:155:29: req.DestAddr undefined (type *socks5.Request has no field or method DestAddr)
./server.go:174:46: req.DestAddr undefined (type *socks5.Request has no field or method DestAddr)
./server.go:181:21: req.AuthContext undefined (type *socks5.Request has no field or method AuthContext)
./server.go:181:21: too many errors

帮我解决下发修复后的代码给我，顺便看下代码是否符合我所有的需求，不符合的也继续帮我完善好