openssh obfuscation patch ppa deb disqus

Obfuscated OpenSSH Patches

Updated: 2023-Oct-09

1. Introduction to Obfuscated OpenSSH

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.

2. How to Use the Patches

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 portable folder.

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

3. Server Configuration

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

4. Connecting to Obfuscated OpenSSH Server

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 1.2.3.4
    Port 2234
    ObfuscateHandshake yes
    ObfuscateKeyword mykey

Then you can just input 'ssh obssh1' to connect to 1.2.3.4:2234 using obfuscation keyword 'mykey', equivalent to 'ssh -z -Z mykey -p 2234 1.2.3.4'.

5. Securing Server using Fail2ban

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 /etc/fail2ban/filter.d/sshd.conf:

^%(__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 /etc/fail2ban/filter.d/sshd.conf:

^Magic value check failed \(\d*\) on obfuscated handshake from <HOST> port

Remember to check proper indention as it's Python code.

6. Pre-built Binary Packages

I have built patched versions of OpenSSH as Ubuntu source and binary packages and published them on launchpad.

Use the following commands to enable the repository:

apt-add-repository ppa:zinglau/obfuscated-openssh

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 bookworm part to match the actual Debian version):

wget https://deb.zinglau.com/pubkey.pgp -O /etc/apt/keyrings/deb_zinglau_com.pgp
cat <<EOF > /etc/apt/sources.list.d/obfuscated_openssh.sources
# OpenSSH with obfuscated handshake
Types: deb deb-src
URIs: https://deb.zinglau.com/debian
Suites: bookworm
Components: main
Signed-By: /etc/apt/keyrings/deb_zinglau_com.pgp
EOF

For Debian versions < 12 (Bullseye and earlier), it's also possible to use the following commands to enable this repository (change the bullseye part if necessary):

wget https://deb.zinglau.com/pubkey.pgp -O - | apt-key add -
echo "deb https://deb.zinglau.com/debian/ bullseye main" > /etc/apt/sources.list.d/obfuscated_openssh.list

After the repository has been enabled, install the patched server and client:

apt-get update
apt-get install ssh

Don't forget to edit /etc/ssh/sshd_config and restart ssh service after installation to enable obfuscation.

7. Don't get locked out by auto upgrade!

Since this patchset introduces configuration keys not known to upstream openssh, it is vital that unpatched openssh-server is not installed over patched version, e.g. when published ppa/deb 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 Debian-based distros.

Create a file in /etc/apt/preferences.d/ with the following contents:

Package: *
Pin: release o=LP-PPA-zinglau-obfuscated-openssh
Pin-Priority: 600

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 becomes effective. 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.

8. Bugs and Issues

For serious bugs and issues, please report using github. For simple questions, just leave a comment below using Disqus.


Donation

If you find this project useful, feel free to show your appreciation :)

Donate using Liberapay