Created
May 24, 2020 05:08
-
-
Save 0187773933/b791af9d527989cbc6fdc69f574de872 to your computer and use it in GitHub Desktop.
Our WIP Golang Port Forwarding Agent
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 | |
// 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