Secure you Debian Server
This guide contain the steps i always do on first time login after installing Debian on a blank server.
- You need root access for the first steps, so gain root access as secure as you possibly can.
Update Debian
- This is a good idea to do before anything else.
- Using the -y switch on apt-get will assume "yes" to all questions from apt-get.
- Sometimes ca-certificates needs an upgrade, and to make sure you know this is done you will need to press q to continue the apt-get -y upgrade
Here is how:
root@pulspc:~# apt-get -y update Ign http://ftp.debian.org jessie InRelease Get:1 http://ftp.debian.org jessie-updates InRelease [145 kB] Get:2 http://ftp.debian.org jessie Release.gpg [2,373 B] ........ Lots of lines removed for convienience !! Get:15 http://ftp.debian.org jessie-updates/main amd64 2016-11-30-2028.41.pdiff [530 B] Get:16 http://security.debian.org jessie/updates/main Translation-en [183 kB] Fetched 19.5 MB in 7s (2,674 kB/s) Reading package lists... Doneroot@pulspc:~#apt-get -y upgrade Reading package lists... Done Building dependency tree Reading state information... Done Calculating upgrade... Done The following packages will be upgraded: ........ Lots of lines removed for convienience !! Setting up python-pil:amd64 (2.6.1-2+deb8u3) ... Processing triggers for libc-bin (2.19-18+deb8u7) ... Processing triggers for ca-certificates (20141019+deb8u2) ... Updating certificates in /etc/ssl/certs... 10 added, 10 removed; done. Running hooks in /etc/ca-certificates/update.d....done. root@pulspc:~#
Configure Automatic Security Updates
Here you can see my configuration files
This is my version of the file /etc/apt/apt.conf.d/50unattended-upgrades
// Unattended-Upgrade::Origins-Pattern controls which packages are // upgraded. // // Lines below have the format format is "keyword=value,...". A // package will be upgraded only if the values in its metadata match // all the supplied keywords in a line. (In other words, omitted // keywords are wild cards.) The keywords originate from the Release // file, but several aliases are accepted. The accepted keywords are: // a,archive,suite (eg, "stable") // c,component (eg, "main", "crontrib", "non-free") // l,label (eg, "Debian", "Debian-Security") // o,origin (eg, "Debian", "Unofficial Multimedia Packages") // n,codename (eg, "jessie", "jessie-updates") // site (eg, "http.debian.net") // The available values on the system are printed by the command // "apt-cache policy", and can be debugged by running // "unattended-upgrades -d" and looking at the log file. // // Within lines unattended-upgrades allows 2 macros whose values are // derived from /etc/debian_version: // ${distro_id} Installed origin. // ${distro_codename} Installed codename (eg, "jessie") Unattended-Upgrade::Origins-Pattern { // Codename based matching: // This will follow the migration of a release through different // archives (e.g. from testing to stable and later oldstable). "o=Debian,n=jessie"; "o=Debian,n=jessie-updates"; "o=Debian,n=jessie-proposed-updates"; "o=Debian,n=jessie,l=Debian-Security"; // Archive or Suite based matching: // Note that this will silently match a different release after // migration to the specified archive (e.g. testing becomes the // new stable). // "o=Debian,a=stable"; // "o=Debian,a=stable-updates"; // "o=Debian,a=proposed-updates"; "origin=Debian,codename=${distro_codename},label=Debian-Security"; }; // List of packages to not update (regexp are supported) Unattended-Upgrade::Package-Blacklist { // "vim"; // "libc6"; // "libc6-dev"; // "libc6-i686"; }; // This option allows you to control if on a unclean dpkg exit // unattended-upgrades will automatically run // dpkg --force-confold --configure -a // The default is true, to ensure updates keep getting installed //Unattended-Upgrade::AutoFixInterruptedDpkg "false"; // Split the upgrade into the smallest possible chunks so that // they can be interrupted with SIGUSR1. This makes the upgrade // a bit slower but it has the benefit that shutdown while a upgrade // is running is possible (with a small delay) //Unattended-Upgrade::MinimalSteps "true"; // Install all unattended-upgrades when the machine is shuting down // instead of doing it in the background while the machine is running // This will (obviously) make shutdown slower //Unattended-Upgrade::InstallOnShutdown "true"; // Send email to this address for problems or packages upgrades // If empty or unset then no email is sent, make sure that you // have a working mail setup on your system. A package that provides // 'mailx' must be installed. E.g. "[email protected]" Unattended-Upgrade::Mail "root"; // Set this value to "true" to get emails only on errors. Default // is to always send a mail if Unattended-Upgrade::Mail is set //Unattended-Upgrade::MailOnlyOnError "true"; // Do automatic removal of new unused dependencies after the upgrade // (equivalent to apt-get autoremove) Unattended-Upgrade::Remove-Unused-Dependencies "true"; // Automatically reboot *WITHOUT CONFIRMATION* if // the file /var/run/reboot-required is found after the upgrade Unattended-Upgrade::Automatic-Reboot "false"; // If automatic reboot is enabled and needed, reboot at the specific // time instead of immediately // Default: "now" Unattended-Upgrade::Automatic-Reboot-Time "02:00"; // Use apt bandwidth limit feature, this example limits the download // speed to 70kb/sec //Acquire::http::Dl-Limit "70";This is my version of the file /etc/apt/apt.conf.d/02periodic
// Control parameters for cron jobs by /etc/cron.daily/apt // // Enable the update/upgrade script (0=disable) APT::Periodic::Enable "1"; // Do "apt-get update" automatically every n-days (0=disable) APT::Periodic::Update-Package-Lists "1"; // Do "apt-get upgrade --download-only" every n-days (0=disable) APT::Periodic::Download-Upgradeable-Packages "1"; // Run the "unattended-upgrade" security upgrade script // every n-days (0=disabled) // Requires the package "unattended-upgrades" and will write // a log in /var/log/unattended-upgrades APT::Periodic::Unattended-Upgrade "1"; // Do "apt-get autoclean" every n-days (0=disable) APT::Periodic::AutocleanInterval "21"; // Send report mail to root // 0: no report (or null string) // 1: progress report (actually any string) // 2: + command outputs (remove -qq, remove 2>/dev/null, add -d) // 3: + trace on APT::Periodic::Verbose "2";This is my version of the file /etc/apt/listchanges.conf
[apt] frontend=pager email_address=root confirm=0 save_seen=/var/lib/apt/listchanges.db which=both
Create and use a non-root user account
- It is not a good idea to use the root account all the time. It is so powerful that even the smallest mistake can have devastating results if executed as root. Logging in as root directly is also considered bad practice so we will fix that now.
The 7 steps:
1. The sudo feature is not installed by default on Debian so we will do this first, since we rely heavily on this command when logging in as a "normal" user that needs to do stuff that requires root privileges.
apt-get install sudo
root@pulspc:~# apt-get install sudo Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: sudo 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 855 kB of archives. After this operation, 2,390 kB of additional disk space will be used. .................... Setting up sudo (1.8.10p3-1+deb8u3) ... Processing triggers for systemd (215-17+deb8u6) ... root@pulspc:~#2. Create the user, replacing new_user with your desired username. You’ll then be asked to assign the user a password:
adduser new_user
root@pulspc:~# adduser new_user Adding user `new_user' ... Adding new group `new_user' (1000) ... Adding new user `new_user' (1000) with group `new_user' ... Creating home directory `/home/new_user' ... Copying files from `/etc/skel' ... Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully Changing the user information for new_user Enter the new value, or press ENTER for the default Full Name []: New User Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] Y root@pulspc:~#3. Add the new_user to the sudo group so it will have the option to do stuff that needs root-privileges.
adduser new_user sudo
root@pulspc:~# adduser new_user sudo Adding user `new_user' to group `sudo' ... Adding user new_user to group sudo Done. root@pulspc:~#4. Make sure your new user is working by logging in to localhost from you current shell terminal using this command
ssh new_user@localhost
root@pulspc:~# ssh new_user@localhost The authenticity of host 'localhost (127.0.0.1)' can't be established. RSA key fingerprint is 12:34:56:78:90:12:34:56:78:90:12:34:56:78:90 Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'localhost' (RSA) to the list of known hosts. new_user@localhost's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. new_user@pulspc:~$5. Test that new_user can use the sudo command by calling the harmless ls command using sudo.
sudo ls /
fm@pulspc:~$ sudo ls / We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. [sudo] password for fm: bin etc lib lost+found opt run sys var boot home lib32 media proc sbin tmp vmlinuz dev initrd.img lib64 mnt root srv usr fm@pulspc:~$6. Exit the new_user ssh connection and your root login.
exit
root@pulspc:~# fm@pulspc:~$ exit logout Connection to localhost closed. root@pulspc:~# exit7. ALWAYS login as the new_user from now on!
login as: new_user
login as: new_user new_user@<IP or HOST name>'s password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Feb 22 09:55:27 2017 from localhost new_user@pulspc:~$
Make SSH Access more secure
Install authentication key-pair
The crypto key-pairs is created on your local workstation.
Follow the guide that fit your workstation:
- Linux / OS X : https://www.linode.com/docs/security/securing-your-server/#create-an-authentication-key-pair
- Windows : https://www.linode.com/docs/security/use-public-key-authentication-with-ssh#windows-operating-system
Harden the SSH Daemon
- Do not allow direct root login.
- Do not allow login without crypto key-pairs.
- Make SSH listen only on the IP protocol you will be using.
This is my /etc/ssh/sshd_config file
# Package generated configuration file # See the sshd_config(5) manpage for details # What ports, IPs and protocols we listen for Port 22 # Use these options to restrict which interfaces/protocols sshd will bind to #ListenAddress :: ListenAddress 0.0.0.0 Protocol 2 # HostKeys for protocol version 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key #Privilege Separation is turned on for security UsePrivilegeSeparation yes # Lifetime and size of ephemeral version 1 server key KeyRegenerationInterval 3600 ServerKeyBits 1024 # Logging SyslogFacility AUTH LogLevel INFO # Authentication: LoginGraceTime 120 PermitRootLogin no StrictModes yes RSAAuthentication yes PubkeyAuthentication yes #AuthorizedKeysFile %h/.ssh/authorized_keys # Don't read the user's ~/.rhosts and ~/.shosts files IgnoreRhosts yes # For this to work you will also need host keys in /etc/ssh_known_hosts RhostsRSAAuthentication no # similar for protocol version 2 HostbasedAuthentication no # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication #IgnoreUserKnownHosts yes # To enable empty passwords, change to yes (NOT RECOMMENDED) PermitEmptyPasswords no # Change to yes to enable challenge-response passwords (beware issues with # some PAM modules and threads) ChallengeResponseAuthentication no # Change to no to disable tunnelled clear text passwords PasswordAuthentication no # Kerberos options #KerberosAuthentication no #KerberosGetAFSToken no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes X11Forwarding yes X11DisplayOffset 10 PrintMotd no PrintLastLog yes TCPKeepAlive yes #UseLogin no #MaxStartups 10:30:60 #Banner /etc/issue.net # Allow client to pass locale environment variables AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. UsePAM yes
Remember to restart the SSH daemon: sudo systemctl restart sshd
Brute force SSH Login Protection
Fail2ban scans log files (e.g. /var/log/apache/error_log) and bans IPs that show the malicious signs of brute force attacks
sudo apt-get -y install fail2ban
new_user@pulspc:~$ sudo apt-get -y install fail2ban Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: python-pyinotify Suggested packages: python-gamin python-pyinotify-doc The following NEW packages will be installed: fail2ban python-pyinotify 0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. Need to get 192 kB of archives. After this operation, 713 kB of additional disk space will be used. Get:1 http://ftp.debian.org/debian/ jessie/main fail2ban all 0.8.13-1 [165 kB] Get:2 http://ftp.debian.org/debian/ jessie/main python-pyinotify all 0.9.4-1 [26.4 kB] Fetched 192 kB in 0s (934 kB/s) Selecting previously unselected package fail2ban. (Reading database ... 37932 files and directories currently installed.) Preparing to unpack .../fail2ban_0.8.13-1_all.deb ... Unpacking fail2ban (0.8.13-1) ... Selecting previously unselected package python-pyinotify. Preparing to unpack .../python-pyinotify_0.9.4-1_all.deb ... Unpacking python-pyinotify (0.9.4-1) ... Processing triggers for man-db (2.7.0.2-5) ... Processing triggers for systemd (215-17+deb8u6) ... Setting up fail2ban (0.8.13-1) ... Setting up python-pyinotify (0.9.4-1) ... Processing triggers for systemd (215-17+deb8u6) ... new_user@pulspc:~$
Configure it to your needs: http://www.fail2ban.org/wiki/index.php/Main_Page
Inspiration was found at http://www.linode.com/docs/security/securing-your-server/