1
0

sshprox.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package sshprox
  2. import (
  3. "errors"
  4. "net/http"
  5. "net/url"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "runtime"
  10. "strconv"
  11. "imuslab.com/zoraxy/mod/reverseproxy"
  12. "imuslab.com/zoraxy/mod/utils"
  13. )
  14. /*
  15. SSH Proxy
  16. This is a tool to bind gotty into Zoraxy
  17. so that you can do something similar to
  18. online ssh terminal
  19. */
  20. type Manager struct {
  21. StartingPort int
  22. ReservedPorts map[string]int
  23. Instances []*Instance
  24. }
  25. type Instance struct {
  26. ExecPath string
  27. conn *reverseproxy.ReverseProxy //HTTP proxy
  28. tty *exec.Cmd //SSH connection ported to web interface
  29. }
  30. func NewSSHProxyManager() *Manager {
  31. return &Manager{
  32. StartingPort: 14810,
  33. ReservedPorts: map[string]int{},
  34. Instances: []*Instance{},
  35. }
  36. }
  37. //Get the next free port in the list
  38. func (m *Manager) GetNextPort() int {
  39. nextPort := m.StartingPort
  40. for {
  41. if _, exists := m.ReservedPorts[strconv.Itoa(nextPort)]; !exists {
  42. if !isPortInUse(nextPort) {
  43. return nextPort
  44. }
  45. }
  46. if nextPort == 65534 {
  47. return -1
  48. }
  49. nextPort++
  50. }
  51. }
  52. func (m *Manager) NewSSHProxy(binaryRoot string) (*Instance, error) {
  53. //Check if the binary exists in system/gotty/
  54. binary := "gotty_" + runtime.GOOS + "_" + runtime.GOARCH
  55. if runtime.GOOS == "windows" {
  56. binary = binary + ".exe"
  57. }
  58. execPath := filepath.Join(binaryRoot, binary)
  59. if !utils.FileExists(execPath) {
  60. //Binary not found
  61. return nil, errors.New("binary not found at " + execPath)
  62. }
  63. //Convert the binary path to realpath
  64. realpath, err := filepath.Abs(execPath)
  65. if err != nil {
  66. return nil, err
  67. }
  68. return &Instance{
  69. ExecPath: realpath,
  70. }, nil
  71. }
  72. //Create a new Connection to target address
  73. func (i *Instance) CreateNewConnection(listenPort int, remoteIpAddr string, remotePort int) error {
  74. //Create a gotty instance
  75. cmd := exec.Command(i.ExecPath, "-w", "-p", strconv.Itoa(listenPort), "-a", "127.0.0.1", "--once", "ssh", remoteIpAddr, "-p", strconv.Itoa(remotePort))
  76. cmd.Stdout = os.Stdout
  77. cmd.Stderr = os.Stderr
  78. go func() {
  79. cmd.Run()
  80. }()
  81. i.tty = cmd
  82. //Create a new proxy agent for this root
  83. path, err := url.Parse("http://127.0.0.1:" + strconv.Itoa(listenPort))
  84. if err != nil {
  85. return err
  86. }
  87. //Create a new proxy object to the proxy
  88. proxy := reverseproxy.NewReverseProxy(path)
  89. i.conn = proxy
  90. return nil
  91. }
  92. //Bridge the remote connection to reverse proxy
  93. func (i *Instance) BridgeConnection(w http.ResponseWriter, r *http.Request) error {
  94. return i.conn.ProxyHTTP(w, r)
  95. }