The fact that you are on this page reading this text is evidence in itself that you most likely do not need any introduction on this topic. Nevertheless, for completeness' sake, here is some background info.
Bruce Leidl (@brl) gave a detailed description of the reasons behind his proposal to obfuscate the handshake process of ssh connection. Go over it if you have the time. It's not long and fairly easy to understand.
In short, ssh connection starts with a handshake between client and server, which is performed in clear text. The purpose of obfuscating openssh handshake is to make it more difficult for traffic analysis tools to identify this process. Consequently, blocking, interfering or eavesdropping application(s) or mechanism(s) that target ssh traffic by relying on such identification will not be triggered. More difficult, but not impossible, especially if obfuscation is performed without using a keyword (see configuration and securing below). In addition, there definitely exist other methods of identifying ssh traffic, so handshake obfuscation may not solve all your problems.
Leidl's patches did not make into upstream. Fortunately, popular demand made sure that the patches live on outside upstream. In fact, the usefulness of handshake obfuscation have become so recognized that various non-openssh ssh client/server implementations have adopted this feature (see below).
Over the years, a couple of guys have also attempted to port Leidl's patches to newer openssh versions with varying degrees of success. This project is based on Bruce Leidl's original patches against openssh-5.2p1 as well as arigo's patches against openssh-6.1p1, and intends to provide workable patches against all recent and upcoming openssh releases.
Download from openssh.com a recent version (e.g. openssh-7.1p1.tar.gz) and extract the sources:
tar xvf openssh-7.1p1.tar.gz
You can download the patches as a zip archive and extract the matching patch (e.g. 7.0_7.1.diff for 7.0p1 and 7.1p1), or download only the matching patch from the github repo using copy and paste, or clone the git repo to your local machine. For upstream versions from openssh.com, use patches in the
Assuming that you have placed the patch file in the parent folder of extracted openssh sources, apply the patch:
cd openssh-7.1p1 patch -p1 < ../7.0_7.1.diff
There should not be any error at this stage. If there is, check whether you have applied the patch that matches the openssh version.
OpenSSH has building dependencies that might vary between distros and versions. The easiest way to satisfy these dependencies is to build a distro version of OpenSSH first. In Debian/Ubuntu, this can be simplified by using a single line of command:
apt-get build-dep ssh
For testing purpose, configure and build using the following commands from within the openssh source folder:
./configure --prefix=/usr/local --sysconfdir=/etc/obssh make && make install
If these is no building error, the executable binaries will be installed under /usr/local, while the config file will be installed to /etc/obssh, and new server and client keys will be generated. This allows you to test the obfuscated openssh installation while using your distro's normal openssh version.
When you have finished testing and made sure that the obfuscated openssh works as expected, you can choose to install it to the usual locations:
make uninstall ./configure --prefix=/usr --sysconfdir=/etc/ssh make && make install
Edit /etc/obssh/sshd_config, make sure these options are uncommented and specified with desired values:
Port 22 ObfuscatedPort 222 ObfuscateKeyword key
Remember to set different ports for obfuscated and non-obfuscated connections. It is strongly advised to use keyword for obfuscation, but please do change the default 'key' to something else!
Then start the server in debug mode:
/usr/loca/sbin/sshd -D -ddd
First, test on the machine obfuscated openssh is built and installed:
/usr/local/bin/ssh -z -Z yourkey -p 222 -v localhost
This is assuming you have configured the server to listen on localhost interface or all available interfaces in /etc/obssh/sshd_config. Remember to change the parameter of '-Z' option to the keyword specified in sshd_config. If all goes well, a connection should be established and you will be prompted to enter password for the connecting user. On both the server and client side, you should see debug messages telling you that obfuscation is enabled before handshake, and disabled after handshake.
Once local testing passes, you can try connecting from another machine using an obfuscation-aware client. On Linux and MacOS, download and build a patched openssh as detailed above. On Windows, you can use the latest version of the free (as in beer) Bitvise ssh client. Patched versions of the open source PuTTY client named PoTTY are also available.
Other clients in OpenSSH like sftp and scp, as well as non-OpenSSH clients that establish ssh connection using ssh, sftp or scp from locally installed OpenSSH package (e.g. sshuttle), are also obfuscation-aware if OpenSSH is built using these patches. Use or pass the proper -z and -Z commandline options to enable obfuscated handshake.
On Linux, you can set default obfuscation options in ~/.ssh/config to avoid having to remember settings for each server like this:
Host obssh1 HostName 184.108.40.206 Port 2234 ObfuscateHandshake yes ObfuscateKeyword mykey
Then you can just input 'ssh obssh1' to connect to 220.127.116.11:2234 using obfuscation keyword 'mykey', equivalent to 'ssh -z -Z mykey -p 2234 18.104.22.168'.
A properly configured (e.g. MaxStartups value in sshd_config) ssh server and a tool like fail2ban can protect you from most attacks through ssh connection. However, handshake failure due to wrong keyword happens before any authentication attempts were made, and fail2ban is not supposed to handle such failures. To make fail2ban pick up ssh handshake failures and ban IPs repeatedly trying to connect with wrong keywords, add the following regex to
failregex definition in
^%(__prefix_line)sMagic value check failed \(\d*\) on obfuscated handshake from <HOST> port
More recent versions of fail2ban have changed the filter file format and the following regex needs to be added to
cmnfailre definition in
^Magic value check failed \(\d*\) on obfuscated handshake from <HOST> port
Remember to check proper indention as it's Python code.
I have built patched versions of OpenSSH as Ubuntu source and binary packages and published them on launchpad.
Use the following commands to install the package corresponding to your versions of Ubuntu:
apt-add-repository ppa:zinglau/obfuscated-openssh apt-get update apt-get install ssh
Don't forget to edit /etc/ssh/sshd_config and restart ssh service after installation.
For Debian, I have set up a repository for the patched source and binary packages that is available at https://deb.zinglau.com/debian/ . Use the following commands to enable this repository (change the
buster part if necessary):
wget https://deb.zinglau.com/pubkey.gpg -O - | apt-key add - echo "deb https://deb.zinglau.com/debian/ buster main" > /etc/apt/sources.list.d/obfuscated_openssh.list apt-get update apt-get install ssh
Since this patchset introduces configuration keys not known to upstream openssh, it is important that unpatched openssh-server is not installed if the ppa version lags behind distribution version. Otherwise, ssh server won't be able to start and you may get locked out. This can be achieved using apt pinning.
For Ubuntu, create a file in
/etc/apt/preferences.d/ with the following contents:
Package: * Pin: release o=LP-PPA-zinglau-obfuscated-openssh Pin-Priority: 600
For Debian, create a file in
/etc/apt/preferences.d/ with the following contents:
Package: * Pin: release o=zinglau.com Pin-Priority: 600
Successful pinning can be verified using
apt-cache policy openssh-server.
In addition, if your server has
unattended-upgrades enabled, it's best to restart the service to ensure the pinning is picked up. To be safer, you can also disable unattended automatic update of
openssh-server, by adding it under "Unattended-Upgrade::Package-Blacklist" in
/etc/apt/apt.conf.d/50unattended-upgrades, and restart the service.
For serious bugs and issues, please report using github. For simple questions, just leave a comment below using Disqus.
If this project has proven useful to you, feel free to show your appreciation :)