Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some questions #20

Open
Forum1877621 opened this issue Nov 10, 2022 · 11 comments
Open

some questions #20

Forum1877621 opened this issue Nov 10, 2022 · 11 comments

Comments

@Forum1877621
Copy link

Hi, I was testing rospo and had some questions:

  • Are keys that are password protected not supported? I get an error "unable to authenticate" when trying to use a password protected key.
  • Is there a way to provide the server password as a command line arg?
  • How do you launch the UI?
@Forum1877621
Copy link
Author

also, is it possible to save logs to a text file, to see if anyone is attacking the server?

@ferama
Copy link
Owner

ferama commented Nov 10, 2022

Password protected keys are not supported at the moment.
Some features are available using config file only.
For example to enable the webui you should use somthing like:

sshclient:
  server: 192.168.5.56
  identity: "~/.ssh/id_rsa"

web:
  listen_address: "127.0.0.1:8090"

@Forum1877621
Copy link
Author

Password protected keys are not supported at the moment.

are you planning to add support in a future update?

Also, is it possible to save logs to a text file?

@ferama
Copy link
Owner

ferama commented Nov 11, 2022

I'm not planning to support protected keys at the moment, but it should not be too difficult to add it. Would you like to contribute?

Regarding logs, for my use cases I usually simply redirect console output to a log file, so no you cannot configure rospo to write to a log file directly.

@Forum1877621
Copy link
Author

I'm not planning to support protected keys at the moment, but it should not be too difficult to add it. Would you like to contribute?

I can try to take a look if you can give advice on what files need to be edited

@ferama
Copy link
Owner

ferama commented Nov 12, 2022

Look at the sshc package here https://github.com/ferama/rospo/tree/main/pkg/sshc
The identity is loaded and the ssh connection is instantiated. You should start from there

@Forum1877621
Copy link
Author

I switched to using Python sshtunnel which supports key pw, will close this.
One question about the included server though, is there way to change the packet size to 256 KiB? I guess right now it's 32 KiB?

@Forum1877621
Copy link
Author

I tried sshtunnel but the performance is too bad, so I went back to this program.

@ferama I have never used golang before did some research and got it working. The file that was changed was keys.go. Here are the changes, can you incorporate this feature in the next release?

Add this to the imports

"syscall"
"golang.org/x/crypto/ssh/terminal"

Change LoadIdentityFile and add the helper function

func isKeyEncryptedWithPassphrase(keyPath string) (bool, error) {
	// Read the private key file
	keyData, err := ioutil.ReadFile(keyPath)
	if err != nil {
		return false, err
	}

	// Parse the private key
	_, err = ssh.ParsePrivateKey(keyData)
	if err != nil {
		// If the key is encrypted with a passphrase, ssh.ParsePrivateKey will return an
		// error indicating that the key is encrypted. In this case, we can conclude that
		// the key has a passphrase.
		log.Printf("key at %s is encrypted", keyPath)
		return true, nil
	}

	log.Printf("key at %s is not encrypted", keyPath)

	// If the key was successfully parsed, it means that the key does not have a passphrase
	return false, nil
}

// LoadIdentityFile reads a public key file and loads the keys to
// an ssh.PublicKeys object
func LoadIdentityFile(file string) (ssh.AuthMethod, error) {
	path, _ := ExpandUserHome(file)

	usr, _ := user.Current()
	// no path is set, try with a reasonable default
	if path == "" {
		path = filepath.Join(usr.HomeDir, ".ssh", "id_rsa")
	}

	isKeyEncrypted, err := isKeyEncryptedWithPassphrase(file)
	if err != nil {
		return nil, err
	}

	if isKeyEncrypted {
		fmt.Print("Enter passphrase for SSH key: \n")
		password, err := terminal.ReadPassword(int(syscall.Stdin))
		fmt.Print("\n")

		if err != nil {
			return nil, err
		}
		buffer, err := ioutil.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("cannot read SSH identity key file %s", path)
		}

		key, err := ssh.ParsePrivateKeyWithPassphrase(buffer, password)
		if err != nil {
			return nil, fmt.Errorf("cannot parse SSH identity key file %s", file)
		}
		return ssh.PublicKeys(key), nil
	} else {
		buffer, err := ioutil.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("cannot read SSH identity key file %s", path)
		}

		key, err := ssh.ParsePrivateKey(buffer)
		if err != nil {
			return nil, fmt.Errorf("cannot parse SSH identity key file %s", file)
		}
		return ssh.PublicKeys(key), nil
	}
}

@Forum1877621
Copy link
Author

Here's some changes that allows for key passphrase caching

Uses a new file cache.go

package cache

var CachedKeyPw []byte

LoadIdentityFile

func LoadIdentityFile(file string) (ssh.AuthMethod, error) {
	path, _ := ExpandUserHome(file)

	usr, _ := user.Current()
	// no path is set, try with a reasonable default
	if path == "" {
		path = filepath.Join(usr.HomeDir, ".ssh", "id_rsa")
	}

	isKeyEncrypted, err := isKeyEncryptedWithPassphrase(file)
	if err != nil {
		return nil, err
	}

	if isKeyEncrypted {
		password := []byte(cache.CachedKeyPw)

		if string(cache.CachedKeyPw) == "" {
			fmt.Println("Enter passphrase for SSH key")
			password, err = terminal.ReadPassword(int(syscall.Stdin))
			if err != nil {
				return nil, err
			}

			for {
				fmt.Println("Cache the key password? (y/n) (insecure, stored as an array of bytes in RAM)")
				cacheInput, err := terminal.ReadPassword(int(syscall.Stdin))
				if err != nil {
					return nil, err
				}

				if string(cacheInput) == "y" {
					cache.CachedKeyPw = password
					break
				} else if string(cacheInput) == "n" {
					cache.CachedKeyPw = []byte("")
					break
				}

				fmt.Println("invalid option (pick y/n)")
			}
		}

		buffer, err := ioutil.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("cannot read SSH identity key file %s", path)
		}

		key, err := ssh.ParsePrivateKeyWithPassphrase(buffer, password)
		if err != nil {
			return nil, fmt.Errorf("cannot parse SSH identity key file %s", file)
		}

		return ssh.PublicKeys(key), nil
	} else {
		buffer, err := ioutil.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("cannot read SSH identity key file %s", path)
		}

		key, err := ssh.ParsePrivateKey(buffer)
		if err != nil {
			return nil, fmt.Errorf("cannot parse SSH identity key file %s", file)
		}
		return ssh.PublicKeys(key), nil
	}
}

@ferama
Copy link
Owner

ferama commented Jan 2, 2023

Thanks for your work. I can evaluate your edits and include them in next release. You should make a proper pull request with your commits to the rospo main branch.

@lars18th
Copy link
Contributor

Hi @ferama ,

You will add the suggested patches provided by @Forum1877621 ? They aren't in the current repo.

In addition, I suggest to add a simple XOR to the cached password (using a typdef master key). And instead of caching only the password key, you can cache the certificate too. Then you can remove the certificate from the disk after starting the tool and it will work with all in ram.

I hope it helps.
Regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants