Last active
January 31, 2016 14:13
-
-
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 :)
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 ( | |
"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