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

Feature request: ports & devices encoded in SSH username #119

Open
robbat2 opened this issue Mar 18, 2021 · 14 comments
Open

Feature request: ports & devices encoded in SSH username #119

robbat2 opened this issue Mar 18, 2021 · 14 comments
Assignees
Labels
enhancement New feature or request

Comments

@robbat2
Copy link

robbat2 commented Mar 18, 2021

OpenGear console servers have a nice feature that lets you encode where you want to connect as part of the SSH username,

<username>:<portXX> - numbered port
<username>:<port label> - labeled port
<username>:<ttySX> - explicit device
<username>:<serial> - jumps straight to the device menu

(if omitted, you get a normal SSH login to the embedded linux device).

This would be handy as it permits direct SSH access to specific devices, while keeping it secure and containing everything to a single port. It may require some magic in sshd to split out the user however.

I don't know if OpenGear ever published the patches they used to do that, but I suspect similar could be accomplished today with the AuthorizedKeysCommand

@Pack3tL0ss Pack3tL0ss added the enhancement New feature or request label Jul 2, 2021
@Pack3tL0ss
Copy link
Owner

I'm going to archive this for now, It takes care of itself at least in part with ser2net 4.x

I've tested ser2net 4 in the past, has to be built manually. They still have 3.x in the package repo. 4.x is re-architected and supports more connection methods including SSH, so you could map ssh on port 7001 to a particular adapter.

May experiment a bit, then revisit if there are some useful things along these lines in the future, but have some re-factoring and cleanup I need to get done.

You could launch directly to items and even bypass the menu entirely with something like
ssh -t BarnPi picocom /dev/barn-2930F-sw and make aliases for the stuff you want quick access to for now.

@Taralas
Copy link

Taralas commented Apr 25, 2022

Any chance you can give some additional examples, or point us to a how-to? From what I can see, ser2net 4 does support gtlssh, but that isn't quite the same. Ideally, the goal would be SSH to a either a known port, or a username:port combo, and have it connect directly to a serial port.

@Pack3tL0ss
Copy link
Owner

Well $h!t, I thought ser2net handled that, but your assessment is correct... gtlssh not the same, and looks to me to require a more cumbersome configuration than what it's worth.

The easiest way to ssh and connect directly is by sending the command/args as in
ssh -t BarnPi.consolepi.org picocom /dev/barn-4100 -b 115200 which could be aliased by placing a file with

alias your-alias-name 'ssh -t BarnPi.consolepi.org picocom /dev/barn-4100 -b 115200'
alias con-usb0 'ssh -t BarnPi.consolepi.org picocom /dev/ttyUSB0'
# and so on

and placing it in either /etc/bash_aliases.d (every user gets the alias) or place the alias in .bash_aliases in your home dir (you alone get the alias).

Then you could just type your-alias-name and it would ssh/connect directly to the serial port.

There is another option, but you would have to configure the ssh server to listen on some alternative ports, then you can automate the connection to a specific adapter based on the port... either with one of the rc files sshd reads or in .bashrc evaluating $SSH_CLIENT environment variable.

I'd have to think about how best to implement if I were to build something like that in. It sounds like you are connecting from a system that is not a ConsolePi and is not ConsolePi aware. The way I run it, may satisfy the desire, but I need to finish the tweaks to make a client-only ConsolePi install less of a custom thing (it's described on the GitHub, but it's a partially manual install). To describe that fully, I run ConsolePi in WSL (Ubuntu) on Windows, it has no local adapters, just adapters on any remotes (which it gets by using the Gdrive sync function, configured to pull-only, so wsl never adds itself just learns the remote ConsolePis). Then I can connect to any adapter on any ConsolePi in the environment via whatever the menu item# is.

@Pack3tL0ss
Copy link
Owner

Pack3tL0ss commented Apr 26, 2022

I did some testing and have one of my systems working ssh to port 22 get the linux shell, ssh to port 2202 directly connect to a specific device.

I would need to provide config options for it so I know what ports you want mapped to what device along with the connection settings if you wanted to override the default (9600 8N1 None).

On a system running bullseye

wade@ConsolePi4:~ $ cat /etc/ssh/sshd_config.d/consolepi.conf
Port 22
Port 2202
AddressFamily any
ListenAddress 0.0.0.0

Match LocalPort 2202
    ForceCommand /etc/ConsolePi/src/remote_launcher.py picocom /dev/sr-SDbranch-2930F-sw --baud 9600 --flow n --databits 8 --parity n --stopbits 1

