Skip to content

Commit

Permalink
feature: Internal key usage on ssh tunnels
Browse files Browse the repository at this point in the history
  • Loading branch information
dogukanoksuz committed Dec 18, 2023
1 parent ef0af81 commit 2e8d01c
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 9 deletions.
17 changes: 15 additions & 2 deletions app/handlers/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// OpenTunnel opens ssh tunnel on unix sockets or ports
func OpenTunnel(c *fiber.Ctx) error {
params := []string{"remote_host", "remote_port", "username", "password"}
params := []string{"remote_host", "remote_port"}

for _, param := range params {
if len(c.FormValue(param)) < 1 {
Expand All @@ -21,13 +21,26 @@ func OpenTunnel(c *fiber.Ctx) error {
sshPort = "22"
}

port := bridge.CreateTunnel(
if len(c.FormValue("username")) < 1 {
port, err := bridge.CreateTunnelInternalKey(c)
if err != nil {
return logger.FiberError(fiber.StatusInternalServerError, err.Error())
}

return c.JSON(port)
}

port, err := bridge.CreateTunnel(
c.FormValue("remote_host"),
c.FormValue("remote_port"),
c.FormValue("username"),
c.FormValue("password"),
sshPort,
"ssh",
)
if err != nil {
return logger.FiberError(fiber.StatusInternalServerError, err.Error())
}

return c.JSON(port)
}
Expand Down
57 changes: 50 additions & 7 deletions internal/bridge/ssh_tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bridge

import (
"context"
"errors"
"fmt"
"io"
"net"
Expand All @@ -11,6 +12,9 @@ import (
"time"

"github.com/avast/retry-go"
"github.com/gofiber/fiber/v2"
"github.com/limanmys/render-engine/app/models"
"github.com/limanmys/render-engine/internal/liman"
"github.com/limanmys/render-engine/pkg/logger"
"github.com/phayes/freeport"
"golang.org/x/crypto/ssh"
Expand Down Expand Up @@ -301,8 +305,30 @@ func (t *Tunnel) String() string {
return fmt.Sprintf("%s@%s | %s %s %s", t.user, t.hostAddr, left, mode, right)
}

func CreateTunnelInternalKey(c *fiber.Ctx) (int, error) {
credentials, err := liman.GetCredentials(&models.User{
ID: c.Locals("user_id").(string),
}, &models.Server{
ID: c.FormValue("server_id"),
})
if err != nil {
return 0, err
}

port, err := CreateTunnel(
c.FormValue("remote_host"),
c.FormValue("remote_port"),
credentials.Username,
credentials.Key,
credentials.Port,
credentials.Type,
)

return port, err
}

// CreateTunnel starts a new tunnel instance and sets it into TunnelPool
func CreateTunnel(remoteHost, remotePort, username, password, sshPort string) int {
func CreateTunnel(remoteHost, remotePort, username, password, sshPort, connType string) (int, error) {
// Creating a tunnel cannot exceed 25 seconds
ch := make(chan int)
time.AfterFunc(25*time.Second, func() {
Expand All @@ -315,7 +341,7 @@ func CreateTunnel(remoteHost, remotePort, username, password, sshPort string) in
// Check if existing tunnel started, if not wait until starts (max: 25sec)
if err == nil {
if t.password != password {
return 0
return 0, errors.New("password mismatch")
}

startedLoop:
Expand All @@ -336,14 +362,14 @@ func CreateTunnel(remoteHost, remotePort, username, password, sshPort string) in
}

t.LastConnection = time.Now()
return t.Port
return t.Port, nil
}

// This part from now creates a new tunnel
port, err := freeport.GetFreePort()
if err != nil {
logger.Sugar().Errorw(err.Error())
return 0
return 0, errors.New("couldnt find a free port")
}

dial := net.JoinHostPort("127.0.0.1", remotePort)
Expand All @@ -355,8 +381,8 @@ func CreateTunnel(remoteHost, remotePort, username, password, sshPort string) in
}

ctx, cancel := context.WithCancel(context.Background())

sshTunnel := &Tunnel{
auth: []ssh.AuthMethod{ssh.RetryableAuthMethod(ssh.Password(password), 3)},
hostKeys: ssh.InsecureIgnoreHostKey(),
user: username,
mode: '>',
Expand All @@ -376,6 +402,23 @@ func CreateTunnel(remoteHost, remotePort, username, password, sshPort string) in
cancel: cancel,
}

if connType == "ssh" {
sshTunnel.auth = []ssh.AuthMethod{
ssh.RetryableAuthMethod(ssh.Password(password), 3),
}
}

if connType == "ssh_certificate" {
key, err := ssh.ParsePrivateKey([]byte(password))
if err != nil {
return 0, errors.New("an error occured while parsing ssh key")
}

sshTunnel.auth = []ssh.AuthMethod{
ssh.RetryableAuthMethod(ssh.PublicKeys(key), 3),
}
}

Tunnels.Set(remoteHost, remotePort, username, sshTunnel)
go sshTunnel.Start()

Expand All @@ -398,8 +441,8 @@ loop:

if !sshTunnel.Started {
cancel()
return 0
return 0, errors.New("cannot start tunnel")
}

return sshTunnel.Port
return sshTunnel.Port, nil
}

0 comments on commit 2e8d01c

Please sign in to comment.