我公司有大量的边缘设备部署在各个地方，但是边缘设备没有公网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"
    "encoding/base64"
    "errors"
    "fmt"
    "github.com/armon/go-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) {
    defer conn.Close()
    reader := bufio.NewReader(conn)
    idLine, err := reader.ReadString('\n')
    if err != nil {
        log.Printf("Failed to read id from client: %v", err)
        return
    }
    id := strings.TrimSpace(idLine)
    if id == "" {
        log.Printf("Client sent empty id")
        return
    }
    log.Printf("Client connected with id: %s", id)

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

    // 保持会话
    session.Wait()
    log.Printf("Session with id %s closed", id)
    clients.Delete(id)
}

// 启动SOCKS5代理
func startSocks5Proxy() {
    cred := Socks5Credential{}

    conf := &socks5.Config{
        AuthMethods: []socks5.Authenticator{socks5.UserPassAuthenticator{
            Credentials: cred,
        }},
        Dial:         socks5Dial,
        UDPEnabled:   true,
        AssociateUDP: socks5AssociateUDP,
    }
    server, err := socks5.New(conf)
    if err != nil {
        log.Fatalf("Failed to create SOCKS5 server: %v", err)
    }

    ln, err := net.Listen("tcp", ":10103")
    if err != nil {
        log.Fatalf("Failed to listen on 10103: %v", err)
    }
    log.Println("SOCKS5 proxy listening on :10103")
    err = server.Serve(ln)
    if err != nil {
        log.Fatalf("SOCKS5 server error: %v", err)
    }
}

type Socks5Credential struct{}

func (s Socks5Credential) Valid(username, suppliedPassword string) bool {
    if suppliedPassword != password {
        return false
    }
    _, ok := clients.Load(username)
    return ok
}

// 自定义Dial函数
func socks5Dial(ctx socks5.Context, network, addr string) (net.Conn, error) {
    username := ctx.AuthContext.Payload["Username"]
    sessionI, ok := clients.Load(username)
    if !ok {
        return nil, errors.New("no client session for user")
    }
    session := sessionI.(*smux.Session)
    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
    }

    // 返回stream作为连接
    return &streamConn{Stream: stream}, nil
}

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)
}

// 实现UDP Associate
func socks5AssociateUDP(clientConn net.Conn, dstAddr *net.UDPAddr) (*net.UDPAddr, error) {
    ctx := clientConn.Context()
    username := ctx.AuthContext.Payload["Username"]

    sessionI, ok := clients.Load(username)
    if !ok {
        return nil, errors.New("no client session for user")
    }
    session := sessionI.(*smux.Session)

    // 创建UDP监听器
    udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:0")
    if err != nil {
        return nil, err
    }
    udpConn, err := net.ListenUDP("udp", udpAddr)
    if err != nil {
        return nil, err
    }

    // 存储映射
    clientsUdp.Store(username, udpConn)

    // 启动goroutine处理UDP数据包
    go handleUdpPackets(udpConn, session)

    return udpConn.LocalAddr().(*net.UDPAddr), nil
}

func handleUdpPackets(udpConn *net.UDPConn, session *smux.Session) {
    defer udpConn.Close()
    buf := make([]byte, 65535)
    for {
        n, addr, err := udpConn.ReadFromUDP(buf)
        if err != nil {
            log.Printf("UDP read error: %v", err)
            return
        }
        // 对于每个数据包，发送到客户端

        // 打开新的stream
        stream, err := session.OpenStream()
        if err != nil {
            log.Printf("Failed to open stream: %v", err)
            continue
        }

        // 发送命令和地址到客户端
        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, buf[:n]...)
        _, err = stream.Write(packet)
        if err != nil {
            log.Printf("Failed to write to stream: %v", err)
            stream.Close()
            continue
        }

        go func(stream *smux.Stream) {
            defer stream.Close()
            // 从客户端读取回复
            reply := make([]byte, 65535)
            n, err := stream.Read(reply)
            if err != nil {
                log.Printf("Failed to read from stream: %v", err)
                return
            }
            // 发送回复到UDP客户端
            _, err = udpConn.WriteToUDP(reply[:n], addr)
            if err != nil {
                log.Printf("Failed to write to UDP client: %v", err)
                return
            }
        }(stream)
    }
}

// 启动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{
        Dial: func(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)
        }
    }
}




------------------------------------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:8:5: "fmt" imported and not used
./server.go:79:13: session.Wait undefined (type *smux.Session has no field or method Wait)
./server.go:93:9: unknown field UDPEnabled in struct literal of type socks5.Config
./server.go:94:9: unknown field AssociateUDP in struct literal of type socks5.Config
./server.go:123:28: undefined: socks5.Context
./server.go:182:23: clientConn.Context undefined (type net.Conn has no field or method Context)
root@VM-4-17-ubuntu:/opt/hzsrv# /usr/local/go/bin/go build -ldflags "-w -s" -o client client.go 
# command-line-arguments
./client.go:6:5: "fmt" imported and not used

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