2024-11-17 18:10:35 +00:00
|
|
|
package sshproxy
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type proxyConnection struct {
|
|
|
|
internalPort int
|
|
|
|
externalPort int
|
|
|
|
listener net.Listener
|
2024-11-17 18:30:07 +00:00
|
|
|
|
|
|
|
// closedChan is used to notify that the proxy connection is closed
|
|
|
|
closedChan chan<- *proxyConnection
|
2024-11-17 18:10:35 +00:00
|
|
|
}
|
|
|
|
|
2024-11-17 18:30:07 +00:00
|
|
|
func newProxyConnection(toPort int, closedChan chan *proxyConnection) (*proxyConnection, error) {
|
2024-11-17 18:10:35 +00:00
|
|
|
l, err := net.Listen("tcp", ":0")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
externalPort := l.Addr().(*net.TCPAddr).Port
|
|
|
|
|
|
|
|
return &proxyConnection{
|
|
|
|
internalPort: toPort,
|
|
|
|
externalPort: externalPort,
|
|
|
|
listener: l,
|
2024-11-17 18:30:07 +00:00
|
|
|
closedChan: closedChan,
|
2024-11-17 18:10:35 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *proxyConnection) start() {
|
|
|
|
for {
|
|
|
|
conn, err := c.listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("error accepting connection at %v: %v\n", c.listener.Addr(), err)
|
|
|
|
}
|
|
|
|
go c.forwardConnectionToSSH(conn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *proxyConnection) forwardConnectionToSSH(conn net.Conn) {
|
|
|
|
containerConn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", c.internalPort))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("error connecting to container ssh at port %d\n", c.internalPort)
|
|
|
|
return
|
|
|
|
}
|
2024-11-17 18:30:07 +00:00
|
|
|
defer func() {
|
|
|
|
c.closedChan <- c
|
|
|
|
}()
|
2024-11-17 18:10:35 +00:00
|
|
|
defer containerConn.Close()
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
defer wg.Wait()
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
defer conn.Close()
|
|
|
|
for {
|
|
|
|
_, err := io.Copy(conn, containerConn)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("read remote conn err", err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
defer conn.Close()
|
|
|
|
for {
|
|
|
|
_, err := io.Copy(containerConn, conn)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("write remote conn err", err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|