Ask HN: What Linux setup/hardening guide do you use?

88 points by z9znz ↗ HN
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 ] thread
I use Arch, btw. But I run the linux-hardened kernel, doing pacman -Syu once a week.

I also run endlessh on TCP port 22, and a fake HTTP server as a community service.

I was running this on my laptop for a while but it doesn't support hibernation which sucks :(
Try linux-zen. I run it on Dell laptops, and it seems to support hibernation. Unless I'm not calling it the right thing.
Im curious: Why are you running a fake HTTP server? To slow down bots for a while or does it serve a higher purpose?
Slow down bots, and to see what garbage they're sending. I keep track of POST data and HTTP headers.

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.

Why aren't linux-hardened's options the default and patches, if any, upstreamed?
I'm running my mail server on Arch Linux since 2011 (so since Arch was in its quite early days) and I applied principles outlined within CISSP. Particularly I was focusing on reducing plane of attack to absolute minimum, ensuring I know exactly what each config option results in and keeping my server up to date. This has served me well and let me go through more than a decade.

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.

SELinux, Rocky is good for servers (successor to CentOS)
Most server-oriented linux distributions come with fairly sensible defaults.

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.

My personal preference is to begin with STIG from DoD Cyber Exchange: https://public.cyber.mil/stigs/downloads/

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 :-)

Hardening against vulnerabilities is a zero sum game ultimately.

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

> 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].

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.

Most guides only deal with Systemd distros, not distros like Devuan etc
> I harden ssh (no root login, no passwords), setup fail2ban for it and leave it at that.

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)

Most is the guides online have the issue of being too specific to what the author cares about or just a dump of random "I thought it would be good" ideas. I wouldn't follow any specific ones really.

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.

Use a trusted distro like Ubuntu LTS. Install security updates automatically.

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.

(comment deleted)
Fail2ban serves no purpose other than bloating your firewall's denylist. You can mitigate most blind bruteforce attacks by just changing the port number of your SSH server and by using a public/private key pair instead of passwords.
While this obscurity doesn’t add much security, sure does clean up the logs, doesn’t it?
AppArmor is often pretty easy to use IME.
I do things like disabling ipv6 (to avoid thinking about ipv6 firewall), setting various sysctl settings (e.g. to make sure ipv4 forwarding is disabled), mounting /proc with hidepid option. I think this matters on any distro.

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

What does mounting /proc with hidepid option brings us?
Makes privilege escalation more difficult by tightening the information available to unprivileged processes.
It means that unprivileged users cannot see what other processes are running. Basically just prevents exposing information that might help an attacker, but it does break some tools that might rely on parsing /proc for system information if they are running unprivileged.
I like to live life dangerously, I use defaults.

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.

In the past I was following a guide which I probably got from a Digital Ocean blog post (they have a lot of very good instructive guides).

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.

Or all that stuff would be the default and the setup process of whatever you are doing would loosen restrictions. If you have pubke only for ssh, no need to log password attempts.
It depends

Do you want which of the two?

* performance

* security

* older hardware

I'm not OP, but I choose the first two. What are your recommendations?
It’s like asking: time, money, or resources? Pick only two

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).

(comment deleted)
Is older hardware that is performant not secure? I never had the feeling that securing a linux server slowed it down.
I've been hosting small and mid-sized web sites and applications for years without a hitch using my own script, written from reading it up online. It might not work exactly as is for you but perhaps can offer some reference: https://github.com/corenzan/provision
Is setting up a server by hand and following a checklist even the right frame for this question? I would imagine the orgs that are sophisticated about this have images, Puppet/Chef modules, etc. Might not even permit any manual tweaking.
I can't claim to have been through it but this is sitting on my bookmarks folder and looks very useful: https://github.com/imthenachoman/How-To-Secure-A-Linux-Serve...

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.

> by default docker will effectively override ufw port restrictions

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.

For my personal servers/services? Everything behind an OpnSense and only accessible via VPN. There is one service on HTTPS a friend has to access, that got a nginx as reverse proxy with http basic auth & long random password in front of it. This reduces my attack surface to "people on my network or VPN", which is further segmented in VLANs. The OpnSense firewalls between VLANs, and especially the IoT crap & my VPN only have very limited access.

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.

Really depends on the role of the system. Will it be multi-user/single-user? Hosting containers? Hosting virtual machines? Running as a virtual machine? Doing network magic? Each of these classifications will take hardening in different directions.

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)

Honestly I think nowadays the best idea is to not mess with defaults for the most part, but I do:

* 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

Selinux In enforcing mode, but you want RedHat family distro for that.
(comment deleted)
Can’t believe some of the terrible advice here.

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.

Ubuntu LTS is no longer viable, their last viable revision was 18.04.

They've also made it practically impossible to work around issues with their snap bs.

Better recommendation would be RHEL or Suse.

Find your favorite reference (e.g. CIS Benchmark Level 1/2, etc) and look for an open source implementation in configuration management code from a credible source. You can pear back from there. You’ll likely find they’ve implemented the configuration as well as the auditing.

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.

(comment deleted)
(comment deleted)
(comment deleted)