Ask HN: What Linux setup/hardening guide do you use?
When setting up a new publicly accessible Linux server, it is usually necessary to make some changes from the defaults to improve security. There are many guides which can be followed, some from presumably reputable sources. However, the details depend quite a bit on Linux distro, version, and the current date.
Considering Ubuntu (22.02 LTS), what setup and hardening guide do you follow?
And if not using Ubuntu, or using a different version, please describe what you use and why (and if being so generous, also what guide you follow).
TIA!
54 comments
[ 3.9 ms ] story [ 113 ms ] threadI also run endlessh on TCP port 22, and a fake HTTP server as a community service.
I'm on CenturyLink fiber, they are apparently so incompetent they can't take my money for a static IP address, so whoever is doing HTTP requests is blindly trolling CenturyLink residential IPv4 blocks. Nobody doing this is up to anything legit.
I see some posters saying it's not good practice to run Arch, but I think distro alone is not an answer to your security concerns.
Maybe wouldn't set up a pubnix on them without some tweaking, but for most use cases the defaults are sane. Maybe disable password login on SSH and if you're worried.
Set up a honeypot if you don't believe me.
They take a while to come for the latest version of a OS and none is out for Ubuntu later than 20.04 yet, but it is a very good starting point for a checklist even if you do not run a DoD system (a lot of the points might be specific for these but easily skipped) and depending on changes between versions, some parts might still apply. For a recently released OS you usually have to rely on the system documentation from the system creator (Canonical in this case) but most of my experience is from the Red Hat world so not sure how good it is for other distros.
If you start with the best practices for your OS/distro and then dig into a hardening guide (like STIG) you should probably have a pretty good understanding and base documentation for your specific use-case. As always, if you use a specific service/software on top of that (a web-server, mail-server, etc) you will need to dig into the documentation of that specific product and after that check for hardening guides.
The general principle of removing/disabling/blocking everything that you do not use is usually a good one. Knowing what you actually use and the exceptions is what makes it hard :-)
You can also do it the easy way, instead of installing Ubuntu, which is based on Debian, install and Arch spin such as Arco Linux https://arcolinux.com/ and during the installation choose the 'hardened kernel' option instead of the default or zen kernel.
It is my experience that most guides you will find for Linux hardening are either outdated, too opinionated or are written with shock value to induce paranoia [0].
I harden ssh (no root login, no passwords), setup fail2ban for it and leave it at that.
Only thing I remember to do is not to mess with security configurations e.g disabling selinux to make something work. Keeping number of software installed to an absolute minimum. And last but not least I setup automatic updates via unattended-upgrades.
[0] https://madaidans-insecurities.github.io/guides/linux-harden...
A lot of it may be written for career benefits as well. If you're trying to sell security services, especially if you don't really have too many actual referrals to show, putting together a guide or two like this (by borrowing tips you find online) makes you not only appear more legit, but it appears like you know byzantine security secrets that nobody else does.
Similar here (but I allow root login), with the addition of setting up an nftables firewall with whitelisted ports and logging all the rest, and having fail2ban analyze logs and adding/removing to it IPs that become blacklisted because of some global limit is exceeded (which happens e.g. if you try once to access weird stuff stuff in my webserver VM + try to guess a pwd in the mailserver VM + try to login unsuccessfully into SSHd)
Instead, if you'd like to improve your security, I'd recommend 3 things:
- Learn basics of threat modelling. There are many posts about it, but in short it's asking: who can do what and what are the options to prevent that.
- Learn what's running in your system. What services you're running, what apps. What untrusted data hits any software.
- Go to the higher quality sources for what you actually care about. For example, you find out you're running samba - read the security sections of their docs https://www.samba.org/samba/docs/using_samba/ch09.html and system administration guides. Read about firewall configuration for your system.
Be aware and focus specifically on which ports/services are available from the internet.
If you absolutely need SSH, ensure you use something like fail2ban and use complex credentials. If possible, use obscurity to change from the default port of 22.
If you're running an internet-facing service, like nginx, ensure that it's always up to date.
Using SELinux and AppArmour and GRSecurity are usually way overkill and cumbersome to manage.
[0] https://www.fuzzygrim.com/posts/secure-vps
There's no perfect guide. You should collect things that make sense to you, put them in git and apply to your servers via Ansible/SaltStack
Seriously though: Lynis when setting things up and then for work CIS.
But, that's just checking boxes. I do use apparmor to lockdown my browser and VMM but that's as far as I go and I have accepted that security on Linux is a dangerous illusion because there will always that one man page, that one setting everyone appsrently knows, that one permission you are expected to know by implication of having an understanding of some Linux subsystem where that is really all anyone targeting you needs to get in or move laterally. Logging more than you should and forwarding centrally (auditd and security logs) seems about all you can do (detection focused not prevention) that said, checking boxes is much better than defaults. Security is a reponsibility left to the user/admin by default and to be fair, Linux is hardlh alone in that regard,it just so happens to change a lot making it harder to keep up.
It eliminated password ssh logins (cert only), and I think it changed the default port (which I do always, just to cut out the lowest quality script kiddies).
As I recall, it also changed some permissions on shared memory via fstab. And it did something regarding sudo or suid... I forget now.
I also setup ufw firewall so at least I only allow incoming request to the specific services I intend to offer.
All that said, my nginx logs would be full of sh*t from wordpress-related vulnerability scanners and whatnot, and it just personally offended me. I think I did try to setup fail2ban, but I don't recall the success of that.
At this point it seems like there should be a "wizard" (not so unlike a linux console installation process) which asks you questions and adjusts configuration accordingly.
Do you want which of the two?
* performance
* security
* older hardware
It depends on your goal.
Me; <=2014 CPU, DDR3, Whonix/Gentoo OS with eBPF JIT compiled out for servers;
QubesOS for desktops with bleeding edge CPU, H/T BIOS disabled, and CPU IBT compiled out.
Absolutely no JavaScript (not even WASM).
It applies to basically every distribution and has useful links at the bottom for even more tips.
My only tip I haven't seen mentioned here is be very careful using docker with ufw, as by default docker will effectively override ufw port restrictions if it is told to expose a port.
Thanks for that reminder. I discovered that accidentally last year with a toy project and it blew my mind! I still think that is a terrible bad default behavior… and I was disappointed to learn that root-defined UFW rules were not the final answer.
I HTTPS all the things except the Tasmota UIs. I use a SmallStep CA with ACME on my internal network to get certs for my internal stuff; to be safe, the root cert is NameConstrain'ed to `.lan`. Obviously everything is in my local DNS. If someone steals that approach: Make sure to put DHCP-assigned DNS names into something like `.dhcp.lan` ;-)
As you can see, this is already quite opinionated. Generally: Be minimal with what you expose, make sure to quickly update, setup SELinux, setup proper firewalls/VLANs for multi-host deployments. SSH only with keys, not with passwords. Compartmentalize, so that one breach doesn't pwn your machine(s). For that you need either more physical machines, or you can put stuff in containers (I prefer root-less podman over docker) or VMs (e.g. libvirt/qemu or ESXi).
Also, don't rely on some Ubuntu LTS to get all updates you need for "a long time". E.g. Tomcat is a community package and the 18.04 LTS was missing many (security) updates last time I've checked. I've also seen docker containers not being timely updated by their maintainers. Do some external port scans to not be surprised that you e.g. accidentially left your SQL open for the world. Because mistakes happen, and a `nmap -T5 -p1-65535 $host` doesn't hurt you.
You can get a rough feel for the enthusiasm of your distro's desire to do 'hardened things' by checking its kernel config. Heres one such script that has consolidated some hardening guides; https://github.com/a13xp0p0v/kconfig-hardened-check and also spot check with http://kernsec.org/wiki/index.php/Kernel_Self_Protection_Pro...
Then can also see if the distro is doing things to harden the binaries (relro, nx, canaries, aslr, pie, etc) ; https://www.trapkit.de/tools/checksec/ Also! you may be surprised to find which distros are comfortable with allowing unprivileged user namespaces (kernel.unprivileged_userns_clone=1)
* Check open/listening ports and reconfigure or disable unnecessary services to limit attack surface. Do you really need an NTP server, or just a client? What about SNMP, you going to use that or do you use telegraf/metricbeat/whatever?
* Harden configs for any remaining services. SNMPv3 only. SSH key/cert based auth only. Disable insecure ciphers or protocols.
* Keep the distro PATCHED. So easy to pwn old ass sudo binaries, openssl versions, or kernels. Patch your shit. Can't overstate this.
* send audit logs to a central log store, for post-intrusion forensics
Stick with Ubuntu LTS, unless you are willing to pay for RHEL. Do NOT use Fedora or any Arch based distro, those have way too aggressive releases to be considered for any type of server (they are fine desktop or lab distros but I would never consider them for legit servers).
Ideally have a firewall (or security group if in AWS, etc) that sits in front of your server. Make sure only the absolute necessary ports are open (white list by ip if you can). Extra credit have Wire Guard server that you connect to and only allow ssh through that.
If you are the only person accessing a shell on the machine then make sure shh allows keys only, and make sure you private key has a pass phrase on it. Extra credit, use jump cloud (free if you have under 5 users), and it’s super easy to enforce 2FA with ssh.
If you have several people that need to ssh then use a short lived certificate solution like Teleport.
They've also made it practically impossible to work around issues with their snap bs.
Better recommendation would be RHEL or Suse.
I use to download the Cookbooks for CIS benchmark from Chef’s repos.
An important detail is that these frameworks will typically word a control as "Disable X, unless it is required by the application or not used”. Don’t beat yourself up for removing controls that are not applicable to your situation.
Once your application is installed and configured, with configuration management of course, set AppArmor or SELinux into permissive but logging mode. After profiling the application in use for a period, write a policy to allow those events for your application and enable enforcing mode.
Systemd offers some very simple to use controls as well. You can update your application unit to do sandboxing things like block access to system directories, block system capabilities, and even limit network access. These additions are very easy with significant rewards.
If you can bake it all into a machine image, glorious. If you need last mile configuration or personalization, use cloud-init to make those changes on first boot. If you need to save state, externalize it with an additional volume or network storage. Log to an external system, and disable remote access. Enforce a maximum life for a server to a couple of days and replace. Of course, many applications can’t survive as cattle and need to live longer or have difficult replacement procedures.