/etc/ConsolePi/src/remote_launcher.py passes it through a script which handles any auto power-on linkages, and will give you the option to kill an existing session if there is already a hung process connected to the serial device. You could leave it off and launch picocom, but you would lose those capabilities.

Prior to bullseye sshd_config.d wasn't a thing, so the content of the file would just go in /etc/sshd_config.

It's certainly possible to build this into ConsolePi, but no estimate on timing at this point. For now you could try as highlighted above, (restart or restart sshd to take effect).

@Taralas
Copy link

Taralas commented Apr 26, 2022

That is exactly what I was looking for. Thank you.

If you are looking for ideas, take a look at https://support.get-console.com/support/solutions/articles/5000712932-using-the-ssh-to-serial-port-feature-of-airconsole. It's a commercial product that does this. Not a good fit for a lot of the functionality that ConsolePI offers, but not a bad place to start. I think they are dynamically adding ports to the sshd in a similar fashion.

@robbat2
Copy link
Author

robbat2 commented May 3, 2022

This might help, but needs something to extract the part after the : in the username, and then pass it onto where to connect, maybe a special launcher that does the extraction

Match User consolepi:%
  Username consolepi
  ForceCommand /etc/ConsolePi/src/remote_launcher.py picocom /dev/... 

@Pack3tL0ss
Copy link
Owner

I need to play with it some more I did get this to work:

Match User consolepi
  AcceptEnv *
  ForceCommand ( set -o posix ; set ) | grep -v _xspecs | grep -v LS_COLORS

That prints all defined variables and terminates which works,
I can connect using password auth using:

  • ssh consolepi:7001@barnpi
  • ssh consolepi:/dev/barn-gw@barnpi

If I'm using certificate auth the 2nd one (consolepi:/dev/barn-gw@barnpi) does not work. auth.log throws:

sshd[8766]: wrong user name passed to monitor: expected consolepi != consolepi:
sshd[11220]: fatal: mm_answer_keyverify: bad signature data blob

Looking at the environment variables available I don't see anything with the text after the : in the user.
Match User consolepi:% or Match User consolepi:* etc. don't match apparently sshd knows the user is the stuff before the : so the user = consolepi even if you connected using consolepi:stuff@host

Will play with it some more when I have time.
ssh user@host barn-gw may be a format we can work with.

Match User consolepi 
  ForceCommand /etc/ConsolePi/src/remote_launcher.py $SSH_ORIGINAL_COMMAND

I can verify barn-gw is not actually a valid executable, and that it is a valid serial device, then I can have remote-launcher grab all the connection details for barn-gw from the config (if they differ from a default of 9600 8N1 None)

Currently not sure how to process user:barn-gw@host but user@host barn-gw should be possible.

Re-opening in case someone else is familiar with ssh/sshd that can comment.

@Pack3tL0ss Pack3tL0ss reopened this May 4, 2022
@Pack3tL0ss Pack3tL0ss self-assigned this May 4, 2022
@robbat2
Copy link
Author

robbat2 commented May 4, 2022

Ok, research this I found a really weird old corner of OpenSSH:
https://openssh-unix-dev.mindrot.narkive.com/PHQlnJuM/user-style#post2

I think it could have future potential, but it's not going to be "easy". Most of the code is still there, but it doesn't seem to export the style data outside of sshd

@d3ra1l
Copy link

d3ra1l commented May 3, 2023

This project currently uses the username to map to a serial device.

https://github.com/mdlayher/consrv

@Pack3tL0ss
Copy link
Owner

This project currently uses the username to map to a serial device.

https://github.com/mdlayher/consrv

Thanks for the heads up. I'll test it out. Would be good to have it as a separate process from sshd. Looks like it may do the trick.

Pack3tL0ss pushed a commit that referenced this issue Jul 8, 2023
User would just `ssh -t <consolepi address> -p 2202 <device name>`
The `-t` is key or picocom launches without a tty and tab completion
and some other things break.

`<device name>` is the name of the adapter.  Which should be an alias like
`r1-6300M-sw` but could also be `ttyUSB0`

currently extract the baud and connection settings from ser2net config.
@Pack3tL0ss
Copy link
Owner

Pack3tL0ss commented Jul 8, 2023

https://github.com/mdlayher/consrv

I finally got a chance to play with this. It worked... kinda. It has a couple of issues, the main one being it will fail to start if any of configured adapters are not available when it starts. There is also an issue related, on how it doesn't handle devices that drop-off and come back while it's running. Add to that, it's a bit on the cumbersome/time-consuming side to install golang (can't use apt, have to grab the more current one manually), then build it....

