ConsolePi
ConsolePi copied to clipboard
Feature request: ports & devices encoded in SSH username
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
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.
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.
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.
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).
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.
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/...
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.
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
This project currently uses the username to map to a serial device.
https://github.com/mdlayher/consrv
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.
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
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.
@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 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.