Skip to content

Instantly share code, notes, and snippets.

@rberrelleza
Last active January 22, 2024 05:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rberrelleza/3ac2ad6d59629c9d1d984c9c7c3eb5f7 to your computer and use it in GitHub Desktop.
Save rberrelleza/3ac2ad6d59629c9d1d984c9c7c3eb5f7 to your computer and use it in GitHub Desktop.
sample SSH forward
module forward
go 1.14
require (
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
github.com/gliderlabs/ssh v0.3.0
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71
)
package main
import (
"fmt"
"io"
"log"
"net"
"net/http"
gSSH "github.com/gliderlabs/ssh"
"golang.org/x/crypto/ssh"
)
func checkErr(err error) {
if err != nil {
panic(err)
}
}
func sshListenAndServe(port int) {
forwardHandler := &gSSH.ForwardedTCPHandler{}
server := &gSSH.Server{
Addr: fmt.Sprintf(":%d", port),
ChannelHandlers: map[string]gSSH.ChannelHandler{
"direct-tcpip": gSSH.DirectTCPIPHandler,
"session": gSSH.DefaultSessionHandler,
},
LocalPortForwardingCallback: gSSH.LocalPortForwardingCallback(func(ctx gSSH.Context, dhost string, dport uint32) bool {
return true
}),
ReversePortForwardingCallback: gSSH.ReversePortForwardingCallback(func(ctx gSSH.Context, host string, port uint32) bool {
return true
}),
RequestHandlers: map[string]gSSH.RequestHandler{
"tcpip-forward": forwardHandler.HandleSSHRequest,
"cancel-tcpip-forward": forwardHandler.HandleSSHRequest,
},
}
if err := server.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
func httpListenAndServe(port int) {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Server listening on %d", port)
})
http.ListenAndServe(fmt.Sprintf(":8080"), nil)
}
func handleForward(local net.Conn, sshPort, forwardToPort int) {
defer local.Close()
config := &ssh.ClientConfig{
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
conn, err := net.Dial("tcp", fmt.Sprintf(":%d", sshPort))
checkErr(err)
clientConn, chans, reqs, err := ssh.NewClientConn(conn, fmt.Sprintf(":%d", sshPort), config)
checkErr(err)
client := ssh.NewClient(clientConn, chans, reqs)
remote, err := client.Dial("tcp", fmt.Sprintf(":%d", forwardToPort))
checkErr(err)
defer remote.Close()
quit := make(chan struct{}, 1)
go transfer(remote, local, quit)
go transfer(local, remote, quit)
<-quit
}
func transfer(from io.Writer, to io.Reader, quit chan struct{}) {
_, err := io.Copy(from, to)
if err != nil {
fmt.Printf("data transfer failed: %v", err)
}
quit <- struct{}{}
}
func main() {
sshPort := 2222
forwardToPort := 8080
listenOnPort := 8090
go sshListenAndServe(sshPort)
fmt.Printf("Started SSH server in port %d\n", sshPort)
go httpListenAndServe(forwardToPort)
fmt.Printf("Started HTTP server in port %d\n", forwardToPort)
localListener, err := net.Listen("tcp", ":8090")
checkErr(err)
defer localListener.Close()
fmt.Printf("Waiting for HTTP request on port %d\n", listenOnPort)
for {
localConn, err := localListener.Accept()
checkErr(err)
go handleForward(localConn, sshPort, forwardToPort)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment