Untitled


SUBMITTED BY: Guest

DATE: June 27, 2024, 4:21 p.m.

FORMAT: Text only

SIZE: 3.4 kB

HITS: 266

  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "fmt"
  6. "log"
  7. "net"
  8. "sync"
  9. "time"
  10. "golang.org/x/crypto/ssh"
  11. "github.com/armon/go-socks5"
  12. "ssh-client/tunnel"
  13. )
  14. var (
  15. sshClient *ssh.Client
  16. clientMux sync.Mutex
  17. )
  18. func main() {
  19. // Define command-line flags
  20. server := flag.String("server", " ", "SSH server address")
  21. port := flag.String("port", " ", "SSH server port")
  22. user := flag.String("user", " ", "SSH username")
  23. pass := flag.String("pass", " ", "SSH password")
  24. listen := flag.String("listen", "localhost:1080", "Local address to listen on")
  25. proxyHost := flag.String("proxyHost", " ", "HTTP proxy host")
  26. proxyPort := flag.Int("proxyPort", , "HTTP proxy port")
  27. // Parse command-line flags
  28. flag.Parse()
  29. sshConfig := &ssh.ClientConfig{
  30. User: *user,
  31. Auth: []ssh.AuthMethod{
  32. ssh.Password(*pass),
  33. },
  34. HostKeyCallback: ssh.InsecureIgnoreHostKey(),
  35. }
  36. sshHost := fmt.Sprintf("%s:%s", *server, *port)
  37. var err error
  38. // Create HTTP proxy
  39. httpProxy, err := tunnel.NewHttpProxy(*proxyHost, *proxyPort)
  40. if err != nil {
  41. log.Fatalf("Failed to create HTTP proxy: %s", err)
  42. }
  43. // Initial SSH connection
  44. sshClient, err = connectToSSH(sshHost, sshConfig, httpProxy)
  45. if err != nil {
  46. log.Fatalf("Failed to establish initial SSH connection: %s", err)
  47. }
  48. defer httpProxy.Close()
  49. listener, err := net.Listen("tcp", *listen)
  50. if err != nil {
  51. log.Fatalf("Failed to listen on %s: %s", *listen, err)
  52. }
  53. defer listener.Close()
  54. log.Printf("SOCKS5 proxy listening on %s", *listen)
  55. socksConf := &socks5.Config{
  56. Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
  57. return dialThroughSSH(ctx, network, addr, sshHost, sshConfig, httpProxy)
  58. },
  59. }
  60. socksServer, err := socks5.New(socksConf)
  61. if err != nil {
  62. log.Fatalf("Failed to create SOCKS5 server: %s", err)
  63. }
  64. for {
  65. conn, err := listener.Accept()
  66. if err != nil {
  67. log.Printf("Failed to accept connection: %s", err)
  68. continue
  69. }
  70. go func() {
  71. defer conn.Close()
  72. if err := socksServer.ServeConn(conn); err != nil {
  73. log.Printf("Failed to serve connection: %s", err)
  74. }
  75. }()
  76. }
  77. }
  78. func connectToSSH(sshHost string, sshConfig *ssh.ClientConfig, proxy *tunnel.HttpProxy) (*ssh.Client, error) {
  79. for {
  80. proxyConn, err := proxy.OpenConnection(sshHost, 0, 10000, 10000)
  81. if err != nil {
  82. log.Printf("Failed to connect to SSH server via proxy: %s. Retrying...", err)
  83. time.Sleep(2 * time.Second)
  84. continue
  85. }
  86. clientConn, chans, reqs, err := ssh.NewClientConn(proxyConn, sshHost, sshConfig)
  87. if err == nil {
  88. log.Printf("Successfully connected to SSH server at %s via proxy", sshHost)
  89. return ssh.NewClient(clientConn, chans, reqs), nil
  90. }
  91. log.Printf("Failed to dial SSH: %s. Retrying...", err)
  92. proxyConn.Close()
  93. //time.Sleep(2 * time.Second)
  94. }
  95. }
  96. func dialThroughSSH(ctx context.Context, network, addr, sshHost string, sshConfig *ssh.ClientConfig, proxy *tunnel.HttpProxy) (net.Conn, error) {
  97. clientMux.Lock()
  98. defer clientMux.Unlock()
  99. conn, err := sshClient.Dial(network, addr)
  100. if err == nil {
  101. return conn, nil
  102. }
  103. // Reconnect if the connection is lost
  104. log.Printf("SSH connection lost: %s. Reconnecting...", err)
  105. sshClient, err = connectToSSH(sshHost, sshConfig, proxy)
  106. if err != nil {
  107. return nil, err
  108. }
  109. return sshClient.Dial(network, addr)
  110. }

comments powered by Disqus