Hardening my freshly installed OpenBSD 6.5 box

First I want to be able to use my regular user, the one I made during installation, to use doas which is pretty much something like sudo. Let’s edit the file /etc/doas.conf to enable it.

Ah, and now it turns out that my favorite editor is not available by default, so let’s first install that. I install nano in this process, but you might like another editor, or even, you might be happy using vi, whatever your preferences are, this is the time to make them available!!

$ su root
# pkg_add nano

On a recent install pkg_add wasn’t working, giving me errors like:

# pkg_add nano
https://cdn.openbsd.org/pub/OpenBSD/6.9/packages-stable/amd64/: TLS handshake failure: ocsp verify failed: ocsp response not current
https://cdn.openbsd.org/pub/OpenBSD/6.9/packages/amd64/: TLS handshake failure: ocsp verify failed: ocsp response not current
https://cdn.openbsd.org/pub/OpenBSD/6.9/packages/amd64/: empty
Can't find nano

The problem was my clock was ahead 2 hours:

# date
Wed May 26 19:08:28 CEST 2021
# date 1709
Wed May 26 17:09:00 CEST 2021

And now pkg_add was working just as it should.

doas

And now we have nano at our fingertips, so let’s put that to effect:

$ su root
# nano /etc/doas.conf

create the file with the following content, permitting users from the wheel group to do-as…

permit persist :wheel

ssh & sshd

One of the first things I like to do is enabling hasing of the hostnames in ~/.ssh/known_hosts so an attacker is not able to see which boxes I visit from this machine. In /etc/ssh/ssh_config set:

HashKnownHosts yes

Next I only want to use public-private key authentication on ssh. So first let’s upload my public key, from my local machine:

$ ssh-copy-id -i id_rsa user@hostname

As soon as we verified that the key is working we disable password login for the ssh-server in /etc/ssh/sshd_config make sure to set:

PasswordAuthentication no
ChallengeResponseAuthentication no

And we reload sshd:

$ doas rcctl reload sshd

And now log out and back in.

firewall

Trying to read and learn about PF, the OpenBSD Packet Filter, that can do firewalling, NAT, just to name a few, I was a bit overwhelmed. And I actually had a hard time finding examples of rules that would do what I wanted. In the end I just sad down, and with some trail and error I ended up with a simple set of rules that did what I wanted, which I added to the end of /etc/pf.conf

# here I go!! following conf by R3MY B7OM!
#
# WHAT I WANT:
#
# pass all out, block all in, except on http/https

web = "{ 80, 443 }"

block in
pass out

pass in proto tcp from any to any port $web

# I want to restrict access to any port to a group of trusted ip/ranges:
# 10.1.0.0/16       # Some IP Range that I trust
# 192.168.0.0./16   # Other IP Range that is okay!

trusted = "{ 10.1.0.0/16, 192.168.0.0/16, server.hostname.com foo.hostname.com }"

pass in proto tcp from $trusted to any

To activate the current config type:

$ doas pfctl -f /etc/pf.conf

Do take care tho, you might apply rules that shut yourself out of your box. I saw people do cronjobs that disable pf every 2 minutes or so, but as long as you have access to the console, you don’t need these fancy work-arounds, you just use the console to change your ruleset.

Now in the above ruleset I opened up 80 and 443 for http and https traffic, but I have not yet installed any webserver. But to test the correct rules are set in pf you can use this very useful command:

$ doas nc -l 80

It starts listening on port 80. doas is needed for lower port-numbers. You can use telnet to connect to the port and everything you enter there will echo here. Great little tool.

$ telnet hostname 80

syspatch and pkg_add

To keep your system up-to-date you should regularly check to see patches are available:

$ doas syspatch -c

Install the available patches:

$ doas syspatch

Keeping installed packages up-to-date, use:

$ doas pkg_add -u

Only see what pkg_add -u will do:

$ doas pkg_add -us

Now that we have this out of the way, let’s install the famous LEMP-stack!

Hardening Ubuntu 18.04 LTS

Just got a new box setup and delivered to me by the company’s IT department. They setup a user-account with sudo privileges and included my public ssh-key. But in case you only have a root account you should create a user-account with sudo privileges yourself:

$ adduser username
$ usermod -aG sudo username

And from your local machine upload your public key:

$ ssh-copy-id -i .ssh/id_rsa user@hostname

So let’s start hardening. First let’s set a new password:

$ passwd

After that I needed to set another hostname, since the one I got from IT was not what I asked for:

$ sudo nano hostname
$ sudo nano hosts
$ sudo reboot 

ssh & sshd

In /etc/ssh/sshd_config set:

PermitRootLogin no 
PasswordAuthentication no 

In /etc/ssh/ssh_config set:

HashKnownHosts yes

firewall

Use a firewall to block all unwanted traffic to your machine. Only open up the ports you want publicly available and limit access to your ssh-port to known IP’s only.

$ sudo ufw allow from 10.2.0.0/16
$ sudo ufw allow http 
$ sudo ufw allow https
$ sudo ufw enable
$ sudo ufw status numbered

unattended updates

Make sure the package is installed and running:

$ sudo apt install unattended-upgrades
$ sudo service unattended-upgrades status

Edit /etc/apt/apt.conf.d/50unattended-upgrades to do only security updates on production machines. Only out-comment the following lines:

"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESM:${distro_codename}";

Security updates may need dependencies from non-security origins. EMS, or extended security maintenance is for releases that have reached end of life, like 14.04 LTS.

Further you can play with settings like:

Unattended-Upgrade::Mail "your@email.com";
Unattended-Upgrade::MailOnlyOnError "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

Doing automatic-reboots at night are at your own risk, I don’t do that on production machines, but really think it is perfectly fine on private, personal and development boxes. And I have never had anything go wrong with them, ever…

Add/edit /etc/apt/apt.conf.d/20auto-upgrades:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

The unattended upgrades are initiated by your daily crontab, in my case this runs at 06:25 by default, which I think is a little late to also do a reboot, so I changed the time my daily crontab runs by editing /etc/crontab:


# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
0  3	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

Test

$ sudo unattended-upgrades --dry-run --debug

Checkrestart

Another great way to see whether you need to reboot a machine or are just fine with reload/restarting services is the checkrestart command. It is not on the machine by default so you install it yourself:

$ sudo apt install debian-goodies

I added it to my .bash_profile so everytime I log into the machine I get to see which processes still use old versions of upgraded files.

echo 'Type password for checkrestart report'
sudo checkrestart

More stuff…

This list is of course incomplete and could be updated and expended over time… Things like fail2ban or appArmor might be added….

But for now let’s install that LEMP stack!