Page MenuHomePhabricator

tunnel.go
No OneTemporary

tunnel.go

package sshtunnel
import (
"net"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"fmt"
"io"
"os"
"log"
"sync"
"time"
)
type SSHtunnel struct {
Local []Endpoint
Server *Endpoint
Remote []Endpoint
ErrorChans []chan error
ServerClient *ssh.Client
Config *ssh.ClientConfig
ServerConnection *ssh.ServerConfig
ExecPath string
sync.Mutex
}
func(tunnel *SSHtunnel) Listen( localE Endpoint, remoteE Endpoint, errorChan chan error) {
log.Printf("LocalEndpoint: %v, RemoteEndpoint: %v", localE, remoteE)
listener, err := net.Listen("tcp", localE.String())
if err != nil {
return
}
for {
conn, err := listener.Accept()
if err != nil {
log.Println("Cannot listen.")
errorChan <- err
}
defer listener.Close()
log.Printf("Localhost listen %s, Remote Connection: %s \n", localE.String(), remoteE.String())
go tunnel.forward(conn, remoteE)
}
}
func (tunnel *SSHtunnel) Start() error {
var err error
tunnel.ErrorChans = make([]chan error, len(tunnel.Local))
//
tunnel.ServerClient, err = ssh.Dial("tcp", tunnel.Server.String(), tunnel.Config)
if err != nil {
fmt.Printf("Server dial error: %s\n", err)
//log.Println("Sever dial error occurred. No Internet connection. Program exited.")
// if err == "ssh: handshake failed: ssh: unable to authenticate, attempted methods [password none], no supported methods remain" {
// fmt.Println(" Incorrect Password entered.")
os.Exit(1)
return err
}
//
for i, _ := range tunnel.Local {
//defer listener.Close()
log.Printf("Main - LocalEndpoint: %v, RemoteEndpoint: %v", tunnel.Local[i], tunnel.Remote[i])
go tunnel.Listen(tunnel.Local[i], tunnel.Remote[i], tunnel.ErrorChans[i])
}
for {
for _, c := range tunnel.ErrorChans {
select {
case msg := <-c:
log.Printf("\n in tunnel.errorschans : %v", msg)
// case msg2:= <- done:
// log.Printf("%v", msg2)
// os.Exit(1)
default:
//fmt.Println("No message received")
}
}
time.Sleep(time.Second * 1)
//TODO run ExecPath
}
return err
}
//TODO refactor to accept remoteEndpoint
func (tunnel *SSHtunnel) forward(localConn net.Conn, remoteEndpoint Endpoint) {
var err error
log.Printf("Connect with client. %s \n", remoteEndpoint.String())
remoteConn, err := tunnel.ServerClient.Dial("tcp", remoteEndpoint.String())
if err != nil {
fmt.Printf("Remote dial error: %s\n", err)
log.Println("Remote dial error occurred. Trying to establish a new server connection.")
tunnel.ServerClient, err = ssh.Dial("tcp", tunnel.Server.String(), tunnel.Config)
return
}
log.Printf("Remote connection: %v", remoteConn)
copyConn:=func(writer, reader net.Conn) {
_, err:= io.Copy(writer, reader)
if err != nil {
log.Printf("%s io.Copy error: %s \n", remoteEndpoint.String(), err)
}
}
go copyConn(localConn, remoteConn)
go copyConn(remoteConn, localConn)
}
func SSHAgent() ssh.AuthMethod {
if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
}
return nil
}
func check(e error) {
if e != nil {
panic(e)
}
}

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 24, 2:54 PM (1 d, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15148
Default Alt Text
tunnel.go (3 KB)

Event Timeline