Skip to content

Instantly share code, notes, and snippets.

@0187773933
Created May 24, 2020 05:08
Show Gist options
  • Save 0187773933/b791af9d527989cbc6fdc69f574de872 to your computer and use it in GitHub Desktop.
Save 0187773933/b791af9d527989cbc6fdc69f574de872 to your computer and use it in GitHub Desktop.
Our WIP Golang Port Forwarding Agent
package main
// https://github.com/longXboy/gotunnel
import (
"fmt"
"io"
"log"
"net"
"os"
"time"
"golang.org/x/crypto/ssh"
)
// TODO - 1
// Somehow figure out how to add Remote Port Forwarding || aka remote vps --> localhost
// All we have so far is Local Port Forwarding || aka localhost --> remote vps
// https://github.com/davrodpin/mole/blob/master/tunnel/tunnel.go
// TODO - 2
// Add daemon / service functionality
// https://github.com/takama/daemon
// https://github.com/sevlyar/go-daemon
var version = "unversioned"
// var SSH_KEY_FILE_DATA = []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
// -----END OPENSSH PRIVATE KEY-----`)
func main() {
var REMOTE_SSH_USER = "gotunnel"
var REMOTE_SSH_HOST = "11.22.33.44:22"
var SSH_KEY_FILE_PASSWORD = ""
const total_bindings = 2
var port_bindings [total_bindings][2] string
port_bindings[0][0] = "127.0.0.1:22" // Local
port_bindings[0][1] = "0.0.0.0:3003" // Remote
port_bindings[1][0] = "127.0.0.1:6379" // Local
port_bindings[1][1] = "0.0.0.0:3004" // Remote
log.SetOutput( os.Stdout )
// 1.) Build Auth Agent and Config
var auths []ssh.AuthMethod
if SSH_KEY_FILE_PASSWORD != "" {
auths = append( auths , ssh.Password( SSH_KEY_FILE_PASSWORD ) )
}
signer, err := ssh.ParsePrivateKey( SSH_KEY_FILE_DATA )
if err != nil {
log.Fatalf( "unable to parse private key: %v" , err )
}
auths = append( auths , ssh.PublicKeys( signer ) )
config := &ssh.ClientConfig{
User: REMOTE_SSH_USER ,
Auth: auths ,
HostKeyCallback: func( hostname string , remote net.Addr , key ssh.PublicKey ) error {
return nil
} ,
Timeout: 6 * time.Second ,
}
// 2.) Dial SSH Connection to Remote Host
connection , err := ssh.Dial( "tcp" , REMOTE_SSH_HOST , config )
if err != nil {
log.Fatalf( "unable to connect to [%s]: %v" , REMOTE_SSH_HOST , err )
}
defer connection.Close()
// 3.) Start Listener on Remote End
for index := range port_bindings {
go ListenRemote( connection , port_bindings[ index ][ 0 ] , port_bindings[ index ][ 1 ] )
}
// 5.) Keep Go Program Running for Infinity
ticker := time.NewTicker( 15 * time.Minute )
for now := range ticker.C {
fmt.Println( now , "still here" )
}
log.Println( "shutting down" )
}
func ListenRemote( client *ssh.Client , local_bind_address string , remote_bind_address string ) {
log.Printf( "listening for remote tcp connections on [%s]\n" , remote_bind_address )
listener , err := client.Listen( "tcp" , remote_bind_address )
if err != nil {
log.Fatal( "unable to register tcp forward: " , err )
}
defer listener.Close()
for {
connection , err := listener.Accept()
if err != nil {
log.Fatal( "accept remote failed!err:=%v" , err )
return
}
// 4.) Forward Local Port to Remote Listener
go ServeTCP( connection , local_bind_address )
}
}
func ServeTCP( connection net.Conn , local_bind_address string ) {
defer connection.Close()
local_connection , err := net.Dial( "tcp" , local_bind_address )
if err != nil {
log.Printf( "dial local addr %v failed!err:=%v" , local_bind_address , err )
return
}
defer local_connection.Close()
channel := make( chan struct{} , 0 )
go func() {
io.Copy( connection , local_connection )
close( channel )
}()
io.Copy(local_connection, connection )
<-channel
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment