From 7b75ddb8d417b1dc0aaf212403e5045ecf024bfc Mon Sep 17 00:00:00 2001 From: IMTheNachoMan Date: Sat, 16 Feb 2019 16:11:38 -0500 Subject: [PATCH] major changes - re-structure of document - adding new sections - added example output - other changes --- README.md | 1677 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 1077 insertions(+), 600 deletions(-) diff --git a/README.md b/README.md index 5b080db..a9e04f2 100644 --- a/README.md +++ b/README.md @@ -4,46 +4,44 @@ An evolving how-to guide for securing a Linux server that, hopefully, also teach ## Table of Contents -- [Table of Contents](#table-of-contents) - [Introduction](#introduction) - - [Document Objective](#document-objective) + - [Guide Objective](#guide-objective) - [Why Secure Your Server](#why-secure-your-server) - [Why Yet Another Guide](#why-yet-another-guide) - - [Contributing](#contributing) - - [Editing Configuration Files - For The Lazy](#editing-configuration-files---for-the-lazy) - [To Do / To Add](#to-do--to-add) +- [Guide Overview](#guide-overview) + - [About This Guide](#about-this-guide) + - [Safe vs. DANGER ZONE](#safe-vs-danger-zone) + - [Editing Configuration Files - For The Lazy](#editing-configuration-files---for-the-lazy) + - [Contributing](#contributing) - [Before You Start](#before-you-start) - - [Identify Your Principals](#identify-your-principals) + - [Identify Your Principles](#identify-your-principles) - [Picking A Linux Distribution](#picking-a-linux-distribution) - [Installing Linux](#installing-linux) - [Pre/Post Installation](#prepost-installation) - - [Important Advice For Using This Guide](#important-advice-for-using-this-guide) -- [Securing Linux - Safe To Do](#securing-linux---safe-to-do) - - [Overview](#overview) + - [Other Important Notes](#other-important-notes) +- [The Main Event](#the-main-event) - [SSH Public/Private Keys](#ssh-publicprivate-keys) - [Limit Who Can Use `sudo`](#limit-who-can-use-sudo) - [Secure SSH](#secure-ssh) - [Create SSH Group For `AllowGroups`](#create-ssh-group-for-allowgroups) - - [Secure `/etc/ssh/sshd_config`](#secure-etcsshsshdconfig) + - [Secure `/etc/ssh/sshd_config`](#secure-etcsshsshd_config) - [Deactivate Short Moduli](#deactivate-short-moduli) - - [Force Accounts To Use Secure Passwords](#force-accounts-to-use-secure-passwords) - [NTP Client](#ntp-client) + - [`[NS]` Configure Gmail as MTA](#ns-configure-gmail-as-mta) - [UFW: Uncomplicated Firewall](#ufw-uncomplicated-firewall) - - [Fail2ban: Intrusion Detection And Prevention](#fail2ban-intrusion-detection-and-prevention) + - [PSAD: `iptables` Intrusion Detection And Prevention](#psad-iptables-intrusion-detection-and-prevention) + - [`[NS]` Separate `iptables` Log File](#ns-separate-iptables-log-file) + - [Fail2ban: Application Intrusion Detection And Prevention](#fail2ban-application-intrusion-detection-and-prevention) + - [`[DZ]` Linux Kernel `sysctl` Hardening](#dz-linux-kernel-sysctl-hardening) + - [`[DZ]` Password Protect GRUB](#dz-password-protect-grub) + - [`[DZ]` Disable Root Login](#dz-disable-root-login) + - [`[DZ]` Change Default `umask`](#dz-change-default-umask) + - [Force Accounts To Use Secure Passwords](#force-accounts-to-use-secure-passwords) - [2FA/MFA for SSH](#2famfa-for-ssh) - [Apticron - Automatic Update Notifier](#apticron---automatic-update-notifier) - [Orphaned Software](#orphaned-software) -- [Securing Linux - DANGER ZONE](#securing-linux---danger-zone) - - [Section Overivew](#section-overivew) - - [Linux Kernel `sysctl` Hardening](#linux-kernel-sysctl-hardening) - - [Change Default `umask`](#change-default-umask) - - [Password Protect GRUB](#password-protect-grub) - - [Disable Root Login](#disable-root-login) -- [Other Stuff](#other-stuff) - - [Configure Gmail as MTA](#configure-gmail-as-mta) - [Lynis - Linux Security Auditing](#lynis---linux-security-auditing) -- [Not Security](#not-security) - - [Mount `/tmp` In RAM Using `tmpfs`](#mount-tmp-in-ram-using-tmpfs) - [Miscellaneous](#miscellaneous) - [Contacting Me](#contacting-me) - [Additional References](#additional-references) @@ -54,33 +52,23 @@ An evolving how-to guide for securing a Linux server that, hopefully, also teach ## Introduction -### Document Objective +### Guide Objective This guide's purpose is to teach you how to secure a Linux server. -There are a lot of things you can do to secure a Linux server to prevent bad-actors from gaining access to your server and this guide will attempt to cover as many of them as possible. More topics/material will be added as I learn, or as folks [contribute](#contributing). - -This guide... - -- ...**is** a work in progress. -- ...**is** focused on **at-home** Linux servers. All of the concepts/recommendations here apply to larger/professional environments but those use-cases call for more advanced and specialized configurations that are out-of-scope for this guide. -- ...**does not** teach you about Linux, how to [install Linux](#installing-linux), or how to use it. -- ...**is** meant to be [Linux distribution agnostic](#distribution-agnostic). -- ...**does not** teach you everything you need to know about security nor does it get into all aspects of system/server security. Physical security, for example, is out of scope for this guide. -- ...**does not** talk about how programs/tools work, nor does it delve into their nook and crannies. Most of the programs/tools this guide references are very powerful and highly configurable. The goal is to cover the bare necessities -- enough to wet your appetite and make you hungry enough to go and learn more. -- ...**aims** to make it easy by providing code you can copy-and-paste. You might need to modify the commands before you paste so keep your favorite [text editor](https://notepad-plus-plus.org/) handy. +There are a lot of things you can do to secure a Linux server and this guide will attempt to cover as many of them as possible. More topics/material will be added as I learn, or as folks [contribute](#contributing). ([Table of Contents](#table-of-contents)) ### Why Secure Your Server -I assume you're using this guide because you, hopefully, already understand why good security is important. That is a heavy topic onto itself and breaking it down is out-of-scope for this document. If you don't know the answer to that question, I advise you research it first. +I assume you're using this guide because you, hopefully, already understand why good security is important. That is a heavy topic onto itself and breaking it down is out-of-scope for this guide. If you don't know the answer to that question, I advise you research it first. -At a high level, the second a device, like a server, is in the public domain -- i.e visible to the outside world -- it becomes a target for bad-actors. An unsecured device is a playground for bad-actors who want access to confidential data, or to add nodes to their coordinated large-scale DDOS attacks. +At a high level, the second a device, like a server, is in the public domain -- i.e visible to the outside world -- it becomes a target for bad-actors. An unsecured device is a playground for bad-actors who want access to your data, or to use your server as another node for their large-scale DDOS attacks. What's worse is, without good security, you may never know if your server has been compromised. A bad-actor may have gained unauthorized access to your server and copied your data without changing anything so you'd never know. Or your server may have been part of a DDOS attack and you wouldn't know. Look at many of the large scale data breaches in the news -- the companies often did not discover the data leak or intrusion until long after the bad-actors were gone. -Contrary to popular, bad-actors don't always want to change something or lock you out of your data for money. Sometimes they just want your for their data warehouses (there is big money in big data) or to covertly use your server for their nefarious purposes. +Contrary to popular, bad-actors don't always want to change something or [lock you out of your data for money](). Sometimes they just want your for their data warehouses (there is big money in big data) or to covertly use your server for their nefarious purposes. ([Table of Contents](#table-of-contents)) @@ -90,7 +78,7 @@ This guide may appear duplicative/unnecessary because there are countless articl As I was going through research for my Debian build, I kept notes. At the end I realized that, along with what I already knew, and what I was learning, I had the makings of a how-to guide. I figured I'd put it online to hopefully help others **learn**, and **save time**. -I've never found one guide that covers everything -- this guide is my attempt to remedy that. +I've never found one guide that covers everything -- this guide is my attempt. Many of the things covered in this guide may be rather basic/trivial, but most of us do not install Linux every day and it is easy to forget those basic things. @@ -98,11 +86,47 @@ IT automation tools like [Ansible](https://www.ansible.com/), [Chef](https://www ([Table of Contents](#table-of-contents)) -### Contributing +### To Do / To Add -I wanted to put this document on [GitHub](http://www.github.com) to make it easy to collaborate. The more folks that contribute, the better and more complete this guide will become. +- [ ] [Custom Jails for Fail2ban](#custom-jails) +- [x] [Linux Kernel `sysctl` Hardening](#dz-linux-kernel-sysctl-hardening) +- [ ] [Security-Enhanced Linux / SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) +- [ ] disk encryption +- [x] BIOS password +- [ ] Anti-Virus +- [x] use ed25519 keys instead of RSA for SSH public/private keys +- [x] `psad` +- [ ] unattended upgrades for critical security updates and patches +- [ ] `logwatch` -To contribute you can fork and submit a pull request or submit a [new issue](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/new). +([Table of Contents](#table-of-contents)) + +## Guide Overview + +### About This Guide + +This guide... + +- ...**is** a work in progress. +- ...**is** focused on **at-home** Linux servers. All of the concepts/recommendations here apply to larger/professional environments but those use-cases call for more advanced and specialized configurations that are out-of-scope for this guide. +- ...**does not** teach you about Linux, how to [install Linux](#installing-linux), or how to use it. +- ...**is** meant to be [Linux distribution agnostic](#picking-a-linux-distribution). +- ...**does not** teach you everything you need to know about security nor does it get into all aspects of system/server security. For example, physical security is out of scope for this guide. +- ...**does not** talk about how programs/tools work, nor does it delve into their nook and crannies. Most of the programs/tools this guide references are very powerful and highly configurable. The goal is to cover the bare necessities -- enough to wet your appetite and make you hungry enough to want to go and learn more. +- ...**aims** to make it easy by providing code you can copy-and-paste. You might need to modify the commands before you paste so keep your favorite [text editor](https://notepad-plus-plus.org/) handy. +- ...**is** organized in an order that makes logical sense to me -- i.e. securing SSH before installing a firewall. As such, this guide is intended to be followed in the order it is presented but it is not necessary to do so. Just be careful if you do things in a different order -- some sections require previous sections to be completed. + +([Table of Contents](#table-of-contents)) + +### Safe vs. DANGER ZONE + +Some of the sections in this guide are generally considered safe and shouldn't make your system unusable. + +Some sections cover things that are high risk because there is a possibility they can make your system unusable, or are considered unnecessary by many because the risks outweigh any rewards. These sections are tagged with **`[DZ]`** and the content is hidden by default. **!! PROCEED AT YOUR OWN RISK !!** + +Some sections are not necessary to secure your server but are still helpful. For example, you don't need to [configure your server to send `mail` through Gmail](#ns-configure-gmail-as-mta) but you will want someway to send e-mails so you get critical system/security alerts. These sections are tagged with **`[NS]`**. + +Regardless of the section, as is with **anything** in this guide, **use with caution and proceed at your own risk**. ([Table of Contents](#table-of-contents)) @@ -120,27 +144,19 @@ Not all changes can be automated with `code` snippets. Those changes need good, ([Table of Contents](#table-of-contents)) -### To Do / To Add +### Contributing -- [ ] [Custom Jails for Fail2ban](#tbd) -- [ ] [Linux Kernel `sysctl` Hardening](#tbd) -- [ ] [Security-Enhanced Linux / SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) -- [ ] disk encryption -- [x] BIOS password -- [ ] Anti-Virus -- [x] use ed25519 keys instead of RSA for SSH public/private keys -- [ ] `psad` -- [ ] unattended upgrades for critical security updates and patches -- [ ] `logwatch` +I wanted to put this guide on [GitHub](http://www.github.com) to make it easy to collaborate. The more folks that contribute, the better and more complete this guide will become. +To contribute you can fork and submit a pull request or submit a [new issue](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/new). ([Table of Contents](#table-of-contents)) ## Before You Start -### Identify Your Principals +### Identify Your Principles -Before you start you will want to identify what your principals are. What is your [threat model](https://en.wikipedia.org/wiki/Threat_model)? Some things to think about: +Before you start you will want to identify what your Principles are. What is your [threat model](https://en.wikipedia.org/wiki/Threat_model)? Some things to think about: - Why do you want to secure your server? - How much security do you want or not want? @@ -149,7 +165,7 @@ Before you start you will want to identify what your principals are. What is you - Is physical access to your server/network a possible attack vector? - Will you be opening ports on your router so you can access your server from outside your home? - Will you be hosting a file share on your server that will be mounted on a desktop class machine? What is the possibility of the desktop machine getting infected and, in turn, infecting the server? - - Do you have a means of recovering if your security implementation locks you out of your own server? For example, you [disabled root login](#disable-root-login) or [password protected GRUB](#password-protect-grub). + - Do you have a means of recovering if your security implementation locks you out of your own server? For example, you [disabled root login](#dz-disable-root-login) or [password protected GRUB](#dz-password-protect-grub). These are just **a few things** to think about. Before you start securing your server you will want to understand what you're trying to protect against and why so you know what you need to do. @@ -161,7 +177,7 @@ These are just **a few things** to think about. Before you start securing your s You want a distribution that... -- ...**is stable**. Unless you like debugging issues at 2 AM, you don't want an [unattended upgrade](#wip), or a manual package/system update, to render your server inoperable. But this also means you're okay with not running the latest, greatest, bleeding edge software. +- ...**is stable**. Unless you like debugging issues at 2 AM, you don't want an [unattended upgrade](#tbd), or a manual package/system update, to render your server inoperable. But this also means you're okay with not running the latest, greatest, bleeding edge software. - ...**stays up-to-date with security patches**. You can secure everything on your server, but if the core OS or applications you're running have known vulnerabilities, you'll never be safe. - ...**you're familiar with.** If you don't know Linux, I would advise you play around with one before you try to secure it. You should be comfortable with it and know your way around, like how to install software, where configuration files are, etc... - ...**is well supported.** Even the most seasoned admin needs help every now and then. Having a place to go for help will save your sanity. @@ -170,7 +186,7 @@ You want a distribution that... ### Installing Linux -Installing Linux is out-of-scope for this document because each distribution does it differently and the installation instructions are usually well documented. If you need help, start with your distribution's documentation. Regardless of the distribution, the high-level process usually goes like so: +Installing Linux is out-of-scope for this guide because each distribution does it differently and the installation instructions are usually well documented. If you need help, start with your distribution's documentation. Regardless of the distribution, the high-level process usually goes like so: 1. download the ISO 1. burn/copy/transfer it to your install medium (e.g. a CD or USB stick) @@ -184,18 +200,18 @@ Where applicable, use the expert install option so you have tighter control of w ### Pre/Post Installation - If you're opening ports on your router so you can access your server from the outside, disable the port forwarding until your system is up and secured. -- Unless you're doing everything physically connected to your server, you'll need SSH access so be sure it is installed. -- Be sure to keep your system up-to-date (i.e. `sudo apt update && sudo apt upgrade` on Debian based systems) +- Unless you're doing everything physically connected to your server, you'll need remote access so be sure SSH works. +- Be sure to keep your system up-to-date (i.e. `sudo apt update && sudo apt upgrade` on Debian based systems). - At some point, like maybe right after configuring [SSH public/private keys](#ssh-publicprivate-keys), make sure you perform any tasks specific to your setup like: - configuring network - - configuring mount points in `/etc/fstab` (like [mounting `/tmp` in RAM using `tmpfs`](#mount-tmp-in-ram-using-tmpfs)) + - configuring mount points in `/etc/fstab` - creating the initial user accounts - etc... -- Your server will need to be able to send e-mails so you can get important security alerts. If you're not setting up a mail server check [Configure Gmail as MTA](#configure-gmail-as-mta). +- Your server will need to be able to send e-mails so you can get important security alerts. If you're not setting up a mail server check [Configure Gmail as MTA](#ns-configure-gmail-as-mta). ([Table of Contents](#table-of-contents)) -### Important Advice For Using This Guide +### Other Important Notes - This guide is being written and tested on Debian. Most things below should work on other distributions. If you find something that does not, please [contact me](#contacting-me). The main thing that separates each distribution will be its package management system. Since I use Debian, I will provide the appropriate `apt` commands that should work on all [Debian based distributions](https://www.debian.org/derivatives/). If someone is willing to [provide](#contributing) the respective commands for other distributions, I will add them. - File paths and settings also may differ slightly -- check with your distribution's documentation if you have issues. @@ -204,13 +220,7 @@ Where applicable, use the expert install option so you have tighter control of w ([Table of Contents](#table-of-contents)) -## Securing Linux - Safe To Do - -### Overview - -This section covers things you can do that are generally considered safe and shouldn't make your system unusable. **However**, as is with **anything** in this guide, **use with caution and proceed at your own risk**. - -([Table of Contents](#table-of-contents)) +## The Main Event ### SSH Public/Private Keys @@ -218,12 +228,12 @@ This section covers things you can do that are generally considered safe and sho Using SSH public/private keys is more secure than using a password. It also makes it easier and faster, to connect to our server because you don't have to enter a password. -Check the [references](#ssh-key-references) below for more details but, at a high level, public/private keys work by using a pair . +Check the [references](#ssh-key-references) below for more details but, at a high level, public/private keys work by using a pair of keys to verify identity. 1. One key, the **public** key, **can only encrypt data**, not decrypt it 1. The other key, the **private** key, can decrypt the data -For SSH, a public and private key is created on the client. The public key is then securely transferred to the server you want to connect to. After this is done, SSH uses the public and private keys to verify identity and then establishing a secure connection. Identity is verified by the server encrypting a challenge message with the public key, then sending it to the client. If the client cannot decrypt the challenge, the identity can't be verified and a connection will not be established. +For SSH, a public and private key is created on the client. The public key is then securely transferred to the server you want to connect to. After this is done, SSH uses the public and private keys to verify identity and then establishing a secure connection. Identity is verified by the server encrypting a challenge message with the public key, then sending it to the client. If the client cannot decrypt the challenge message with the private key, the identity can't be verified and a connection will not be established. They are considered more secure because you need the private key to establish an SSH connection. If you set [`PasswordAuthentication no` in `/etc/ssh/sshd_config`](#PasswordAuthentication), then SSH won't let you connect without the private key. @@ -254,22 +264,60 @@ We will be using Ed25519 keys which, according to [https://linux-audit.com/](htt #### Steps -1. From the computer you're going to use to connect to your server, **the client**, not the server itself, create an [Ed25519](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/) key: +1. From the computer you're going to use to connect to your server, **the client**, not the server itself, create an [Ed25519](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/) key with `ssh-keygen`: ``` bash ssh-keygen -t ed25519 ``` - - - Use the default options for all of the questions - - If you set a passphrase, you'll need to enter it every time you connect to your server using this key. -1. Now you need to **append** the contents of the public key `~/.ssh/id_ed25519.pub` to the `~/.ssh/authorized_keys` file on the **target server**. You'll want to do this in a secure way since the public key gives access to your server. One approach is to copy it to a USB stick and physically transfer it to the server. If you're sure there is nobody listening between the client you're on and your server, you can use `ssh-copy-id` to transfer and append the public key: + > ``` + > Generating public/private ed25519 key pair. + > Enter file in which to save the key (/home/user/.ssh/id_ed25519): + > Created directory '/home/user/.ssh'. + > Enter passphrase (empty for no passphrase): + > Enter same passphrase again: + > Your identification has been saved in /home/user/.ssh/id_ed25519. + > Your public key has been saved in /home/user/.ssh/id_ed25519.pub. + > The key fingerprint is: + > SHA256:F44D4dr2zoHqgj0i2iVIHQ32uk/Lx4P+raayEAQjlcs user@client + > The key's randomart image is: + > +--[ED25519 256]--+ + > |xxxx x | + > |o.o +. . | + > | o o oo . | + > |. E oo . o . | + > | o o. o S o | + > |... .. o o | + > |.+....+ o | + > |+.=++o.B.. | + > |+..=**=o=. | + > +----[SHA256]-----+ + > ``` + + **Note**: If you set a passphrase, you'll need to enter it every time you connect to your server using this key. + +1. When you SSH to your server, your server will look for your public key in the `.ssh/authorized_keys` file **in your home directory**. So we need to **append** the contents of the public key `~/.ssh/id_ed25519.pub` from the machine you're on (the client) to the `~/.ssh/authorized_keys` file on the **target server**. You'll want to do this in a secure way since the public key gives access to your server. One approach is to copy it to a USB stick and physically transfer it to the server. If you're sure there is [nobody listening between the client you're on and your server](https://en.wikipedia.org/wiki/Man-in-the-middle_attack), you can use `ssh-copy-id` to transfer and append the public key: ``` bash - ssh-copy-id user@server + ssh-copy-id user@server ``` + + > ``` + > /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub" + > The authenticity of host 'host (192.168.1.96)' can't be established. + > ECDSA key fingerprint is SHA256:QaDQb/X0XyVlogh87sDXE7MR8YIK7ko4wS5hXjRySJE. + > Are you sure you want to continue connecting (yes/no)? yes + > /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed + > /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys + > user@host's password: + > + > Number of key(s) added: 1 + > + > Now try logging into the machine, with: "ssh 'user@host'" + > and check to make sure that only the key(s) you wanted were added. + > ``` -Now would be a good time to [perform any tasks specific to your setup](#post-install). +Now would be a good time to [perform any tasks specific to your setup](#prepost-installation). ([Table of Contents](#table-of-contents)) @@ -294,15 +342,15 @@ Now would be a good time to [perform any tasks specific to your setup](#post-ins 1. Create a group: ``` bash - sudo groupadd sudo + sudo groupadd sudousers ``` 1. Add account(s) to the group: ``` bash - sudo usermod -a -G sudo user1 - sudo usermod -a -G sudo user2 - sudo usermod -a -G sudo ... + sudo usermod -a -G sudousers user1 + sudo usermod -a -G sudousers user2 + sudo usermod -a -G sudousers ... ``` You'll need to do this for every account on your server that needs `sudo` privileges. @@ -314,10 +362,10 @@ Now would be a good time to [perform any tasks specific to your setup](#post-ins sudo visudo ``` -1. Add this line if it is not already there: +1. Tell `sudo` to only allow users in the `sudousers` group to use `sudo` by **adding** this line if it is not already there: ``` - %sudo ALL=(ALL:ALL) ALL + %sudousers ALL=(ALL:ALL) ALL ``` ([Table of Contents](#table-of-contents)) @@ -328,7 +376,7 @@ Now would be a good time to [perform any tasks specific to your setup](#post-ins ##### Why -To make it easy to control who can SSH to the server. +To make it easy to control who can SSH to the server. By using a group, we can quickly add/remove accounts to the group to quickly allow or not allow SSH access to the server. ##### Goals @@ -383,18 +431,22 @@ SSH is a door into your server. This is especially true if you are opening ports - https://linux-audit.com/audit-and-harden-your-ssh-configuration/ - https://www.ssh.com/ssh/sshd_config/ - https://www.techbrown.com/harden-ssh-secure-linux-vps-server/ +- https://serverfault.com/questions/660160/openssh-difference-between-internal-sftp-and-sftp-server/660325 - `man sshd_config` ##### Steps -1. Make a backup of `/etc/ssh/sshd_config`: +1. Make a backup of `/etc/ssh/sshd_config` and remove default comments to make it eaiser to read: ``` bash sudo cp --preserve /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +"%Y%m%d%H%M%S") + sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_config ``` 1. Edit `/etc/ssh/sshd_config` then **find and edit or add** these settings that should apply regardless of your configuration/setup: + **Note**: Your `/etc/ssh/sshd_config` file may already have some of these settings/lines. You will want to remove those and replace them with the ones below. + ``` ######################################################################################################## # start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01 @@ -414,9 +466,6 @@ SSH is a door into your server. This is especially true if you are opening ports # LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. LogLevel VERBOSE - # Log sftp level file access (read/write/etc.) that would not be easily logged otherwise. - Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO - # Use kernel sandbox mechanisms where possible in unprivileged processes # Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere. UsePrivilegeSeparation sandbox @@ -424,7 +473,10 @@ SSH is a door into your server. This is especially true if you are opening ports ######################################################################################################## # end settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01 ######################################################################################################## - + + # Log sftp level file access (read/write/etc.) that would not be easily logged otherwise. + Subsystem sftp internal-sftp -f AUTHPRIV -l INFO + # only use the newer, more secure protocl Protocol 2 @@ -510,61 +562,6 @@ Per [Mozilla's OpenSSH guidelines for OpenSSH 6.7+](https://infosec.mozilla.org/ ([Table of Contents](#table-of-contents)) -### Force Accounts To Use Secure Passwords - -#### Why - -By default, accounts can use any password they want, including bad ones. [pwquality](https://linux.die.net/man/5/pwquality.conf)/[pam_pwquality](https://linux.die.net/man/8/pam_pwquality) addresses this security gap by providing "a way to configure the default password quality requirements for the system passwords" and checking "its strength against a system dictionary and a set of rules for identifying poor choices." - -#### Goal - -- enforced strong passwords - -#### Steps - -1. Install `libpam-pwquality`. - - For Debian based systems: - - ``` bash - sudo apt install libpam-pwquality - ``` - -1. Edit `/etc/pam.d/common-password` and **change** the line that starts like this: - - ``` - password requisite pam_pwquality.so - ``` - - to this: - - ``` - password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec - ``` - - The above options are: - - - `retry=3` = prompt user 3 times before returning with error. - - `minlen=10` = the minimum length of the password, factoring in any credits (or debits) from these: - - `dcredit=-1` = must have at least **one digit** - - `ucredit=-1` = must have at least **one upper case letter** - - `lcredit=-1` = must have at least **one lower case letter** - - `ocredit=-1` = must have at least **one non-alphanumeric character** - - `difok=3` = at least 3 characters from the new password cannot have been in the old password - - `maxrepeat=3` = allow a maximum of 3 repeated characters - - `gecoschec` = do not allow passwords with the account's name - - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - sudo cp --preserve /etc/pam.d/common-password /etc/pam.d/common-password.$(date +"%Y%m%d%H%M%S") - - sudo sed -i -r -e "s/^(password\s+requisite\s+pam_pwquality.so)(.*)$/# \1\2 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1 retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/pam.d/common-password - ``` - -([Table of Contents](#table-of-contents)) - ### NTP Client #### Why @@ -589,8 +586,136 @@ Many security protocols leverage the time. If your system time is incorrect, it sudo apt install ntp ``` -Check https://cloudpro.zone/index.php/2018/01/27/debian-9-3-server-setup-guide-part-4/ for instructions on how to check if its running. +1. Check `ntp`'s status: + ``` bash + sudo systemctl status ntp + ``` + + > ``` + > ● ntp.service - LSB: Start NTP daemon + > Loaded: loaded (/etc/init.d/ntp; generated; vendor preset: enabled) + > Active: active (running) since Sat 2019-02-16 00:32:20 EST; 3s ago + > Docs: man:systemd-sysv-generator(8) + > CGroup: /system.slice/ntp.service + > └─1051 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 109:114 + > + > Feb 16 00:32:20 host ntpd[1051]: Listen normally on 3 enp0s3 192.168.1.96:123 + > Feb 16 00:32:20 host ntpd[1051]: Listen normally on 4 lo [::1]:123 + > Feb 16 00:32:20 host ntpd[1051]: Listen normally on 5 enp0s3 [fe80::a00:27ff:feb6:ed8e%2]:123 + > Feb 16 00:32:20 host ntpd[1051]: Listening on routing socket on fd #22 for interface updates + > Feb 16 00:32:21 host ntpd[1051]: Soliciting pool server 173.255.206.154 + > Feb 16 00:32:22 host ntpd[1051]: Soliciting pool server 216.6.2.70 + > Feb 16 00:32:22 host ntpd[1051]: Soliciting pool server 82.197.188.130 + > Feb 16 00:32:23 host ntpd[1051]: Soliciting pool server 95.215.175.2 + > Feb 16 00:32:23 host ntpd[1051]: Soliciting pool server 107.155.79.108 + > Feb 16 00:32:23 host ntpd[1051]: Soliciting pool server 212.110.158.28 + > ``` + + ``` bash + sudo ntpq -p + ``` + + > ``` + > remote refid st t when poll reach delay offset jitter + > ============================================================================== + > 0.debian.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 + > 1.debian.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 + > 2.debian.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 + > 3.debian.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 + > -li216-154.membe 45.56.123.24 3 u 119 64 2 51.912 0.663 2.311 + > +eudyptula.init7 162.23.41.10 2 u 60 64 3 99.378 1.563 3.485 + > +107.155.79.108 129.7.1.66 2 u 119 64 2 49.171 -1.372 1.441 + > -212.110.158.28 89.109.251.21 2 u 120 64 2 167.465 -1.064 1.263 + > *ec2-54-242-183- 128.10.19.24 2 u 62 64 3 19.157 2.536 4.434 + > -69.195.159.158 128.252.19.1 2 u 119 64 2 42.990 6.302 3.507 + > -200.89.75.198 ( 200.27.106.115 2 u 58 64 3 160.786 42.737 12.827 + > ``` + + + +([Table of Contents](#table-of-contents)) + +### `[NS]` Configure Gmail as MTA + +#### Why + +Unless you're planning on setting up your own mail server, you'll need a way to send e-mails from your server. This will be important for system alerts/messages. + +#### Goals + +- `mail` configured to send e-mails from your server using [Gmail](https://mail.google.com/) + +#### References + +- https://php.quicoto.com/setup-exim4-to-use-gmail-in-ubuntu/ + +#### Steps + +1. Install `exim4`. + + On Debian based systems: + + ``` bash + sudo apt install exim4 + ``` + +1. Configure `exim4`: + + For Debian based systems: + ``` bash + sudo dpkg-reconfigure exim4-config + ``` + + You'll be prompted with some questions: + + |Prompt|Answer| + |--:|--| + |General type of mail configuration|`mail sent by smarthost; no local mail`| + |System mail name|(default)| + |IP-addresses to listen on for incoming SMTP connections|`127.0.0.1`| + |Other destinations for which mail is accepted|(default)| + |Visible domain name for local users|(default)| + |IP address or host name of the outgoing smarthost|`smtp.gmail.com::587`| + |Keep number of DNS-queries minimal (Dial-on-Demand)?|`No`| + |Split configuration into small files?|`No`| + +1. Make a backup of `/etc/exim4/passwd.client`: + + ``` bash + sudo cp /etc/exim4/passwd.client /etc/exim4/passwd.client.$(date +"%Y%m%d%H%M%S") + ``` + +1. **Add** a line like this to `/etc/exim4/passwd.client` + + ``` + *.google.com:yourAccount@gmail.com:yourPassword + ``` + + Replace `yourAccount@gmail.com` and `yourPassword` with your details. If you have 2FA/MFA enabled on your Gmail then you'll need to create and use an app password. + +1. This file has your Gmail password so we need to lock it down: + + ``` bash + sudo chown root:Debian-exim /etc/exim4/passwd.client + sudo chmod 640 /etc/exim4/passwd.client + ``` + +1. Restart `exim4`: + + ``` bash + sudo service exim4 restart + ``` + +1. Add some mail aliases so we can send e-mails to local accounts by **adding** lines like this to `/etc/aliases`: + + ``` + user1: user1@gmail.com + user2: user2@gmail.com + ... + ``` + + You'll need to add all the local accounts that exist on your server. ([Table of Contents](#table-of-contents)) @@ -602,9 +727,9 @@ Call me paranoid, and you don't have to agree, but I want to deny all traffic in Of course, if you disagree, that is totally fine and can configure UFW to suit your needs. -Either way, ensuring that only traffic we explicitly allow is the job of a firewall. On Linux, the most common firewall is [iptables](https://en.wikipedia.org/wiki/Iptables). iptables, however, is rather complicated and confusing (IMHO). This is where UFW comes in. UFW simplifies the process of creating and managing iptables rules. +Either way, ensuring that only traffic we explicitly allow is the job of a firewall. On Linux, the most common firewall is [`iptables`](https://en.wikipedia.org/wiki/Iptables). `iptables`, however, is rather complicated and confusing (IMHO). This is where UFW comes in. UFW simplifies the process of creating and managing `iptables` rules. -UFW works by letting you configure rules that: +**UFW** works by letting you configure rules that: - **allow** or **deny** - **input** or **output** traffic @@ -628,7 +753,7 @@ You can create rules by explicitly specifying the ports or with application conf 1. Install `ufw`. - For Debian based systems: + On Debian based systems: ``` bash sudo apt install ufw @@ -640,6 +765,11 @@ You can create rules by explicitly specifying the ports or with application conf sudo ufw default deny outgoing comment 'deny all outgoing traffic' ``` + > ``` + > Default outgoing policy changed to 'deny' + > (be sure to update your rules accordingly) + > ``` + If you are not as paranoid as me, and don't want to deny all outgoing traffic, you can allow it instead: ``` bash @@ -658,6 +788,11 @@ You can create rules by explicitly specifying the ports or with application conf sudo ufw limit in ssh comment 'allow SSH connections in' ``` + > ``` + > Rules updated + > Rules updated (v6) + > ``` + 1. Allow additional traffic as per your needs. Some common use-cases: ``` bash @@ -680,6 +815,7 @@ You can create rules by explicitly specifying the ports or with application conf sudo ufw allow out whois comment 'allow whois' # allow traffic out on port 68 -- the DHCP client + # you only need this if you're using DHCP sudo ufw allow out 68 comment 'allow the DHCP client to update' ``` @@ -688,16 +824,75 @@ You can create rules by explicitly specifying the ports or with application conf ``` bash sudo ufw enable ``` + + > ``` + > Command may disrupt existing ssh connections. Proceed with operation (y|n)? y + > Firewall is active and enabled on system startup + > ``` 1. If you want to see a status: ``` bash sudo ufw status ``` + + > ``` + > Status: active + > + > To Action From + > -- ------ ---- + > 22/tcp LIMIT Anywhere # allow SSH connections in + > 22/tcp (v6) LIMIT Anywhere (v6) # allow SSH connections in + > + > 53 ALLOW OUT Anywhere # allow DNS calls out + > 123 ALLOW OUT Anywhere # allow NTP out + > 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out + > 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out + > 21/tcp ALLOW OUT Anywhere # allow FTP traffic out + > Mail submission ALLOW OUT Anywhere # allow mail out + > 43/tcp ALLOW OUT Anywhere # allow whois + > 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out + > 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out + > 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out + > 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out + > 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out + > Mail submission (v6) ALLOW OUT Anywhere (v6) # allow mail out + > 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois + > ``` + or + ``` bash sudo ufw status verbose ``` + + > ``` + > Status: active + > Logging: on (low) + > Default: deny (incoming), deny (outgoing), disabled (routed) + > New profiles: skip + > + > To Action From + > -- ------ ---- + > 22/tcp LIMIT IN Anywhere # allow SSH connections in + > 22/tcp (v6) LIMIT IN Anywhere (v6) # allow SSH connections in + > + > 53 ALLOW OUT Anywhere # allow DNS calls out + > 123 ALLOW OUT Anywhere # allow NTP out + > 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out + > 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out + > 21/tcp ALLOW OUT Anywhere # allow FTP traffic out + > 587/tcp (Mail submission) ALLOW OUT Anywhere # allow mail out + > 43/tcp ALLOW OUT Anywhere # allow whois + > 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out + > 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out + > 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out + > 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out + > 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out + > 587/tcp (Mail submission (v6)) ALLOW OUT Anywhere (v6) # allow mail out + > 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois + > ``` + #### Default Applications @@ -707,23 +902,67 @@ You can create rules by explicitly specifying the ports or with application conf sudo ufw app list ``` +> ``` +> Available applications: +> AIM +> Bonjour +> CIFS +> DNS +> Deluge +> IMAP +> IMAPS +> IPP +> KTorrent +> Kerberos Admin +> Kerberos Full +> Kerberos KDC +> Kerberos Password +> LDAP +> LDAPS +> LPD +> MSN +> MSN SSL +> Mail submission +> NFS +> OpenSSH +> POP3 +> POP3S +> PeopleNearby +> SMTP +> SSH +> Socks +> Telnet +> Transmission +> Transparent Proxy +> VNC +> WWW +> WWW Cache +> WWW Full +> WWW Secure +> XMPP +> Yahoo +> qBittorrent +> svnserve +> ``` + To get details about the app, like which ports it includes, type: ``` bash sudo ufw app info [app name] ``` -For example: - -``` bash -$ sudo ufw app info DNS -Profile: DNS -Title: Internet Domain Name Server -Description: Internet Domain Name Server - -Port: - 53 -``` +> ``` bash +> sudo ufw app info DNS +> ``` +> +> ``` +> Profile: DNS +> Title: Internet Domain Name Server +> Description: Internet Domain Name Server +> +> Port: +> 53 +> ``` #### Custom Application @@ -732,13 +971,16 @@ If you don't want to create rules by explicitly providing the port number(s), yo For example, here is what you would use for [Plex](https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/): ``` bash -$ cat /etc/ufw/applications.d/plexmediaserver -[PlexMediaServer] -title=Plex Media Server -description=This opens up PlexMediaServer for http (32400), upnp, and autodiscovery. -ports=32469/tcp|32413/udp|1900/udp|32400/tcp|32412/udp|32410/udp|32414/udp|32400/udp +cat /etc/ufw/applications.d/plexmediaserver ``` +> ``` +> [PlexMediaServer] +> title=Plex Media Server +> description=This opens up PlexMediaServer for http (32400), upnp, and autodiscovery. +> ports=32469/tcp|32413/udp|1900/udp|32400/tcp|32412/udp|32410/udp|32414/udp|32400/udp +> ``` + Then you can enable it like any other app: ```bash @@ -747,25 +989,234 @@ sudo ufw allow plexmediaserver ([Table of Contents](#table-of-contents)) -### PSAD (WIP) +### PSAD: `iptables` Intrusion Detection And Prevention + +#### Why + +I can't explain it any better than user [FINESEC](https://serverfault.com/users/143961/finesec) from https://serverfault.com/ did at: https://serverfault.com/a/447604/289829. + +> Fail2BAN scans log files of various applications such as apache, ssh or ftp and automatically bans IPs that show the malicious signs such as automated login attempts. PSAD on the other hand scans iptables and ip6tables log messages (typically /var/log/messages) to detect and optionally block scans and other types of suspect traffic such as DDoS or OS fingerprinting attempts. It's ok to use both programs at the same time because they operate on different level. + +And, since we're already using [UFW](#ufw-uncomplicated-firewall) so we'll follow the awesome instructions by [netson](https://gist.github.com/netson) at https://gist.github.com/netson/c45b2dc4e835761fbccc to make PSAD work with UFW. #### References - http://www.cipherdyne.org/psad/ +- http://www.cipherdyne.org/psad/docs/config.html - https://www.thefanclub.co.za/how-to/how-install-psad-intrusion-detection-ubuntu-1204-lts-server -- https://serverfault.com/questions/447578/do-we-need-psad-if-we-already-have-fail2ban#447604 -- https://serverfault.com/questions/421087/how-to-set-iptables-log-rules-for-psad-with-ufw -- https://gist.github.com/netson/c45b2dc4e835761fbccc +- https://serverfault.com/a/447604/289829 +- https://serverfault.com/a/770424/289829 +- https://gist.github.com/netson/c45b2dc4e835761fbccc- + +#### Steps + +1. Install `psad`. + + On Debian based systems: + + ``` bash + sudo apt install psad + ``` + +1. Make a backup of `/etc/psad/psad.conf`: + + ``` bash + sudo cp /etc/psad/psad.conf /etc/psad/psad.conf.$(date +"%Y%m%d%H%M%S") + ``` + +1. Review and update configuration options in `/etc/psad/psad.conf`. Pay special attention to these: + + |Setting|Set To + |--|--| + |[`EMAIL_ADDRESSES`](http://www.cipherdyne.org/psad/docs/config.html#EMAIL_ADDRESSES)|your email address(s)| + |`HOSTNAME`|your server's hostname| + |[`ENABLE_AUTO_IDS`](http://www.cipherdyne.org/psad/docs/config.html#ENABLE_AUTO_IDS)|`ENABLE_AUTO_IDS Y;`| + |`ENABLE_AUTO_IDS_EMAILS`|`ENABLE_AUTO_IDS_EMAILS Y;`| + |`EXPECT_TCP_OPTIONS`|`EXPECT_TCP_OPTIONS Y;`| + + Check the configuration file `psad`'s documentation at http://www.cipherdyne.org/psad/docs/config.html for more details. + +1. Now we need to make some changes to `ufw` so it works with `psad` by telling `ufw` to log all traffic so `psad` can analyze it. Do this by editing **two files** and **adding** these lines **at the end but before the COMMIT line**. + + Make backups: + + ``` bash + sudo cp /etc/ufw/before.rules /etc/ufw/before.rules.$(date +"%Y%m%d%H%M%S") + sudo cp /etc/ufw/before6.rules /etc/ufw/before6.rules.$(date +"%Y%m%d%H%M%S") + ``` + + Edit the files: + + - `/etc/ufw/before.rules` + - `/etc/ufw/before6.rules` + + And add **add** this **at the end but before the COMMIT line**: + + ``` + # log all traffic so psad can analyze + -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] " + -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] " + ``` + + **Note**: We're adding a log prefix to all the `iptables` logs. We'll need this for [seperating `iptables` logs to their own file](#ns-separate-iptables-log-file). + + For example: + + > ``` + > ... + > + > # log all traffic so psad can analyze + > -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] " + > -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] " + > + > # don't delete the 'COMMIT' line or these rules won't be processed + > COMMIT + > ``` + + +1. Now we need to reload/restart `ufw` and `psad` for the changes to take effect: + + ``` bash + sudo ufw reload + + sudo psad -R + sudo psad --sig-update + sudo psad -H + ``` + +1. Analyze `iptables` rules for errors: + + ``` bash + sudo psad --fw-analyze + ``` + + > ``` + > [+] Parsing INPUT chain rules. + > [+] Parsing INPUT chain rules. + > [+] Firewall config looks good. + > [+] Completed check of firewall ruleset. + > [+] Results in /var/log/psad/fw_check + > [+] Exiting. + > ``` + + **Note**: If there were any issues you will get an e-mail with the error. + +1. Check the status of `psad`: + + ``` bash + sudo psad --Status + ``` + + > ``` + > [-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on vm + > [+] psad_fw_read (pid: 3444) %CPU: 0.0 %MEM: 2.2 + > Running since: Sat Feb 16 01:03:09 2019 + > + > [+] psad (pid: 3435) %CPU: 0.2 %MEM: 2.7 + > Running since: Sat Feb 16 01:03:09 2019 + > Command line arguments: [none specified] + > Alert email address(es): root@localhost + > + > [+] Version: psad v2.4.3 + > + > [+] Top 50 signature matches: + > [NONE] + > + > [+] Top 25 attackers: + > [NONE] + > + > [+] Top 20 scanned ports: + > [NONE] + > + > [+] iptables log prefix counters: + > [NONE] + > + > Total protocol packet counters: + > + > [+] IP Status Detail: + > [NONE] + > + > Total scan sources: 0 + > Total scan destinations: 0 + > + > [+] These results are available in: /var/log/psad/status.out + > ``` ([Table of Contents](#table-of-contents)) -### Fail2ban: Intrusion Detection And Prevention +### `[NS]` Separate `iptables` Log File + +#### Why + +There will come a time when you'll need to look through your `iptables` logs. Having all the `iptables` logs go to their own file will make it a lot easier to find what you're looking for. + +#### References + +- https://blog.shadypixel.com/log-iptables-messages-to-a-separate-file-with-rsyslog/ +- https://gist.github.com/netson/c45b2dc4e835761fbccc +- https://www.rsyslog.com/doc/v8-stable/configuration/actions.html + +#### Steps + +1. The first step is by telling your firewall to prefix all log entries with some unique string. If you're using `iptables` directly, you would do something like `--log-prefix "[IPTABLES] "` for all the rules. We took care of this in step [step 4 of installing `psad`](#psad_step4). + +1. After you've added a prefix to the firewall logs, we need to tell `rsyslog` to send those lines to its own file. Do this by **creating** the file `/etc/rsyslog.d/10-iptables.conf` and **adding** this: + + ``` + :msg, contains, "[IPTABLES] " /var/log/iptables.log + & stop + ``` + + If you're expecting a lot if data being logged by your firewall, prefix the filename with a `-` ["to omit syncing the file after every logging"](https://www.rsyslog.com/doc/v8-stable/configuration/actions.html#regular-file). For example: + + ``` + :msg, contains, "[IPTABLES] " -/var/log/iptables.log + & stop + ``` + + **Note**: Remember to change the prefix to whatever you use. + +1. Since we're logging firewall messages to a different file, we need to tell `psad` where the new file is. Edit `/etc/psad/psad.conf` and set `IPT_SYSLOG_FILE` to the path of the log file. For example: + + ``` + IPT_SYSLOG_FILE /var/log/iptables.log; + ``` + +1. Restart `psad` and `rsyslog` to activate the changes (or reboot): + + ``` bash + sudo psad -R + sudo psad --sig-update + sudo psad -H + sudo service rsyslog restart + ``` + +1. The last thing we have to do is tell `logrotate` to rotate the new log file so it doesn't get to big and fill up our disk. **Create** the file `/etc/logrotate.d/iptables` and **add** this: + + ``` + /var/log/iptables.log + { + rotate 7 + daily + missingok + notifempty + delaycompress + compress + postrotate + invoke-rc.d rsyslog rotate > /dev/null + endscript + } + ``` + +([Table of Contents](#table-of-contents)) + +### Fail2ban: Application Intrusion Detection And Prevention #### Why A firewall will board up all the doors and windows you don't want anyone using so nobody can see they are even there. But what about the doors and windows you want visible so approved folks can use them? Even if the door is locked, how do you ensure that someone doesn't try to force their way in? -That is where Fail2ban comes in. It will monitor network traffic/logs and prevent intrusions by blocking suspicious activity (e.g. multiple successive failed connections in a short time-span). +That is where **Fail2ban** comes in. It will monitor network traffic/logs and prevent intrusions by blocking suspicious activity (e.g. multiple successive failed connections in a short time-span). #### Goal @@ -779,12 +1230,15 @@ That is where Fail2ban comes in. It will monitor network traffic/logs and preven #### References - https://www.fail2ban.org/ +- https://blog.vigilcode.com/2011/05/ufw-with-fail2ban-quick-secure-setup-part-ii/ +- https://dodwell.us/security/ufw-fail2ban-portscan.html +- https://www.howtoforge.com/community/threads/fail2ban-and-ufw-on-debian.77261/ #### Steps 1. Install `fail2ban`. - For Debian based systems: + On Debian based systems: ``` bash sudo apt install fail2ban @@ -796,31 +1250,36 @@ That is where Fail2ban comes in. It will monitor network traffic/logs and preven [DEFAULT] # the IP address range we want to ignore ignoreip = 127.0.0.1/8 [LAN SEGMENT] - + # who to send e-mail to destemail = [your e-mail] - + # who is the email from sender = [your e-mail] - + # since we're using exim4 to send emails mta = mail - + # get email alerts action = %(action_mwl)s ``` - Note: Your server will need to be able to send e-mails so Fail2ban an let you know of suspicious activity and when it banned an IP. + Note: Your server will need to be able to send e-mails so Fail2ban can let you know of suspicious activity and when it banned an IP. -1. Create a jail for `ssh` by **adding** this to `/etc/fail2ban/jail.d/ssh.local`: +1. We need to create a jail for `ssh` that tells `fail2ban` to look at `ssh` logs and use `ufw` to ban/unban IPs as needed. Create a jail for `ssh` by **adding** this to `/etc/fail2ban/jail.d/ssh.local`: ``` [sshd] enabled = true + banaction = ufw port = ssh + filter = sshd logpath = %(sshd_log)s maxretry = 5 ``` + +1. In the above we tell `fail2ban` to use the `ufw` as the `banaction`. Fail2ban ships with an action configuration file for `ufw`. You can see it in `/etc/fail2ban/action.d/ufw.conf` + 1. Enable `fail2ban` and the jail for SSH: ``` bash @@ -833,198 +1292,53 @@ That is where Fail2ban comes in. It will monitor network traffic/logs and preven ``` bash sudo fail2ban-client status + ``` + + > ``` + > Status + > |- Number of jail: 1 + > `- Jail list: sshd + > ``` + + ``` bash sudo fail2ban-client status sshd ``` + + > ``` + > Status for the jail: sshd + > |- Filter + > | |- Currently failed: 0 + > | |- Total failed: 0 + > | `- File list: /var/log/auth.log + > `- Actions + > |- Currently banned: 0 + > |- Total banned: 0 + > `- Banned IP list: + > ``` #### Custom Jails -WIP +I have not needed to create a custom jail yet. Once I do, and I figure out how, I will update this guide. Or, if you know how please help [contribute](#contributing). + +#### Unban an IP + +To unban an IP use this command: + +``` bash +fail2ban-client set [jail] unbanip [IP] +``` + +`[jail]` is the name of the jail that has the banned IP and `[IP]` is the IP address you want to unban. For example, to unaban `192.168.1.100` from SSH you would do: + +``` bash +fail2ban-client set sshd unbanip 192.168.1.100 +``` ([Table of Contents](#table-of-contents)) -### 2FA/MFA for SSH +### `[DZ]` Linux Kernel `sysctl` Hardening -#### Why - -Even though SSH is a pretty good security guard for your doors and windows, it is still a visible door that bad-actors can see and try to brute-force in. [Fail2ban](#fail2ban-intrusion-detection-and-prevention) will monitor for these brute-force attempts but there is no such thing as being too secure. - -Using Two Factor Authentication (2FA) / Multi Factor Authentication (MFA) requires anyone entering to have **two** keys to enter which makes it harder for bad actors. The two keys are: - -1. Their password -1. A 6 digit token that changes every 30 seconds - -Without both keys, they won't be able to get in. - -#### Why Not - -Many folks might find the experience cumbersome or annoying. And, acesss to your system is dependent on the accompanying authenticator app that generates the code. - -#### Goals - -- 2FA/MFA enabled for all SSH connections - -#### Notes - -- Before you do this, you should have an idea of how 2FA/MFA works and you'll need an authenticator app on your phone to continue. -- We'll use [google-authenticator-libpam](https://github.com/google/google-authenticator-libpam). -- With the below configuration, a user will only need to enter their 2FA/MFA code if they are logging on with their password but not **not** if they are using [SSH public/private keys](#ssh-publicprivate-keys). Check the documentation on how to change this behavior to suite your requirements. - -#### References - -- https://github.com/google/google-authenticator-libpam - -#### Steps - -1. Install it `libpam-google-authenticator`. - - For Debian based systems: - - ``` bash - sudo apt install libpam-google-authenticator - ``` - -1. **Make sure you're logged in as the ID you want to enable 2FA/MFA for** and **execute** `google-authenticator`: - - ``` bash - google-authenticator - ``` - - Notice this is **not run as root**. - - Select default option (y in most cases) for all the questions it asks and remember to save the emergency scratch codes. - -1. Now we need to enable it as an authentication method for SSH by **adding** this line to `/etc/pam.d/sshd`: - - ``` - auth required pam_google_authenticator.so nullok - ``` - - Check [here](https://github.com/google/google-authenticator-libpam/blob/master/README.md#nullok) for what `nullok` means. - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - sudo cp --preserve /etc/pam.d/sshd /etc/pam.d/sshd.$(date +"%Y%m%d%H%M%S") - - echo -e "\nauth required pam_google_authenticator.so nullok # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/pam.d/sshd - ``` - -1. Enable it in the SSH settings by **adding** this line in `/etc/ssh/sshd_config`: - - ``` - ChallengeResponseAuthentication yes - ``` - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - sudo cp --preserve /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +"%Y%m%d%H%M%S") - - echo -e "\nChallengeResponseAuthentication yes # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ssh/sshd_config - ``` - -1. Restart `ssh`: - - ``` bash - sudo service sshd restart - ``` - -([Table of Contents](#table-of-contents)) - -### Apticron - Automatic Update Notifier - -#### Why - -It is important to keep your server up-to-date with all security patches. Otherwise you're at risk of known security vulnerabilities that bad-actors could use to gain unauthorized access to your server. - -You have two options: - -- Configure your server for unattended updates -- Be notified when updates are available - -Which option you pick is up to you but I prefer being notified by e-mail when updates are available. This is because an update may break something else. If the server updates it-self then I may not know and, if I do find out, I'll have to scramble to fix it. If it e-mails me when updates are available, then I can do the updates at my schedule. - -#### Notes - -- Your server will need a way to send e-mails for this to work - -#### References - -- https://wiki.debian.org/UnattendedUpgrades#apt-listchanges -- https://www.cyberciti.biz/faq/apt-get-apticron-send-email-upgrades-available/ -- https://www.unixmen.com/how-to-get-email-notifications-for-new-updates-on-debianubuntu/ - -#### Steps - -1. Install `apticron`. - - For Debian based systems: - - ``` bash - sudo apt install apticron - ``` -1. Set the value of `EMAIL` in `/etc/apticron/apticron.conf` to your e-mail address. - -([Table of Contents](#table-of-contents)) - -### Orphaned Software - -#### Why - -As you use your system, and you install and uninstall software, you'll eventually end up with orphaned, or unused software/packages/libraries. You don't need to remove them, but if you don't need them, why keep them? When security is a priority, anything not explicitly needed is a potential security threat. You want to keep your server as trimmed and lean as possible. - -#### Notes - -- Each distribution manages software/packages/libraries differently so how you find and remove orphaned packages will be different. -- So far I only have steps for Debian; I will add for other distributions as I learn how. - -#### Steps - -##### Debian - -For Debian based distributions, you can use [deborphan](http://freshmeat.sourceforge.net/projects/deborphan/) to find orphaned packages. - -1. Install `deborphan`: - - ``` bash - sudo apt install deborphan - ``` - -1. Run `deborphan` as **root** to see a list of orphaned packages: - - ``` bash - sudo deborphan - ``` - -1. Pass it's output to `apt` to remove them: - - ``` bash - sudo apt --autoremove purge $(deborphan) - ``` - - You will want to repeatedly run this command until `deborphan` no longer returns any orphaned packages. - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - while [[ $(deborphan | wc -l) != 0 ]] ; do - sudo apt --autoremove purge $(deborphan) - done - ``` - -([Table of Contents](#table-of-contents)) - -## Securing Linux - DANGER ZONE - -### Section Overivew - -This section covers things that are either high risk because there is a possibility they can make your system unusable, or are considered unnecessary by many because the risks outweigh any rewards. - -**!! PROCEED WITH CAUTION !!** - -([Table of Contents](#table-of-contents)) - -### Linux Kernel `sysctl` Hardening +
!! PROCEED AT YOUR OWN RISK !! #### Why @@ -1042,7 +1356,7 @@ In fact, since I am not 100% sure exactly what each setting does, I took recomme If you have a better understanding of what these settings do, or have any other feedback/advice on them, please [let me know](#contacting-me). -I won't provide [For the lazy](#Editing-Configuration-Files---For-The-Lazy) code in this section. +I won't provide [For the lazy](#editing-configuration-files---for-the-lazy) code in this section. #### Notes @@ -1094,13 +1408,170 @@ I won't provide [For the lazy](#Editing-Configuration-Files---For-The-Lazy) code **Note**: If `sysctl` has trouble writing any settings then `sysctl -w` or `sysctl -p` will write an error to `stderr`. You can use this to quickly find invalid settings in your `/etc/sysctl.conf` file: - ``` bash - sudo sysctl -p >/dev/null - ``` +``` bash +sudo sysctl -p >/dev/null +``` + +
([Table of Contents](#table-of-contents)) -### Change Default `umask` +### `[DZ]` Password Protect GRUB + +
!! PROCEED AT YOUR OWN RISK !! + +#### Why + +If a bad actor has physical access to your server, they could use GRUB to gain unauthorized access to your system. + +#### Why Not + +If you forget the password, you'll have to go through [some work](https://www.cyberciti.biz/tips/howto-recovering-grub-boot-loader-password.html) to recover the password. + +#### Goals + +- auto boot the default Debian install and require a password for anything else + +#### Notes + +- This will only protect GRUB and anything behind it like your operating systems. Check your motherboard's documentation for password protecting your BIOS to prevent a bad actor from circumventing GRUB. + +#### References + +- https://selivan.github.io/2017/12/21/grub2-password-for-all-but-default-menu-entries.html +- https://help.ubuntu.com/community/Grub2/Passwords +- https://computingforgeeks.com/how-to-protect-grub-with-password-on-debian-ubuntu-and-kali-linux/ +- `man grub` +- `man grub-mkpasswd-pbkdf2` + +#### Steps + +1. Create a [Password-Based Key Derivation Function 2 (PBKDF2)](https://en.wikipedia.org/wiki/PBKDF2) hash of your password: + + ``` bash + grub-mkpasswd-pbkdf2 -c 100000 + ``` + + The below output is from using `password` as the password: + + > ``` + > Enter password: + > Reenter password: + > PBKDF2 hash of your password is grub.pbkdf2.sha512.100000.2812C233DFC899EFC3D5991D8CA74068C99D6D786A54F603E9A1EFE7BAEDDB6AA89672F92589FAF98DB9364143E7A1156C9936328971A02A483A84C3D028C4FF.C255442F9C98E1F3C500C373FE195DCF16C56EEBDC55ABDD332DD36A92865FA8FC4C90433757D743776AB186BD3AE5580F63EF445472CC1D151FA03906D08A6D + > ``` + +1. Copy everything **after** `PBKDF2 hash of your password is `, **starting from and including** `grub.pbkdf2.sha512...` to the end. You'll need this in the next step. + +1. The `update-grub` program uses scripts to generate configuration files it will use for GRUB's settings. Create the file `/etc/grub.d/01_password` and **add** the below code after replacing `[hash]` with the hash you copied from the first step. This tells `update-grub` to use this username and password for GRUB. + + ``` bash + #!/bin/sh + set -e + + cat << EOF + set superusers="grub" + password_pbkdf2 grub [hash] + EOF + ``` + + For example: + + > ``` bash + > #!/bin/sh + > set -e + > + > cat << EOF + > set superusers="grub" + > password_pbkdf2 grub grub.pbkdf2.sha512.100000.2812C233DFC899EFC3D5991D8CA74068C99D6D786A54F603E9A1EFE7BAEDDB6AA89672F92589FAF98DB9364143E7A1156C9936328971A02A483A84C3D028C4FF.C255442F9C98E1F3C500C373FE195DCF16C56EEBDC55ABDD332DD36A92865FA8FC4C90433757D743776AB186BD3AE5580F63EF445472CC1D151FA03906D08A6D + > EOF + > ``` + +1. Set the file's execute bit so `update-grub` includes it when it updates GRUB's configuration: + + ``` bash + sudo chmod a+x /etc/grub.d/01_password + ``` + +1. Make a backup of `/etc/grub.d/10_linux` and unset execute bit so `update-grub` doesn't try to run it: + + ``` bash + sudo cp --preserve /etc/grub.d/10_linux /etc/grub.d/10_linux.$(date +"%Y%m%d%H%M%S") + sudo chmod a-x /etc/grub.d/10_linux.* + ``` + +1. To make the default Debian install unrestricted (**without** the password) while keeping everything else restricted (**with** the password) modify `/etc/grub.d/10_linux` and **add** `--unrestricted` to the `CLASS` variable. + + [For the lazy](#editing-configuration-files---for-the-lazy): + + ``` bash + sudo sed -i -r -e "/^CLASS=/ a CLASS=\"\${CLASS} --unrestricted\" # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" /etc/grub.d/10_linux + ``` + +1. Update GRUB with `update-grub`: + + ``` bash + sudo update-grub + ``` + +
+ +([Table of Contents](#table-of-contents)) + +### `[DZ]` Disable Root Login + +
!! PROCEED AT YOUR OWN RISK !! + +#### Why + +If you have `sudo` [configured properly](#limit-who-can-use-sudo), then the **root** account will mostly never need to log in directly -- either at the terminal or remotely. + +#### Why Not + +**Be warned, this can cause issues with some configurations!** + +If your installation uses [`sulogin`](https://linux.die.net/man/8/sulogin) (like Debian) to drop to a **root** console during boot failures, then locking the **root** account will prevent `sulogin` from opening the **root** shell and you will get this error: + + Cannot open access to console, the root account is locked. + + See sulogin(8) man page for more details. + + Press Enter to continue. + +To work around this, you can use the `--force` option for `sulogin`. Some distributions already include this, or some other, workaround. + +An alternative to locking the **root** acount is set a long/complicated **root** password and store it in a secured, non digital format. That way you have it when/if you need it. + +#### Goal + +- locked **root** account that nobody can use to log in as **root** + +#### Notes + +- Some distributions disable **root** login by default (e.g. Ubuntu) so you may not need to do this step. Check with your distribution's documentation. + +#### References + +- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=806852 +- https://github.com/systemd/systemd/issues/7115 +- https://github.com/karelzak/util-linux/commit/7ff1162e67164cb4ece19dd809c26272461aa254 +- https://github.com/systemd/systemd/issues/11596 +- `man systemd` + +#### Steps + +1. Lock the **root** account: + + ``` bash + sudo passwd -l root + ``` + +
+ +([Table of Contents](#table-of-contents)) + +### `[DZ]` Change Default `umask` + +
!! PROCEED AT YOUR OWN RISK !! #### Why @@ -1139,7 +1610,7 @@ Changing the default `umask` can create unexpected problems. For example, if you umask 0027 ``` - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): + [For the lazy](#editing-configuration-files---for-the-lazy): ``` bash sudo cp --preserve /etc/profile /etc/profile.$(date +"%Y%m%d%H%M%S") @@ -1154,7 +1625,7 @@ Changing the default `umask` can create unexpected problems. For example, if you UMASK 0027 ``` - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): + [For the lazy](#editing-configuration-files---for-the-lazy): ``` bash sudo cp --preserve /etc/login.defs /etc/login.defs.$(date +"%Y%m%d%H%M%S") @@ -1162,13 +1633,13 @@ Changing the default `umask` can create unexpected problems. For example, if you echo -e "\nUMASK 0027 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/login.defs ``` -1. [**!! USE WITH CAUTION !!**](#umask-root) -- Set default `umask` for the **root** account to **0077** by **adding** this line to `/root/.bashrc`: +1. Set default `umask` for the **root** account to **0077** by **adding** this line to `/root/.bashrc`: ``` umask 0077 ``` - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): + [For the lazy](#editing-configuration-files---for-the-lazy): ``` bash sudo cp --preserve /root/.bashrc /root/.bashrc.$(date +"%Y%m%d%H%M%S") @@ -1176,229 +1647,276 @@ Changing the default `umask` can create unexpected problems. For example, if you echo -e "\numask 0077 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /root/.bashrc ``` -([Table of Contents](#table-of-contents)) - -### Password Protect GRUB - -#### Why - -If a bad actor has physical access to your server, they could use GRUB to gain unauthorized access to your system. - -#### Why Not - -If you forget the password, you'll have to go through [some work](https://www.cyberciti.biz/tips/howto-recovering-grub-boot-loader-password.html) to recover the password. - -#### Goals - -- auto boot the default Debian install and require a password for anything else - -#### Notes - -- This will only protect GRUB and anything behind it like your operating systems. Check your motherboard's documentation for password protecting your BIOS to prevent a bad actor from circumventing GRUB. - -#### References - -- https://selivan.github.io/2017/12/21/grub2-password-for-all-but-default-menu-entries.html -- https://help.ubuntu.com/community/Grub2/Passwords -- https://computingforgeeks.com/how-to-protect-grub-with-password-on-debian-ubuntu-and-kali-linux/ -- `man grub` -- `man grub-mkpasswd-pbkdf2` - -#### Steps - -1. Create a [Password-Based Key Derivation Function 2 (PBKDF2)](https://en.wikipedia.org/wiki/PBKDF2) hash of your password: - - ``` bash - grub-mkpasswd-pbkdf2 -c 100000 - ``` - - The below output is from using `password` as the password: - - ``` - Enter password: - Reenter password: - PBKDF2 hash of your password is grub.pbkdf2.sha512.100000.2812C233DFC899EFC3D5991D8CA74068C99D6D786A54F603E9A1EFE7BAEDDB6AA89672F92589FAF98DB9364143E7A1156C9936328971A02A483A84C3D028C4FF.C255442F9C98E1F3C500C373FE195DCF16C56EEBDC55ABDD332DD36A92865FA8FC4C90433757D743776AB186BD3AE5580F63EF445472CC1D151FA03906D08A6D - ``` - -1. Copy everything **after** `PBKDF2 hash of your password is `, **starting from and including** `grub.pbkdf2.sha512...` to the end. You'll need this in the next step. - -1. Create the file `/etc/grub.d/01_password` and **add** the below code after replacing `[hash]` with the hash you copied from the first step: - - ``` bash - #!/bin/sh - set -e - - cat << EOF - set superusers="grub" - password_pbkdf2 grub [hash] - EOF - ``` - - For example: - - ``` bash - #!/bin/sh - set -e - - cat << EOF - set superusers="grub" - password_pbkdf2 grub grub.pbkdf2.sha512.100000.2812C233DFC899EFC3D5991D8CA74068C99D6D786A54F603E9A1EFE7BAEDDB6AA89672F92589FAF98DB9364143E7A1156C9936328971A02A483A84C3D028C4FF.C255442F9C98E1F3C500C373FE195DCF16C56EEBDC55ABDD332DD36A92865FA8FC4C90433757D743776AB186BD3AE5580F63EF445472CC1D151FA03906D08A6D - EOF - ``` - -1. Set the file's execute bit so `update-grub` includes it when it updates GRUB's configuration: - - ``` bash - sudo chmod a+x /etc/grub.d/01_password - ``` - -1. Make a backup of `/etc/grub.d/10_linux` and unset execute bit so `update-grub` doesn't try to run it: - - ``` bash - sudo cp --preserve /etc/grub.d/10_linux /etc/grub.d/10_linux.$(date +"%Y%m%d%H%M%S") - sudo chmod a-x /etc/grub.d/10_linux.* - ``` - -1. To make the default Debian install unrestricted (**without** the password) while keeping everything else restricted (**with** the password) modify `/etc/grub.d/10_linux` and **add** `--unrestricted` to the `CLASS` variable. - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - sudo sed -i -r -e "/^CLASS=/ a CLASS=\"\${CLASS} --unrestricted\" # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" /etc/grub.d/10_linux - ``` - -1. Update GRUB with `update-grub`: - - ``` bash - sudo update-grub - ``` +
([Table of Contents](#table-of-contents)) -### Disable Root Login +### Force Accounts To Use Secure Passwords #### Why -If you have `sudo` [configured properly](#limit-who-can-use-sudo), then the **root** account will mostly never need to log in directly -- either at the terminal or remotely. - -#### Why Not - -**Be warned, this can cause issues with some configurations!** - -If your installation uses [`sulogin`](https://linux.die.net/man/8/sulogin) (like Debian) to drop to a **root** console during boot failures, then locking the **root** account will prevent `sulogin` from opening the **root** shell and you will get this error: - - Cannot open access to console, the root account is locked. - - See sulogin(8) man page for more details. - - Press Enter to continue. - -To work around this, you can use the `--force` option for `sulogin`. Some distributions already include this, or some other, workaround. - -An alternative to locking the **root** acount is set a long/complicated **root** password and store it in a secured, non digital format. That way you have it when/if you need it. +By default, accounts can use any password they want, including bad ones. [pwquality](https://linux.die.net/man/5/pwquality.conf)/[pam_pwquality](https://linux.die.net/man/8/pam_pwquality) addresses this security gap by providing "a way to configure the default password quality requirements for the system passwords" and checking "its strength against a system dictionary and a set of rules for identifying poor choices." #### Goal -- locked **root** account that nobody can use to log in as **root** - -#### Notes - -- Some distributions disable **root** login by default (e.g. Ubuntu) so you may not need to do this step. Check with your distribution's documentation. - -#### References - -- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=806852 -- https://github.com/systemd/systemd/issues/7115 -- https://github.com/karelzak/util-linux/commit/7ff1162e67164cb4ece19dd809c26272461aa254 -- https://github.com/systemd/systemd/issues/11596 -- `man systemd` +- enforced strong passwords #### Steps -1. [**!! USE WITH CAUTION !!**](#root-password-disable) -- Lock the **root** account: +1. Install `libpam-pwquality`. + On Debian based systems: + ``` bash - sudo passwd -l root + sudo apt install libpam-pwquality + ``` + +1. Tell PAM to use `libpam-pwquality` to enforce strong passwords by editing the file `/etc/pam.d/common-password` and **change** the line that starts like this: + + ``` + password requisite pam_pwquality.so + ``` + + to this: + + ``` + password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec + ``` + + The above options are: + + - `retry=3` = prompt user 3 times before returning with error. + - `minlen=10` = the minimum length of the password, factoring in any credits (or debits) from these: + - `dcredit=-1` = must have at least **one digit** + - `ucredit=-1` = must have at least **one upper case letter** + - `lcredit=-1` = must have at least **one lower case letter** + - `ocredit=-1` = must have at least **one non-alphanumeric character** + - `difok=3` = at least 3 characters from the new password cannot have been in the old password + - `maxrepeat=3` = allow a maximum of 3 repeated characters + - `gecoschec` = do not allow passwords with the account's name + + + [For the lazy](#editing-configuration-files---for-the-lazy): + + ``` bash + sudo cp --preserve /etc/pam.d/common-password /etc/pam.d/common-password.$(date +"%Y%m%d%H%M%S") + + sudo sed -i -r -e "s/^(password\s+requisite\s+pam_pwquality.so)(.*)$/# \1\2 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1 retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/pam.d/common-password ``` ([Table of Contents](#table-of-contents)) -## Other Stuff - -### Configure Gmail as MTA +### 2FA/MFA for SSH #### Why -Unless you're planning on setting up your own mail server, you'll need a way to send e-mails from your server. This will be important for system alerts/messages. +Even though SSH is a pretty good security guard for your doors and windows, it is still a visible door that bad-actors can see and try to brute-force in. [Fail2ban](#fail2ban-application-intrusion-detection-and-prevention) will monitor for these brute-force attempts but there is no such thing as being too secure. + +Using Two Factor Authentication (2FA) / Multi Factor Authentication (MFA) requires anyone entering to have **two** keys to enter which makes it harder for bad actors. The two keys are: + +1. Their password +1. A 6 digit token that changes every 30 seconds + +Without both keys, they won't be able to get in. + +#### Why Not + +Many folks might find the experience cumbersome or annoying. And, acesss to your system is dependent on the accompanying authenticator app that generates the code. #### Goals -- `mail` configured to send e-mails from your server using [Gmail](https://mail.google.com/) +- 2FA/MFA enabled for all SSH connections + +#### Notes + +- Before you do this, you should have an idea of how 2FA/MFA works and you'll need an authenticator app on your phone to continue. +- We'll use [google-authenticator-libpam](https://github.com/google/google-authenticator-libpam). +- With the below configuration, a user will only need to enter their 2FA/MFA code if they are logging on with their password but not **not** if they are using [SSH public/private keys](#ssh-publicprivate-keys). Check the documentation on how to change this behavior to suite your requirements. #### References -- https://php.quicoto.com/setup-exim4-to-use-gmail-in-ubuntu/ +- https://github.com/google/google-authenticator-libpam #### Steps -1. Install `exim4`. - - For Debian based systems: +1. Install it `libpam-google-authenticator`. + + On Debian based systems: ``` bash - sudo apt install exim4 - ``` - -1. Configure `exim4`: - - For Debian based systems: - ``` bash - sudo dpkg-reconfigure exim4-config + sudo apt install libpam-google-authenticator ``` - You'll be prompted with some questions: - - |Prompt|Answer| - |--:|--| - |General type of mail configuration|`mail sent by smarthost; no local mail`| - |System mail name|(default)| - |IP-addresses to listen on for incoming SMTP connections|`127.0.0.1`| - |Other destinations for which mail is accepted|(default)| - |Visible domain name for local users|(default)| - |IP address or host name of the outgoing smarthost|`smtp.gmail.com::587`| - |Keep number of DNS-queries minimal (Dial-on-Demand)?|`No`| - |Split configuration into small files?|`No`| - -1. **Add** a line like this to `/etc/exim4/passwd.client` - - ``` - *.google.com:yourAccount@gmail.com:yourPassword - ``` - - Replace `yourAccount@gmail.com` and `yourPassword` with your details. If you have 2FA/MFA enabled on your Gmail then you'll need to create and use an app password. - -1. This file has your Gmail password so we need to lock it down: +1. **Make sure you're logged in as the ID you want to enable 2FA/MFA for** and **execute** `google-authenticator` to create the necessary token data: ``` bash - sudo chown root:Debian-exim /etc/exim4/passwd.client - sudo chmod 640 /etc/exim4/passwd.client + google-authenticator ``` + + > ``` + > Do you want authentication tokens to be time-based (y/n) y + > https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@host%3Fsecret%3DR4ZWX34FQKZROVX7AGLJ64684Y%26issuer%3Dhost + > + > ... + > + > Your new secret key is: R3NVX3FFQKZROVX7AGLJUGGESY + > Your verification code is 751419 + > Your emergency scratch codes are: + > 12345678 + > 90123456 + > 78901234 + > 56789012 + > 34567890 + > + > Do you want me to update your "/home/user/.google_authenticator" file (y/n) y + > + > Do you want to disallow multiple uses of the same authentication + > token? This restricts you to one login about every 30s, but it increases + > your chances to notice or even prevent man-in-the-middle attacks (y/n) Do you want to disallow multiple uses of the same authentication + > token? This restricts you to one login about every 30s, but it increases + > your chances to notice or even prevent man-in-the-middle attacks (y/n) y + > + > By default, tokens are good for 30 seconds. In order to compensate for + > possible time-skew between the client and the server, we allow an extra + > token before and after the current time. If you experience problems with + > poor time synchronization, you can increase the window from its default + > size of +-1min (window size of 3) to about +-4min (window size of + > 17 acceptable tokens). + > Do you want to do so? (y/n) y + > + > If the computer that you are logging into isn't hardened against brute-force + > login attempts, you can enable rate-limiting for the authentication module. + > By default, this limits attackers to no more than 3 login attempts every 30s. + > Do you want to enable rate-limiting (y/n) y + > ``` + + Notice this is **not run as root**. + + Select default option (y in most cases) for all the questions it asks and remember to save the emergency scratch codes. + +1. Now we need to enable it as an authentication method for SSH by **adding** this line to `/etc/pam.d/sshd`: -1. Restart `exim4`: + ``` + auth required pam_google_authenticator.so nullok + ``` + + Check [here](https://github.com/google/google-authenticator-libpam/blob/master/README.md#nullok) for what `nullok` means. + + [For the lazy](#editing-configuration-files---for-the-lazy): ``` bash - sudo service exim4 restart + sudo cp --preserve /etc/pam.d/sshd /etc/pam.d/sshd.$(date +"%Y%m%d%H%M%S") + + echo -e "\nauth required pam_google_authenticator.so nullok # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/pam.d/sshd ``` -1. Add some mail aliases so we can send e-mails to local accounts by **adding** lines like this to `/etc/aliases`: +1. Tell SSH to levearage it by **adding** this line in `/etc/ssh/sshd_config`: ``` - user1: user1@gmail.com - user2: user2@gmail.com - ... + ChallengeResponseAuthentication yes ``` - You'll need to add all the local accounts that exist on your server. + [For the lazy](#editing-configuration-files---for-the-lazy): + + ``` bash + sudo cp --preserve /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +"%Y%m%d%H%M%S") + + echo -e "\nChallengeResponseAuthentication yes # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ssh/sshd_config + ``` + +1. Restart `ssh`: + + ``` bash + sudo service sshd restart + ``` + +([Table of Contents](#table-of-contents)) + +### Apticron - Automatic Update Notifier + +#### Why + +It is important to keep your server up-to-date with all security patches. Otherwise you're at risk of known security vulnerabilities that bad-actors could use to gain unauthorized access to your server. + +You have two options: + +- Configure your server for unattended updates +- Be notified when updates are available + +Which option you pick is up to you but I prefer being notified by e-mail when updates are available. This is because an update may break something else. If the server updates it-self then I may not know and, if I do find out, I'll have to scramble to fix it. If it e-mails me when updates are available, then I can do the updates at my schedule. + +#### Notes + +- Your server will need a way to send e-mails for this to work + +#### References + +- https://wiki.debian.org/UnattendedUpgrades#apt-listchanges +- https://www.cyberciti.biz/faq/apt-get-apticron-send-email-upgrades-available/ +- https://www.unixmen.com/how-to-get-email-notifications-for-new-updates-on-debianubuntu/ + +#### Steps + +1. Install `apticron`. + + On Debian based systems: + + ``` bash + sudo apt install apticron + ``` +1. Set the value of `EMAIL` in `/etc/apticron/apticron.conf` to your e-mail address. + +([Table of Contents](#table-of-contents)) + +### Orphaned Software + +#### Why + +As you use your system, and you install and uninstall software, you'll eventually end up with orphaned, or unused software/packages/libraries. You don't need to remove them, but if you don't need them, why keep them? When security is a priority, anything not explicitly needed is a potential security threat. You want to keep your server as trimmed and lean as possible. + +#### Notes + +- Each distribution manages software/packages/libraries differently so how you find and remove orphaned packages will be different. +- So far I only have steps for Debian; I will add for other distributions as I learn how. + +#### Steps + +##### Debian + +For Debian based distributions, you can use [deborphan](http://freshmeat.sourceforge.net/projects/deborphan/) to find orphaned packages. + +1. Install `deborphan`. + + ``` bash + sudo apt install deborphan + ``` + +1. Run `deborphan` as **root** to see a list of orphaned packages: + + ``` bash + sudo deborphan + ``` + + > ``` + > libxapian30 + > libpipeline1 + > ``` + +1. Pass it's output to `apt` to remove them: + + ``` bash + sudo apt --autoremove purge $(deborphan) + ``` + + You will want to repeatedly run this command until `deborphan` no longer returns any orphaned packages. + + [For the lazy](#editing-configuration-files---for-the-lazy): + + ``` bash + while [[ $(deborphan | wc -l) != 0 ]] ; do + sudo apt --autoremove purge $(deborphan) + done + ``` ([Table of Contents](#table-of-contents)) @@ -1416,8 +1934,7 @@ From [https://cisofy.com/lynis/](https://cisofy.com/lynis/): #### Notes -- We will install it from it's [GitHub](https://github.com/CISOfy/lynis) page so we have the latest and greatest. -- CISOFY also offers packages for many distributions. Check https://packages.cisofy.com/ for distribution specific installation instructions. +- CISOFY offers packages for many distributions. Check https://packages.cisofy.com/ for distribution specific installation instructions. #### References @@ -1428,75 +1945,34 @@ From [https://cisofy.com/lynis/](https://cisofy.com/lynis/): #### Steps -1. We want it to be installed system wide so go to `/usr/local` and clone it from https://github.com/CISOfy/lynis: - +1. Install `lynis`. https://cisofy.com/lynis/#installation has detailed instructions on how to install it for your distribution. + + On Debian based systems, using CISOFY's community software repository: + ``` bash - cd /usr/local - sudo git clone https://github.com/CISOfy/lynis + sudo wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo apt-key add - + sudo apt install apt-transport-https + sudo echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list + sudo apt update + sudo apt install lynis ``` 1. Update it: ``` bash - sudo /usr/local/lynis/lynis update info + sudo lynis update info ``` 1. Run a security audit: ``` bash - sudo /usr/local/lynis/lynis audit system + sudo lynis audit system ``` This will scan your server, report its audit findings, and at the end it will give you suggestions. Spend some time going through the output and address gaps as necessary. ([Table of Contents](#table-of-contents)) -### Separate iptables Log File (WIP) - -#### References - -- https://blog.shadypixel.com/log-iptables-messages-to-a-separate-file-with-rsyslog/ -- https://gist.github.com/netson/c45b2dc4e835761fbccc - -## Not Security - -### Mount `/tmp` In RAM Using `tmpfs` - -#### Why - -RAM is faster than disk, even SSD. By mounting `/tmp` in RAM using `tmpfs`, you may notice a performance increase. - -#### Why Not - -Using `tmpfs` will consume RAM. If RAM fills up your system may become unstable. `tmpfs` may resort to using swap. - -#### References - -- https://wiki.archlinux.org/index.php/Tmpfs -- https://wiki.centos.org/TipsAndTricks/TmpOnTmpfs -- `man mount` -- `man tmpfs` - -#### Steps - -1. **Add** this line to `/etc/fstab`: - - ``` - tmpfs /tmp tmpfs defaults,noatime,rw,nodev,nosuid,nodiratime,mode=1777,size=2GB 0 0 - ``` - - Change the value of `size` to suit your needs. If you remove the `size` option then it will default to using half of your RAM. - - [For the lazy](#Editing-Configuration-Files---For-The-Lazy): - - ``` bash - sudo cp --preserve /etc/fstab /etc/fstab.$(date +"%Y%m%d%H%M%S") - - echo -e "\ntmpfs /tmp tmpfs defaults,noatime,rw,nodev,nosuid,nodiratime,mode=1777,size=2G 0 0 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/fstab - ``` - -([Table of Contents](#table-of-contents)) - ## Miscellaneous ### Contacting Me @@ -1510,6 +1986,7 @@ For any questions, comments, concerns, feedback, or issues, submit a [new issue] - [https://github.com/pratiktri/server_init_harden](https://github.com/pratiktri/server_init_harden) - Bash script that automates few of the tasks that you need to perform on a new Linux server to give it basic amount security. - https://security.utexas.edu/os-hardening-checklist/linux-7 - Red Hat Enterprise Linux 7 Hardening Checklist - https://cloudpro.zone/index.php/2018/01/18/debian-9-3-server-setup-guide-part-1/ - # Debian 9.3 server setup guide +- https://blog.vigilcode.com/2011/04/ubuntu-server-initial-security-quick-secure-setup-part-i/ - Ubuntu Server Initial Security guide ([Table of Contents](#table-of-contents))