Compare commits

...

7 Commits

Author SHA1 Message Date
Thorsten Sommer
56f0a8dd64 Merge branch 'master' of github.com:SommerEngineering/SSHTunnel 2016-03-16 08:08:08 +01:00
Thorsten Sommer
c85e21231b Version 1.3.0
In case the password must provided interactively, it is now invisible.
2016-03-16 08:05:56 +01:00
Thorsten Sommer
6146f74c72 Update README.md 2015-09-28 16:07:29 +02:00
Thorsten Sommer
c2a03bfdcf Update README.md 2015-09-28 16:07:00 +02:00
Thorsten Sommer
a16b99af6e Version 1.2.0 2015-09-28 15:28:11 +02:00
Thorsten Sommer
aab3524082 Version 1.1.0 2015-09-23 20:30:51 +02:00
Thorsten Sommer
15803714a8 Update README.md 2015-09-23 20:30:31 +02:00
13 changed files with 315 additions and 278 deletions

34
Main.go
View File

@ -1,31 +1,57 @@
package main
import (
"fmt"
"github.com/SommerEngineering/SSHTunnel/Tunnel"
"github.com/howeyc/gopass"
"golang.org/x/crypto/ssh"
"log"
"os"
"runtime"
)
func main() {
// Show the current version:
log.Println(`SSHTunnel v1.3.0`)
// Allow Go to use all CPUs:
runtime.GOMAXPROCS(runtime.NumCPU())
// Read the configuration from the command-line args:
readFlags()
// Check if the password was provided:
for true {
if password == `` {
// Promt for the password:
fmt.Println(`Please provide the password for the connection:`)
if pass, errPass := gopass.GetPasswd(); errPass != nil {
log.Println(`There was an error reading the password securely: ` + errPass.Error())
os.Exit(1)
return
} else {
password = string(pass)
}
} else {
break
}
}
// Create the SSH configuration:
Tunnel.SetPassword4Callback(password)
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(password),
ssh.PasswordCallback(passwordCallback),
ssh.KeyboardInteractive(keyboardInteractiveChallenge),
ssh.PasswordCallback(Tunnel.PasswordCallback),
ssh.KeyboardInteractive(Tunnel.KeyboardInteractiveChallenge),
},
}
// Create the local end-point:
localListener := createLocalEndPoint()
localListener := Tunnel.CreateLocalEndPoint(localAddrString)
// Accept client connections (will block forever):
acceptClients(localListener, config)
Tunnel.AcceptClients(localListener, config, serverAddrString, remoteAddrString)
}

View File

@ -1,6 +0,0 @@
package main
// Just a callback function for the password request.
func passwordCallback() (string, error) {
return password, nil
}

View File

