Add SSH server user config type flag

pull/113/head
Miguel Mota 3 years ago
parent d21315314a
commit 65626536e3
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9

@ -4,6 +4,7 @@ package cmd
import (
"fmt"
"strings"
"time"
cssh "github.com/miguelmota/cointop/pkg/ssh"
@ -19,6 +20,7 @@ func ServerCmd() *cobra.Command {
var maxSessions uint = 0
var executableBinary string = "cointop"
var hostKeyFile string = cssh.DefaultHostKeyFile
var userConfigType string = cssh.UserConfigTypePublicKey
serverCmd := &cobra.Command{
Use: "server",
@ -33,6 +35,7 @@ func ServerCmd() *cobra.Command {
MaxSessions: maxSessions,
ExecutableBinary: executableBinary,
HostKeyFile: hostKeyFile,
UserConfigType: userConfigType,
})
fmt.Printf("Running SSH server on port %v\n", port)
@ -47,6 +50,7 @@ func ServerCmd() *cobra.Command {
serverCmd.Flags().UintVarP(&maxSessions, "max-sessions", "", maxSessions, "Max number of sessions allowed. Default is 0 for unlimited.")
serverCmd.Flags().StringVarP(&executableBinary, "binary", "b", executableBinary, "Executable binary path")
serverCmd.Flags().StringVarP(&hostKeyFile, "host-key-file", "k", hostKeyFile, "Host key file")
serverCmd.Flags().StringVarP(&userConfigType, "user-config-type", "", userConfigType, fmt.Sprintf("User config type. Options are: %s", strings.Join(cssh.UserConfigTypes, ",")))
return serverCmd
}

@ -400,6 +400,20 @@ draft: false
The public SSH instance is for demo use or short-term usage and will disconnect users after an idle timeout to allow other users to try it out.
## How do I fix the error `SSH key is required to start server` when trying to run SSH server?
Generate the SSH key if the host machine doesn't have one:
```bash
$ ssh-keygen
```
Make sure the host key flag points to the location of the SSH key:
```bash
cointop server -k ~/.ssh/id_rsa [...]
```
## Why doesn't the version number work when I install with `go get`?
The version number is read from the git tag during the build process but this requires the `GO111MODULE` environment variable to be set in order for Go to read the build information:

@ -189,6 +189,12 @@ cointop is available on [Docker Hub](https://hub.docker.com/r/cointop/cointop).
docker run -it cointop/cointop
```
Note: the config is under `/root/.config/cointop` in container, so attach a volume to make it persistent in host:
```bash
docker run -v ~/.cache/cointop:/root/.config/cointop -it cointop/cointop
```
## Binaries
You can find pre-built binaries on the [releases](https://github.com/miguelmota/cointop/releases) page.

@ -5,32 +5,69 @@ draft: false
---
# SSH Server
The SSH server requires that the host has SSH keys, so generate SSH keys if not already:
```bash
$ ssh-keygen
```
Check keys were generated:
```bash
$ ls ~/.ssh
id_rsa id_rsa.pub
```
Run SSH server:
```bash
cointop server -p 2222
```
If the host SSH keys live elsewhere, specify the location:
```bash
cointop server -p 2222 -k ~/.ssh/some-dir/id_rsa
```
SSH into server to see cointop:
```bash
ssh localhost -p 2222
```
SSH demo:
The cointop SSH server will use the client's public SSH key as the identifier for persistent config by default. You may change it to use the username instead:
```bash
ssh cointop.sh
cointop server -p 2222 --user-config-type=username
```
Passing arguments to SSH server:
SSH'ing into server with same username will use the same respective config now:
```bash
ssh cointop.sh -t cointop --colorscheme synthwave
ssh alice@localhost -p 2222
```
Using docker to run SSH server:
Pass arguments to cointop on SSH server by using SSH `-t` flag followed by cointop command and arguments. For example:
```bash
ssh localhost -p 2222 -t cointop --colorscheme synthwave
```
## Using docker to run SSH server:
```bash
docker run -p 2222:22 -v ~/.ssh:/keys --entrypoint cointop -it cointop/cointop server -k /keys/id_rsa
```
cointop server writes the client config to `/tmp/cointop_config` within the container, so to make it persistent in host attach a volume. The following example will to write the cached config to `~/.cache/cointop` on the host:
```bash
docker run -p 2222:22 -v ~/.ssh:/keys -v ~/.cache/cointop:/tmp/cointop_config --entrypoint cointop -it cointop/cointop server -k /keys/id_rsa
```
## SSH demo
```bash
ssh cointop.sh
```

@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"strings"
"syscall"
"time"
"unsafe"
@ -24,6 +25,17 @@ import (
// DefaultHostKeyFile is default SSH key path
var DefaultHostKeyFile = "~/.ssh/id_rsa"
// UserConfigTypePublicKey is constant
var UserConfigTypePublicKey = "public-key"
// UserConfigTypeUsername is constant
var UserConfigTypeUsername = "username"
// UserConfigTypeNone is constant
var UserConfigTypeNone = "none"
var UserConfigTypes = []string{UserConfigTypePublicKey, UserConfigTypeUsername, UserConfigTypeNone}
// Config is config struct
type Config struct {
Port uint
@ -33,6 +45,7 @@ type Config struct {
ExecutableBinary string
HostKeyFile string
MaxSessions uint
UserConfigType string
}
// Server is server struct
@ -46,6 +59,7 @@ type Server struct {
hostKeyFile string
maxSessions uint
sessionCount uint
userConfigType string
}
// NewServer returns a new server instance
@ -54,7 +68,11 @@ func NewServer(config *Config) *Server {
if config.HostKeyFile != "" {
hostKeyFile = config.HostKeyFile
}
userConfigType := config.UserConfigType
if userConfigType == "" {
userConfigType = UserConfigTypePublicKey
}
validateUserConfigType(userConfigType)
hostKeyFile = pathutil.NormalizePath(hostKeyFile)
return &Server{
port: config.Port,
@ -64,6 +82,7 @@ func NewServer(config *Config) *Server {
executableBinary: config.ExecutableBinary,
hostKeyFile: hostKeyFile,
maxSessions: config.MaxSessions,
userConfigType: userConfigType,
}
}
@ -95,18 +114,32 @@ func (s *Server) ListenAndServe() error {
}
configDir := ""
pubKey := sshSession.PublicKey()
if pubKey != nil {
pubBytes := pubKey.Marshal()
if len(pubBytes) > 0 {
hash := sha256.Sum256(pubBytes)
configDir = fmt.Sprintf("/tmp/cointop_config/%x", hash)
err := os.MkdirAll(configDir, 0700)
if err != nil {
fmt.Println(err)
return
configDirKey := ""
switch s.userConfigType {
case UserConfigTypePublicKey:
pubKey := sshSession.PublicKey()
if pubKey != nil {
pubBytes := pubKey.Marshal()
if len(pubBytes) > 0 {
hash := sha256.Sum256(pubBytes)
configDirKey = fmt.Sprintf("%x", hash)
}
}
case UserConfigTypeUsername:
user := sshSession.User()
if user != "" {
configDirKey = user
}
}
if configDirKey != "" {
configDir = fmt.Sprintf("/tmp/cointop_config/%s", configDirKey)
err := os.MkdirAll(configDir, 0700)
if err != nil {
fmt.Println(err)
return
}
}
if configDir == "" {
@ -209,3 +242,12 @@ func setWinsize(f *os.File, w, h int) {
func createTempDir() (string, error) {
return ioutil.TempDir("", "")
}
func validateUserConfigType(userConfigType string) {
for _, validType := range UserConfigTypes {
if validType == userConfigType {
return
}
}
panic(fmt.Errorf("invalid user config type. Acceptable values are: %s", strings.Join(UserConfigTypes, ",")))
}

Loading…
Cancel
Save