Skip to content

Instantly share code, notes, and snippets.

@corvofeng
Created May 26, 2022 12:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corvofeng/30fde73d64fbda13fde48a01163d57cf to your computer and use it in GitHub Desktop.
Save corvofeng/30fde73d64fbda13fde48a01163d57cf to your computer and use it in GitHub Desktop.
SSH tunnel to forward http port
package main
// Forward from local port 8001 to remote port 9999, by ssh tunnel
import (
"fmt"
"io"
"log"
"net"
"net/http"
"golang.org/x/crypto/ssh"
)
var (
username = "corvo"
serverAddrString = "127.0.0.1:2222"
remoteAddrString = "localhost:9999"
)
type indexHandler struct {
content string
config *ssh.ClientConfig
}
func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
sshClientConn, err := ssh.Dial("tcp", serverAddrString, ih.config)
if err != nil {
log.Fatalf("ssh.Dial failed: %s", err)
}
sshConn, err := sshClientConn.Dial("tcp", remoteAddrString)
if err != nil {
log.Fatalf("ssh.Dial failed: %s", err)
}
client, _, err := w.(http.Hijacker).Hijack()
if err != nil {
log.Fatalf("hjacker failed: %s", err)
}
// copy http header to the socket, bootstrap.
data := req.Clone(req.Context())
data.Write(sshConn)
go func() {
io.Copy(client, sshConn)
client.Close()
sshConn.Close()
}()
go func() {
io.Copy(sshConn, client)
client.Close()
sshConn.Close()
}()
}
func main() {
// Setup SSH config (type *ssh.ClientConfig)
config := &ssh.ClientConfig{
User: username,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
// Auth: []ssh.AuthMethod{
// ssh.Password(password),
// },
}
http.Handle("/", &indexHandler{content: "hello world!", config: config})
fmt.Println("Listen to http://127.0.0.1:8001")
http.ListenAndServe("0.0.0.0:8001", nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment