Nov 14, 2020
The main idea of SSH tarpit or honeypot is to trap script-kiddies who try to brute-force attack our servers with some scripts (via SSH, obviously).
endlessh
will pretend to establish the connection to any incoming SSH connection on the port(s), and then proceed to send random SSH login banner lines endlessly without triggering a connection timeout on the attacker side, hopefully to trap unattended attacks inside this loop forever.
Install AUR package endlessh-git
, edit some configuration in /etc/endlessh.conf
, and start the service endlessh.service
Because of my paranoia that I may have irritated an attacker for taking his precious time away, my
endlessh
is deployed in a chroot jail on the tarpit box to minimize any risks of the attacker taking over any of the two machines.
The source is available on GitHub. I am too lazy to patch it for OpenBSD, which is what my webserver is running, therefore I built the software and enabled it a different platform, and have OpenBSD’s relayd(8)
relay the SSH connections into the box running endlessh
.
OpenBSD’s man page for relayd.conf(5)
also has an example for relaying SSH connection. And because of relayd(8)
, we can just spin up one instance of endlessh
to listen to multiple ports on the OpenBSD box. If you are not on OpenBSD, feel free to use any software that could proxy TCP connections.
Simple TCP proxies can be used to redirect connections coming to the host you want to protect to other hosts, or the same hosts but to the port that endlessh.service
is listening on.
Proxying can help us guard the privileged port 22 without having to actually run Endlessh on that port, although it is the proxy who ultimately will have to run as root to listen on port 22.
In this example, I will show you how to set this proxy up, for both OpenBSD relay(8)
and NGINX.
You can just copy the ssh example from relayd.conf(5)
man page. In short, we first define a simple relayd
protocol to properly relay TCP connections. Then we create a relay using the protocol we defined to relay the connection from listening port to target (the one Endlessh is running on):
Note: only relavant portion is shown. You probably need to write some more global configuration, define some macros and host table, etc.
protocol "tcp_relay" {
tcp { nodelay, socket buffer 65536 }
}
relay "sshforward0" {
listen on $ipv4 port 22 #interface vio0
protocol "tcp_relay"
forward to $wg_endlessh port 2222
}
# Load-balance
# Load-balancing will need to specify a table as forward-to host
relay "sshforward1" {
listen on $ipv4 port 2222 #interface wg0
protocol "tcp_relay"
forward to $wg_endlessh port 2222 mode loadbalance check tcp
}
NGINX also has support for TCP relays, but called stream
. The following configuration will define an upstream (equivalent to OpenBSD relayd
’s table), and create a virtual server listening on port 22 that will proxy stream (SSH connections) to upstream endlessh
, which expands to 2 hosts.
If I understand correctly, by using upstream
directive, NGINX should also load-balance the connections instead of just proxying.
stream {
upstream endlessh {
server 127.0.0.1:2222 max_conns=3;
server 10.8.0.69:2222;
}
server {
listen 22;
proxy_pass endlessh;
}
The only difference between my SSH connection and the others is the destination port, which is not accessible outside of my VPN.
SSH connections ---> artnoi.com -(relay)-> Endlessh jail server
My SSH connection -> artnoi.com
$ ssh -v artnoi.com
OpenSSH_8.4p1, OpenSSL 1.1.1h 22 Sep 2020
debug1: Reading configuration data /home/artnoi/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to artnoi.com [45.32.125.13] port 22.
debug1: Connection established.
debug1: Local version string SSH-2.0-OpenSSH_8.4
debug1: kex_exchange_identification: banner line 0: 1m]+
debug1: kex_exchange_identification: banner line 1: i^'i
.
.
And it goes on and on and on!