So I took another look at just manually doing something more reliable/simple using sshd. Commit bc4193a is the result. This is on the dev branch currently until it's tested more, and the sshd_config bit is added to the installer/update script.

With a file /etc/ssh/sshd_config.d/consolepi.conf
Containing something like the following:

Port 22
Port 2202
AddressFamily any
ListenAddress 0.0.0.0

Match LocalPort 2202
    ForceCommand /etc/ConsolePi/src/remote_launcher.py $SSH_ORIGINAL_COMMAND

This would allow you to connect directly to a host using it's name (udev alias). You can use the default names i.e. ttyUSB0 but that's less ideal.

So ssh -t <consolepi-host> -p 2202 r1-6300M-sw Would ssh and connect you directly to /dev/r1-6300M-sw, which should be aliased (udev rule) via consolepi-addconsole or the rename option in the menu.

NOTE the -t bit is important or you won't have a tty, which breaks some stuff in the terminal (auto-complete, reliably disconnecting using picocom sequences, etc)
Also the baud rate for devices that have been aliased is extracted from the ser2net config. I'm in the process of updating all the logic to handle ser2netv3 or v4 (big change in the config format). If the v3 config /etc/ser2net.conf exists, it will continue to use it and consolepi-addconsole or the rn (rename) option in the menu should work. Just be aware if you only have the v4 config /etc/ser2net.yaml... I haven't updated the rename logic yet. It will extract the baud from the v4 config if it's there (manually), but the rename option I believe would still change or create the v3 file.

I could allow for a -b <baud> option, but currently it's pulling from the same info the menu uses (the ser2net config).

@Pack3tL0ss Pack3tL0ss mentioned this issue Jul 19, 2023
@durd
Copy link

durd commented Dec 15, 2023

@Pack3tL0ss
I was so worried ConsolePi wouldn't be able to do this! At first I thought ser2net could do it directly, but I couldn't find anything for ssh as an accepter, nor my 2nd requirement which is to bind to an IP address instead of port.
With nmcli (another story) I was finally able to add a bunch of secondary IPs to my pi's interface, and added a bunch of Match LocalAddress 192.168.1.10 to sshd_config.

Match LocalAddress 192.168.1.10
	ForceCommand /etc/ConsolePi/src/remote_launcher.py ttyUSB0
Match LocalAddress 192.168.1.11
	ForceCommand /etc/ConsolePi/src/remote_launcher.py ttyUSB1
Match LocalAddress 192.168.1.12
	ForceCommand /etc/ConsolePi/src/remote_launcher.py ttyUSB2
...
etc

Of course, I'll have to edit the file depending on what kind of serial adapter is connected, but this is awesome!

A feature to remote_launcher.py would be to be able to open the serial menu from where I am. I'd connect to 192.168.1.12 above, but being lazy I'd want to connect to a different interface, I might have forgotten which? Then I could access consolepi-menu from where I am and switch serial adapter.

@Pack3tL0ss
Copy link
Owner

@durd interesting alternative, hadn't considered that, but on systems with just a few connections makes sense.

A feature to remote_launcher.py would be to be able to open the serial menu from where I am. I'd connect to 192.168.1.12 above, but being lazy I'd want to connect to a different interface, I might have forgotten which? Then I could access consolepi-menu from where I am and switch serial adapter.

Have to think about that. I should be able to add a mini menu once you exit the terminal something like

m. launch consolepi-menu
x. exit

It would be the menu on the remote system. It would be setup to only do that when launched directly to a connection. I typically launch from my local menu to a remote. I already have all the remote connections in my locally launched menu, so it wouldn't make sense to launch on the remote (hopefully that all makes sense).

@durd
Copy link

durd commented Jan 18, 2024

@durd interesting alternative, hadn't considered that, but on systems with just a few connections makes sense.

I find it more useful with IP addresses than ports, I can have DNS-names for IPs, not ports! :)

Have to think about that. I should be able to add a mini menu once you exit the terminal something like

m. launch consolepi-menu
x. exit

It would be the menu on the remote system. It would be setup to only do that when launched directly to a connection. I typically launch from my local menu to a remote. I already have all the remote connections in my locally launched menu, so it wouldn't make sense to launch on the remote (hopefully that all makes sense).

I'd be happy with that, but of course only if you see it useful. It's not hard to ssh to ConsolePi's IP to open the menu.

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

No branches or pull requests

5 participants