Last active
January 22, 2024 05:49
-
-
Save rberrelleza/3ac2ad6d59629c9d1d984c9c7c3eb5f7 to your computer and use it in GitHub Desktop.
sample SSH forward
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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