SSH代理,坏的数据包长度

huangapple go评论135阅读模式
英文:

SSH proxy, bad packet length

问题

在Go语言中实现SSH代理时,出现了"bad packet length"错误。以下是在调试模式下SSH出现的错误信息:

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

代码部分:

  1. func handleSSH(conn net.Conn, r *bufio.Reader, protocol string) {
  2. target, err := url.Parse("ssh://localhost:3333")
  3. if err != nil {
  4. fmt.Println("Error parsing target", err)
  5. conn.Close()
  6. return
  7. }
  8. targetConn, err := net.Dial("tcp", target.Host)
  9. if err != nil {
  10. fmt.Println("error dialing SSH target:", err)
  11. conn.Close()
  12. return
  13. }
  14. defer targetConn.Close()
  15. var wg sync.WaitGroup
  16. wg.Add(2)
  17. go func() {
  18. _, err := io.Copy(targetConn, conn)
  19. if err != nil {
  20. fmt.Println("error copying data to target:", err)
  21. }
  22. wg.Done()
  23. }()
  24. go func() {
  25. _, err := io.Copy(conn, targetConn)
  26. if err != nil {
  27. fmt.Println("error copying data from target:", err)
  28. }
  29. wg.Done()
  30. }()
  31. wg.Wait()
  32. conn.Close()
  33. }
  34. // EDIT
  35. func connection(conn net.Conn) {
  36. r := bufio.NewReader(conn)
  37. protocol, err := r.ReadString('\n')
  38. if err != nil {
  39. fmt.Println("Error reading first line", err)
  40. conn.Close()
  41. return
  42. }
  43. if protocol[0:3] == "SSH" {
  44. handleSSH(conn, r, protocol)
  45. }
  46. }
  47. func main() {
  48. ln, err := net.Listen("tcp", ":8080")
  49. if err != nil {
  50. panic(err)
  51. }
  52. defer ln.Close()
  53. for {
  54. conn, err := ln.Accept()
  55. if err != nil {
  56. panic(err)
  57. }
  58. go connection(conn)
  59. }
  60. }

编辑:添加了相关信息的代码,以展示连接是如何初始化并重现错误。

我最好的猜测是SSH协商过程被中断,导致同步出现问题。

英文:

Implementing an ssh proxy in Go, errors out with bad packet length, these are the errors with ssh in debug mode:

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

Code:

  1. func handleSSH(conn net.Conn, r *bufio.Reader, protocol string) {
  2. target, err := url.Parse("ssh://localhost:3333")
  3. if err != nil {
  4. fmt.Println("Error parsing target", err)
  5. conn.Close()
  6. return
  7. }
  8. targetConn, err := net.Dial("tcp", target.Host)
  9. if err != nil {
  10. fmt.Println("error dialing SSH target:", err)
  11. conn.Close()
  12. return
  13. }
  14. defer targetConn.Close()
  15. var wg sync.WaitGroup
  16. wg.Add(2)
  17. go func() {
  18. _, err := io.Copy(targetConn, conn)
  19. if err != nil {
  20. fmt.Println("error copying data to target:", err)
  21. }
  22. wg.Done()
  23. }()
  24. go func() {
  25. _, err := io.Copy(conn, targetConn)
  26. if err != nil {
  27. fmt.Println("error copying data from target:", err)
  28. }
  29. wg.Done()
  30. }()
  31. wg.Wait()
  32. conn.Close()
  33. }
  34. // EDIT
  35. func connection(conn net.Conn) {
  36. r := bufio.NewReader(conn)
  37. protocol, err := r.ReadString('\n')
  38. if err != nil {
  39. fmt.Println("Error reading first line", err)
  40. conn.Close()
  41. return
  42. }
  43. if protocol[0:3] == "SSH" {
  44. handleSSH(conn, r, protocol)
  45. }
  46. }
  47. func main() {
  48. ln, err := net.Listen("tcp", ":8080")
  49. if err != nil {
  50. panic(err)
  51. }
  52. defer ln.Close()
  53. for {
  54. conn, err := ln.Accept()
  55. if err != nil {
  56. panic(err)
  57. }
  58. go connection(conn)
  59. }
  60. }

EDIT: added code for relevant information on how the connection is initiated and reproduce the error.

My best guess is the ssh negotiation process is being interrupted, and things goes out of sync.

答案1

得分: 1

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

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

但是,代码未能将已读取的字节转发到连接的服务器。这些字节位于protocol中,并且被传递给handleSSH。但是,一旦建立连接,它未能将这些字节发送到连接的服务器。相反,它只是在客户端和服务器之间复制新数据。

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

英文:

The code is reading the first line from the client and checks the kind of protocol in order to call the appropriate handler:

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

But the code fails to forward the already read bytes to the connected server. These bytes are in protocol and are given to handleSSH. But it fails to send these bytes to the connected server once the connection is established. Instead it only copies new data between client and server.

This means the server does not get the first line from the client. It therefore likely complains about a protocol error with something like Invalid SSH identification string. which gets forwarded to the client and misinterpreted as valid data from an SSH connection.

huangapple
  • 本文由 发表于 2023年1月3日 08:04:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/74988064.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定