Automate TOTP-secured SSH logins with 2sh and Bitwarden
As an additional way to protect SSH servers from potential attackers, I started to implement TOTP-based 2FA logins in the past. See this post about how I achieved this.
I also use Bitwarden to store all my credentials and also TOTP tokens and since I was tired of always manually typing in my current token upon a SSH login, I wrote 2sh to automate this for me.
How does 2sh work
It's pretty darn simple, actually. But let me reiterate how the SSH login with TOTP tokens work.
You first connect to SSH like normal with your password or your SSH key. After that, the SSH server will ask for a "Verification code" where you have to enter the currently valid TOTP token from Bitwarden.
This is where I open Bitwarden, search for the server I want to connect and copy & paste the current token into the session and press enter. I'm now logged in. If you were fast enough.
Imagine you have to do this multiple times a day. Doesn't sound that nice, does it?
This is where 2sh comes into play.
2sh uses sshpass to actually recognize the challenge-response string after the SSH login and passes the actual token as the response and presses "enter" for me. So, sshpass waits for the "Verification code" string to appear and then reads the response from the password file which is itself a subshell that calls Bitwarden which prints the wanted token out of it's database.
The actual code that does all the magic is this
~$ sshpass -P "Verification code" -p $(bw get totp "$1 SSH") ssh ${@:1}
How to use 2sh
You simply use it like the ssh command before.
2sh [email protected] -p22
2sh will run ssh itself and the arguments you passed behind 2sh, so we're using no new methods to connect. This is what the ${@:1} does. It takes all parameters except the first and puts them behind the ssh command.
Sshpass itself will then use this pre-build ssh command to connect to the server, wait for the expected string (-P "Verification code") and print the actual token it gets from the Bitwarden CLI tool bw.
As you can see 2sh also expects the TOTP token to be available as the actual connect string plus the "SSH" suffix. Check the Github's README.md for further details here.
For easier setup and use, I also added a simple command that guides you through initial setup. This is
~$ 2sh setup
Limitations
This is the very first version of 2sh, so it probably has a lot of limitations. Currently i only use it for simple SSH connects. It will not work with commands like scp or sftp and it may also fail when concatinating with other commands. I haven't tested other scenarios yet.
Feel free to try 2sh out and help contributing to make it better. It also currently only supports Bitwarden, but someone may want to have support for other password managers. The source is licensed under the MIT license, so feel free to contribute.
Conclusion
2sh may not be the nicest tool you have ever seen. But it solves a problem for me. I hope it also helps you, making your life easier as well.
I will enhance 2sh from time to time to cover more scenarios for me as well. Any help is appreciated.