Skip to content

Instantly share code, notes, and snippets.

@DavyLandman
Last active January 31, 2016 14:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavyLandman/9351416 to your computer and use it in GitHub Desktop.
Save DavyLandman/9351416 to your computer and use it in GitHub Desktop.
The ssh-ssl-behind same port trick but now in go (previous version was in nodejs https://gist.github.com/DavyLandman/8314380 ) for more details on how it works, see the other issue. *why go?:* nodejs is not that nice for low-performance cpu's, and go nicely compiles to a native application :)
package main
import (
"net"
"log"
"time"
)
var noDeadline = time.Time{}
var (
externalHost = net.TCPAddr{net.IPv4(0,0,0,0), 8443,""}
sshTarget = net.TCPAddr{net.IPv4(127,0,0,1), 22,""}
sslTarget = net.TCPAddr{net.IPv4(127,0,0,1), 9443,""}
)
const (
RECV_BUF_LEN = 1024
RECV_BUF_LEN_LARGE = 1024*1024
)
func main() {
println("Starting the server")
listener, err := net.ListenTCP("tcp", &externalHost)
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Fatal(err)
}
go handleRequest(conn)
}
}
func handleRequest(conn *net.TCPConn) {
buf := make([]byte, 1)
// read for max 2 seconds
conn.SetReadDeadline(time.Now().Add(2 * time.Second))
n, err := conn.Read(buf)
timedOut := false
if err != nil {
if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
timedOut = true
} else {
defer conn.Close()
log.Println("Error reading first bytes:", err.Error())
return
}
}
if n != 1 {
log.Println("Unexpected amount of bytes read, assuming timeout alike scenario")
timedOut = true
}
conn.SetReadDeadline(noDeadline)
target := &sshTarget
if !timedOut && (buf[0] == 22 || buf[0] == 128) {
target = &sslTarget
}
connTarget, err := net.DialTCP("tcp4", nil, target)
if err != nil {
defer conn.Close()
log.Println("Error connecting to server:", err.Error(), target)
return
}
if !timedOut {
_, err = connTarget.Write(buf)
if err != nil {
defer connTarget.Close()
defer conn.Close()
log.Println("Error writing to newly created connection:", err.Error(), target)
return
}
}
pipeStreams(conn, connTarget)
}
func pipeStreams(from, to *net.TCPConn) {
go keepCopying(from, to)
go keepCopying(to, from)
}
func keepCopying(from, to *net.TCPConn) {
fullRounds := 0
currentSize := RECV_BUF_LEN
b := make([]byte, currentSize)
for {
n, err := from.Read(b)
if err != nil {
from.Close()
to.Close()
break
}
if n == 0 {
continue;
} else if n == currentSize {
to.Write(b)
fullRounds++;
} else {
b2 := make([]byte, n)
copy(b2, b)
to.Write(b2)
}
if (fullRounds == 10 && currentSize == RECV_BUF_LEN) {
currentSize = RECV_BUF_LEN_LARGE
b = make([]byte, currentSize)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment