Unprivileged endlessh
on FreeBSD
23 December 2021
endlessh
is a tar pit for SSH connections. It ties up the resources of bots trying to connect
to your box. It's very easy to set up, but the most activity from bots will be found on port 22, which must
be bound as a privileged user. Unfortunately, endlessh
doesn't drop privileges, so we need a
workaround to run it as a user other than root.
First, make sure you have set SSH to listen on a different port. I won't go over this here, but
I will assume you've chosen port 9001.
Then, make sure you have git
installed.
Finally, we'll clone endlessh
and build it.
$ sudo pkg install git
$ git clone https://github.com/skeeto/endlessh.git
$ cd endlessh
$ make
Now, in the same directory, we need to create the config file, which I'm calling endlessh.conf
.
For an explanation of each line, see the endlessh
documentation. Essentially, we're binding to
port 2222, logging events non-verbosely, and listening over both IPv4
and IPv6
.
Port 2222
Delay 10000
MaxLineLength 32
MaxClients 4096
LogLevel 1
BindFamily 0
Now, to get traffic destined for port 22 to our instance of endlessh
, we need to use
pf
to redirect it over. I'll assume you don't have pf
set up already.
First let's create /etc/pf.conf
and add in a basic configuration to allow some common services.
I'll add a comment before each line explaining what it does.
# do not filter packets for loopback
set skip on lo0
# redirect all TCP traffic destined for port 22 on vtnet0 to port 2222
# if you already have pf set up, this is the important line, and
# position in the file matters.
rdr on vtnet0 inet proto tcp from any to port 22 -> 127.0.0.1 port 2222
# start by dropping inbound traffic.
block drop in all
# all outbound traffic is allowed.
pass out all keep state
# inbound ICMP traffic is allowed.
pass in proto { icmp, icmp6 }
# allow inbound tcp traffic to these ports.
tcpPorts = "{ 22 80 443 2222 9001 }"
pass in proto tcp to port $tcpPorts
This is pretty minimal. Substitute 9001 for whatever port you have SSH actually running on. If you have
services using UDP, duplicate the last two lines but s/tcp/udp
. Don't forget to change
vtnet0
to whatever your external interface is called. Also, we're allowing traffic directly
to 2222 as well as redirecting because it's a common substitute port for SSH. We'll catch a few more bots
there.
Time to enable pf
and allow IP forwarding. The latter is necessary for the redirection.
Run the following:
$ sudo sysrc pf_enable="YES"
$ sudo sysrc pf_rules="/etc/pf.conf"
$ sudo sysrc pflog_enable="YES"
$ sudo sysrc pflog_logfile="/var/log/pflog"
$ sudo sysctl net.inet.ip.forwarding=1
$ echo 'net.inet.ip.forwarding=1' | sudo tee -a /etc/sysctl.conf
$ sudo service pf start
$ sudo service pflog start
You'll need to pick a user to run endlessh
as. I am just going to use the preexisting
games
user because its shell is already set to /usr/sbin/nologin
and, well,
this is kind of a game, right? If you want to use a different one, run adduser
and set its
shell to /usr/bin/nologin
Now, let's create the log files. Replace games
with the user you picked.
$ sudo -u games touch endlessh.log
$ sudo -u games touch endlessh.err
Edit the user's crontab to have endlessh
start on boot.
$ sudo -u games crontab -e
@reboot /path/to/endlessh -f /path/to/endlessh.conf >/path/to/endlessh.log 2>/path/to/endlessh.err
Now restart the box. We're all set up! Check endlessh.log
after a few minutes to see the
inevitable bot connections, along with total time for each, bytes sent, etc.