mirror of
https://github.com/moul/sshportal.git
synced 2025-01-06 15:38:14 +08:00
58 lines
1.2 KiB
Go
58 lines
1.2 KiB
Go
package ssh
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
|
|
gossh "golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
// direct-tcpip data struct as specified in RFC4254, Section 7.2
|
|
type forwardData struct {
|
|
DestinationHost string
|
|
DestinationPort uint32
|
|
|
|
OriginatorHost string
|
|
OriginatorPort uint32
|
|
}
|
|
|
|
func directTcpipHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx *sshContext) {
|
|
d := forwardData{}
|
|
if err := gossh.Unmarshal(newChan.ExtraData(), &d); err != nil {
|
|
newChan.Reject(gossh.ConnectionFailed, "error parsing forward data: "+err.Error())
|
|
return
|
|
}
|
|
|
|
if srv.LocalPortForwardingCallback == nil || !srv.LocalPortForwardingCallback(ctx, d.DestinationHost, d.DestinationPort) {
|
|
newChan.Reject(gossh.Prohibited, "port forwarding is disabled")
|
|
return
|
|
}
|
|
|
|
dest := fmt.Sprintf("%s:%d", d.DestinationHost, d.DestinationPort)
|
|
|
|
var dialer net.Dialer
|
|
dconn, err := dialer.DialContext(ctx, "tcp", dest)
|
|
if err != nil {
|
|
newChan.Reject(gossh.ConnectionFailed, err.Error())
|
|
return
|
|
}
|
|
|
|
ch, reqs, err := newChan.Accept()
|
|
if err != nil {
|
|
dconn.Close()
|
|
return
|
|
}
|
|
go gossh.DiscardRequests(reqs)
|
|
|
|
go func() {
|
|
defer ch.Close()
|
|
defer dconn.Close()
|
|
io.Copy(ch, dconn)
|
|
}()
|
|
go func() {
|
|
defer ch.Close()
|
|
defer dconn.Close()
|
|
io.Copy(dconn, ch)
|
|
}()
|
|
}
|