@ -1,6 +1,6 @@
SSHTunnel
=========
SSHTunnel is a tiny small program to tunnel something through a SSH without any external dependencies. Yes, you do not need any PuTTY installtion for Microsoft Windows. Just download the executable which matches your OS and architecture (32 vs. 64 bits) and run it.
SSHTunnel is a tiny small program to tunnel something through a SSH without any external dependencies. Just download the executable which matches your OS and architecture (32 vs. 64 bits) and run it.
### Syntax
*This example uses the Microsoft Windows executable, but the syntax is the same for e.g. Linux, Unix, Mac, etc.*
@ -10,19 +10,21 @@ SSHTunnel is a tiny small program to tunnel something through a SSH without any
- At the SSH server's side, connects to `127.0.0.1` to port `27017` (a MongoDB database)
- At your local side, provides a listener at `127.0.0.1` at the port `53001`
- The username for the SSH service is `john`
- The user's password would be `johndow` ;-)
- The user's password would be `johndow` ;-) You can avoid the `-pwd` argument. Thus, the SSHTunnel will ask for the password.
- Now, you are able to use your local MongoDB software and can connect to port `53001` at `localhost`.
### Features
- The whole code is open source and can be used for any purpose (also commercial)
- If you want, you can compile the code by your own by using the Go compiler (http://www.golang.org)
- If you want, you can compile the code by your own by using the [Go](http://www.golang.org)
- The program just needs very low resources e.g. around 1.3 MB memory for Microsoft Windows 8.1
- SSHTunnel is scalable and, if necessary, can utilise all your CPUs
- If a connection cannot setup, the program re-tries it
- At the moment, SSHTunnel uses only the password authentication methods. Therefore, it is currently not possible to use e.g. a certificate, etc. Nevertheless, the implementation of this feature is possible.
- The configuration must be provided by using the command-line arguments. It is currently not possible to use e.g. a configuration file.
- You can avoid the password argument if you prefer to provide the password on demand.
- [Ocean Remote Connections](https://github.com/SommerEngineering/OceanRemoteConnections) is a simple GUI for SSH Tunnel, PuTTY, RDP and WinSCP.
### Download
Go and get the latest release from GitHub's release page: https://github.com/SommerEngineering/SSHTunnel/releases
Go and get the latest release from the [release page](https://github.com/SommerEngineering/SSHTunnel/releases).
*Based on damick's example code from http://stackoverflow.com/questions/21417223/simple-ssh-port-forward-in-golang*

View File

@ -8,7 +8,7 @@ func readFlags() {
flag.StringVar(&serverAddrString, `server`, `127.0.0.1:22`, `The (remote) SSH server, e.g. 'my.host.com', 'my.host.com:22', '127.0.0.1:22', 'localhost:22'.`)
flag.StringVar(&localAddrString, `local`, `127.0.0.1:50000`, `The local end-point of the tunnel, e.g. '127.0.0.1:50000', 'localhost:50000'.`)
flag.StringVar(&remoteAddrString, `remote`, `127.0.0.1:27017`, `The remote side end-point (e.g. on the machine with the SSH server), e.g. a MongoDB (port 27017) '127.0.0.1:27017', a web server '127.0.0.1:80'`)
flag.StringVar(&username, `user`, `username`, `The user's name for the SSD server.`)
flag.StringVar(&password, `pwd`, `password`, `The user's password for the SSD server.`)
flag.StringVar(&username, `user`, `username`, `The user's name for the SSH server.`)
flag.StringVar(&password, `pwd`, ``, `The user's password for the SSH server.`)
flag.Parse()
}

View File

@ -1,4 +1,4 @@
package main
package Tunnel
import (
"golang.org/x/crypto/ssh"
@ -6,7 +6,7 @@ import (
"net"
)
func acceptClients(connection net.Listener, config *ssh.ClientConfig) {
func AcceptClients(connection net.Listener, config *ssh.ClientConfig, serverAddrString, remoteAddrString string) {
// Endless loop
for {
@ -22,7 +22,7 @@ func acceptClients(connection net.Listener, config *ssh.ClientConfig) {
log.Println(`Client accepted.`)
// Start the forwarding:
go forward(localConn, config)
go forward(localConn, config, serverAddrString, remoteAddrString)
}
}
}

View File

@ -1,4 +1,4 @@
package main
package Tunnel
const (
maxRetriesLocal = 16 // How many retries are allowed to create the local end-point?

View File

@ -1,4 +1,4 @@
package main
package Tunnel
import (
"log"
@ -6,7 +6,7 @@ import (
"time"
)
func createLocalEndPoint() (localListener net.Listener) {
func CreateLocalEndPoint(localAddrString string) (localListener net.Listener) {
// Loop for the necessary retries
for {

View File

@ -1,4 +1,4 @@
package main
package Tunnel
import (
"golang.org/x/crypto/ssh"
@ -7,7 +7,7 @@ import (
"time"
)
func forward(localConn net.Conn, config *ssh.ClientConfig) {
func forward(localConn net.Conn, config *ssh.ClientConfig, serverAddrString, remoteAddrString string) {
defer localConn.Close()
currentRetriesServer := 0
@ -17,7 +17,7 @@ func forward(localConn net.Conn, config *ssh.ClientConfig) {
// Loop for retries:
for {
// Try to connect to the SSD server:
// Try to connect to the SSH server:
if sshClientConn, err := ssh.Dial(`tcp`, serverAddrString, config); err != nil {
// Failed:

View File

@ -1,11 +1,11 @@
package main
package Tunnel
import (
"log"
)
// Another auth. method.
func keyboardInteractiveChallenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
func KeyboardInteractiveChallenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
// Log all the provided data:
log.Println(`User: ` + user)
@ -22,7 +22,7 @@ func keyboardInteractiveChallenge(user, instruction string, questions []string,
// We expect that in this case (only one question is asked), that the server want to know the password ;-)
answers = make([]string, countQuestions, countQuestions)
answers[0] = password
answers[0] = callbackPassword
} else if countQuestions > 1 {

View File

@ -0,0 +1,10 @@
package Tunnel
// Just a callback function for the password request.
func PasswordCallback() (string, error) {
return callbackPassword, nil
}
func SetPassword4Callback(password string) {
callbackPassword = password
}

View File

@ -1,4 +1,4 @@
package main
package Tunnel
import (
"io"

6
Tunnel/Variables.go Normal file
View File

@ -0,0 +1,6 @@
package Tunnel
var (
currentRetriesLocal = 0 // Check how many retries are occur for creating the local end-point
callbackPassword = ``
)

View File

@ -1,10 +1,9 @@
package main
var (
username = `` // The SSH user's name
password = `` // The user's password
serverAddrString = `` // The SSH server address
localAddrString = `` // The local end-point
remoteAddrString = `` // The remote end-point (on the SSH server's side)
currentRetriesLocal = 0 // Check how many retries are occur for creating the local end-point
username = `` // The SSH user's name
password = `` // The user's password
serverAddrString = `` // The SSH server address
localAddrString = `` // The local end-point
remoteAddrString = `` // The remote end-point (on the SSH server's side)
)