Golang的socks5代理,流量限制转发到下一个socks5代理

问题描述 投票:0回答:1

第一个socks5代理有流量限制,下一个socks5代理没有流量限制。

使用curl下载类似的东西:

curl -x socks5://127.0.0.1:10801 -O https://mirrors.xxxx.iso

一开始,curl 下载得很好,流量限制起作用了,但过了一会儿,curl 速度变成了 0。

package main

import (
    "fmt"
    "github.com/juju/ratelimit"
    "io"
    "net"
)

var nextProxy = "127.0.0.1:10802"

func main() {
    server, err := net.Listen("tcp", ":10801")
    if err != nil {
        fmt.Printf("Listen failed: %v\n", err)
        return
    }

    for {
        client, err := server.Accept()
        if err != nil {
            fmt.Printf("Accept failed: %v", err)
            continue
        }

        go handle(client)
    }
}

func handle(conn net.Conn) {

    // add close
    defer conn.Close()

    // next socks5 proxy
    nextConn, err := net.Dial("tcp", nextProxy)
    if err != nil {
        fmt.Println("Failed to connect to next proxy:", err)
        conn.Close()
        return
    }
    defer nextConn.Close()

    go func() {
        _, err := Copy(nextConn, conn)
        if err != nil {
            fmt.Println("Error copying data to next proxy:", err)
            conn.Close()
        }
    }()

    _, err = Copy(conn, nextConn)
    if err != nil {
        fmt.Println("Error copying data from next proxy:", err)
        conn.Close()
    }
}

func Copy(left io.Writer, right io.Reader) (int64, error) {
    
    right = ratelimit.Reader(right, ratelimit.NewBucketWithRate(102400, 102400))

    return io.Copy(left, right)
}

我尝试过另一个

Copy
,例如:

func copyWithRateLimit(dst io.Writer, src io.Reader, limiter *ratelimit.Bucket) {
    // buffer
    buf := make([]byte, 32*1024) // 32KB buffer
    for {
        n, err := src.Read(buf)
        if err != nil {
            if err == io.EOF {
                return
            }
            fmt.Println("Error reading from source:", err)
            return
        }

        // Rate limit the data
        if limit := limiter.WaitMaxDuration(int64(n), time.Second); !limit {
            fmt.Println("Error rate limiting:", err)
            return
        }

        if _, err := dst.Write(buf[:n]); err != nil {
            fmt.Println("Error writing to destination:", err)
            return
        }
    }
}

即使你将缓冲区增加到64*1024,速度仍然会变成0,最终不起作用。


还有下一个没有流量限制的socks5代理,例如:

package main

import (
    "encoding/binary"
    "errors"
    "fmt"
    "io"
    "net"
)

func main() {
    server, err := net.Listen("tcp", ":10802")
    if err != nil {
        fmt.Printf("Listen failed: %v\n", err)
        return
    }

    for {
        client, err := server.Accept()
        if err != nil {
            fmt.Printf("Accept failed: %v", err)
            continue
        }

        go process(client)
    }
}

func process(client net.Conn) {
    if err := Socks5Auth(client); err != nil {
        fmt.Println("auth error:", err)
        client.Close()
        return
    }

    target, err := Socks5Connect(client)
    if err != nil {
        fmt.Println("connect error:", err)
        client.Close()
        return
    }

    Socks5Forward(client, target)
}

func Socks5Auth(client net.Conn) (err error) {
    buf := make([]byte, 256)

    n, err := io.ReadFull(client, buf[:2])
    if n != 2 {
        return errors.New("reading header: " + err.Error())
    }

    ver, nMethods := int(buf[0]), int(buf[1])
    if ver != 5 {
        return errors.New("invalid version")
    }

    n, err = io.ReadFull(client, buf[:nMethods])
    if n != nMethods {
        return errors.New("reading methods: " + err.Error())
    }

    n, err = client.Write([]byte{0x05, 0x00})
    if n != 2 || err != nil {
        return errors.New("write rsp: " + err.Error())
    }

    return nil
}

func Socks5Connect(client net.Conn) (net.Conn, error) {
    buf := make([]byte, 256)

    n, err := io.ReadFull(client, buf[:4])
    if n != 4 {
        return nil, errors.New("read header: " + err.Error())
    }

    ver, cmd, _, atyp := buf[0], buf[1], buf[2], buf[3]
    if ver != 5 || cmd != 1 {
        return nil, errors.New("invalid ver/cmd")
    }

    addr := ""
    switch atyp {
    case 1:
        n, err = io.ReadFull(client, buf[:4])
        if n != 4 {
            return nil, errors.New("invalid IPv4: " + err.Error())
        }
        addr = fmt.Sprintf("%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3])

    case 3:
        n, err = io.ReadFull(client, buf[:1])
        if n != 1 {
            return nil, errors.New("invalid hostname: " + err.Error())
        }
        addrLen := int(buf[0])

        n, err = io.ReadFull(client, buf[:addrLen])
        if n != addrLen {
            return nil, errors.New("invalid hostname: " + err.Error())
        }
        addr = string(buf[:addrLen])

    case 4:
        return nil, errors.New("IPv6: no supported yet")

    default:
        return nil, errors.New("invalid atyp")
    }

    n, err = io.ReadFull(client, buf[:2])
    if n != 2 {
        return nil, errors.New("read port: " + err.Error())
    }
    port := binary.BigEndian.Uint16(buf[:2])

    destAddrPort := fmt.Sprintf("%s:%d", addr, port)
    dest, err := net.Dial("tcp", destAddrPort)
    if err != nil {
        return nil, errors.New("dial dst: " + err.Error())
    }

    n, err = client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})
    if err != nil {
        dest.Close()
        return nil, errors.New("write rsp: " + err.Error())
    }

    return dest, nil
}

func Socks5Forward(client, target net.Conn) {

    forward := func(src, dest net.Conn) {
        defer src.Close()
        defer dest.Close()

        io.Copy(src, dest)
    }

    go forward(client, target)
    go forward(target, client)
}


在同一台计算机上启动两个程序并使用curl下载文件会产生以下结果:

curl different file result

做了一些测试。

  1. 设置第一个代理与本机带宽相同,
    curl
    正常下载文件。
  2. curl
    仅通过第二个socks5代理下载,并对第二个socks5代理设置限速,
    curl
    正常下载文件。
  3. 第一个代理和第二个代理都设置了相同的流量限制,
    curl
    下载文件是ok!!!
go proxy rate-limiting socks5
1个回答
0
投票

我检查了以下内容。我认为你的代码本身没有问题。所以我认为你的环境可能是可能的原因之一。

(1)

Copy
函数本身运行良好。我使用这段代码检查了它。 https://go.dev/play/p/5a-T4tIaEFC

(2) 使用您为 sock5 代理添加的代码,我检查它也运行良好。

© www.soinside.com 2019 - 2024. All rights reserved.