Skip to content

Instantly share code, notes, and snippets.

@jes
Last active Mar 20, 2018
Embed
What would you like to do?
Run SSH and HTTP on the same port
package main
import (
"fmt"
"net"
"os"
"strings"
)
func main() {
l, err := net.Listen("tcp", "0.0.0.0:80")
if err != nil {
fmt.Println("listen: ", err.Error())
os.Exit(1)
}
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("accept: ", err.Error())
os.Exit(1)
}
go protoproxy(conn)
}
}
func protoproxy(conn net.Conn) {
buf := make([]byte, 1024)
readlen, err := conn.Read(buf)
if err != nil {
fmt.Println("read: ", err.Error())
conn.Close()
return
}
// XXX: if first read returns fewer than 3 bytes, this might proxy to HTTP server
// instead of SSH server even when it should have gone to SSH. Never mind.
if (strings.HasPrefix(string(buf), "SSH")) {
run_proxy(conn, "localhost:2001", buf[:readlen])
} else {
run_proxy(conn, "localhost:2002", buf[:readlen])
}
}
func run_proxy(conn net.Conn, remote string, initial_send []byte) {
remoteConn, err := net.Dial("tcp", remote)
if err != nil {
fmt.Println("dial ", remote, ": ", err.Error())
conn.Close()
return
}
_, err = remoteConn.Write(initial_send)
if err != nil {
fmt.Println("write: ", err.Error())
conn.Close()
remoteConn.Close()
return
}
go oneway_proxy(conn, remoteConn)
go oneway_proxy(remoteConn, conn)
}
func oneway_proxy(read net.Conn, write net.Conn) {
defer read.Close()
defer write.Close()
buf := make([]byte, 1024)
for {
readlen, err := read.Read(buf)
if err != nil {
fmt.Println("read: ", err.Error())
return
}
_, err = write.Write(buf[:readlen])
if err != nil {
fmt.Println("write: ", err.Error())
return
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment