在GO中实现ssh代理,使用错误的数据包长度输出错误,以下是调试模式下的ssh错误:

debug1: SSH2_MSG_KEXINIT sent
Bad packet length 1231976033.
ssh_dispatch_run_fatal: Connection to ::1 port 8080: message authentication code incorrect

代码:

func handleSSH(conn net.Conn, r *bufio.Reader, protocol string) {

    target, err := url.Parse("ssh://localhost:3333")
    if err != nil {
        fmt.Println("Error parsing target", err)
        conn.Close()
        return
    }

    targetConn, err := net.Dial("tcp", target.Host)
    if err != nil {
        fmt.Println("error dialing SSH target:", err)
        conn.Close()
        return
    }

    defer targetConn.Close()

    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        _, err := io.Copy(targetConn, conn)
        if err != nil {
            fmt.Println("error copying data to target:", err)
        }
        wg.Done()
    }()

    go func() {
        _, err := io.Copy(conn, targetConn)
        if err != nil {
            fmt.Println("error copying data from target:", err)
        }
        wg.Done()
    }()

    wg.Wait()
    conn.Close()
}

// EDIT

func connection(conn net.Conn) {

    r := bufio.NewReader(conn)
    protocol, err := r.ReadString('\n')
    if err != nil {
        fmt.Println("Error reading first line", err)
        conn.Close()
        return
    }

if protocol[0:3] == "SSH" {
        handleSSH(conn, r, protocol)
    }
}

func main() {
   ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }
    defer ln.Close()

    for {
        conn, err := ln.Accept()
        if err != nil {
            panic(err)
        }
        go connection(conn)
    }
}

编辑:添加了有关如何启动连接和重现错误的相关信息的代码.

我最好的猜测是SSH谈判进程被打断,事情变得不同步.

推荐答案

代码从客户端读取第一行并判断协议类型,以便调用适当的处理程序:

protocol, err := r.ReadString('\n')
...
if protocol[0:3] == "SSH" {
        handleSSH(conn, r, protocol)
    }
}

但是代码无法将已经读取的字节转发到连接的服务器.这些字节以protocol为单位,分配给handleSSH.但是一旦建立了连接,它就无法将这些字节发送到所连接的服务器.相反,它只在客户端和服务器之间复制新数据.

这意味着服务器不会从客户端获得第一行.因此,它可能会抱怨类似于Invalid SSH identification string.的协议错误,该错误会被转发到客户端,并被误解为来自SSH连接的有效数据.

Go相关问答推荐

Go Fiber和HTMX—HX—Trigger header被更改为HX—Trigger,这不是HTMX监听的内容

租户GUID X的租户不存在self 邮箱帐户的租户(我是唯一的成员)

Hugo错误:没有为此项目配置现有内容目录

在整个SQL事务中将使用上下文作为默认设置吗?

调用库和直接操作效率有区别吗?

无法读取postman 中的表单数据

nixOS 上的 Nginx 反向代理在try 加载 css/js 时返回 404

无效操作:v > max(类型参数 T 与 > 不可比较)

优化方式中所有可能组合的字符串相似度

是否需要手动调用rand.Seed?

如何在 Go 中将 int 转换为包含 complex128 的泛型类型?

使用 httptest 对 http 请求进行单元测试重试

当填充通道的函数调用未嵌入 goroutine 时,为什么我会遇到死锁?

在 Gorm 的 AfterFind() 钩子中获取智能 Select struct 的值

未定义 protoc protoc-gen-go 时间戳

我如何解码 aes-256-cfb

GRPC 反向代理混淆 GRPC 和 GRPC-Web

每 N 秒运行一次函数,上下文超时

golang jwt.MapClaims 获取用户ID

使用 xml.Name 将 xml 解组为 [] struct