{"id":76,"date":"2021-12-01T18:56:00","date_gmt":"2021-12-01T18:56:00","guid":{"rendered":"https:\/\/mgcspace.com\/content\/?p=76"},"modified":"2022-11-21T17:35:26","modified_gmt":"2022-11-21T17:35:26","slug":"quick-initial-linux-server-security-and-hardening","status":"publish","type":"post","link":"https:\/\/mgcspace.com\/content\/security\/quick-initial-linux-server-security-and-hardening\/","title":{"rendered":"Quick Initial Linux Server Security and Hardening"},"content":{"rendered":"\n<p>Once you get an unmanaged server from MGCSpace.com, the first step you should perform is securing the server. In case of managed services, MGCSpace team will take of your server&#8217;s security aspect. But if you have a server where you want to manage it yourself then you should perform crucial security measures in order to avoid your server being compromised and exploited by bad actors. Securing your server not only keeps you and your server safe but also deters bad actors and send them to look for other less secure servers. <\/p>\n\n\n\n<p>Although there are plethora of aspects of Linux server security but we suggest you to perform some crucial security measures initially which would serve as base for your Linux server security. You may later enhance and fine tune them as per your use case and requirements. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why server security is required ?<\/h2>\n\n\n\n<p>In short, we need it to keep your server secure from unwanted access and exploitation by malicious actors. If you are not vigilant then many kind of compromises are possible such as using the web server to spread malware or just using it to steal your traffic,  creating a spam-sending relay, a web or TCP proxy server, or other malicious activities are possible. When your server is not properly secured, you are not only risking your data but may also helping inadvertently in compromising other servers online.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Basic security measures<\/h2>\n\n\n\n<p>So what kind of basic measures you need ? As already mentioned, there are plenty of things you can do to secure your server but we will focus on some initial and crucial things. <\/p>\n\n\n\n<div style=\"height:45px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"limitedUser\">Add sudo or Limited user account<\/h3>\n\n\n\n<p>In most of the Linux installation, by-default you will have root access. Root user allow to have full  and unrestricted privileges. This may prove fatal as any of the mistake or command can render your system unusable if not used wisely. Hence it is recommended to use limited privilege user which can run Administrative commands via elevated privileges using <code>sudo<\/code>. Another advantage of using sudo user is that you can also log all elevated command perform by such user.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\">For RHEL\/Fedora\/Alma and similar linux distribution<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To add a sudo user for RHEL based distribution, first you need to create a new user on your system. \n<pre class=\"wp-block-code\"><code>useradd -m your_user_name &amp;&amp; passwd your_user_name <\/code><\/pre>\nIn above replace <code>your_user_name<\/code> with desired name, you  password and you have will have new user added to system.<\/li>\n\n\n\n<li>One your new user is added, we need to add it to <code>wheel<\/code> group which will give it sudo privileges. <pre class=\"wp-block-code\"><code>usermod -aG wheel your_user_name<\/code><\/pre> <\/li>\n<\/ul>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\">For Debian\/Ubuntu and similar linux distribution<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To add sudo user in Debian or Ubuntu based distribution, again first we need to create a new user (you may also use existing user and skip to next step).  <pre class=\"wp-block-code\"><code>adduser your_user_name <\/code><\/pre> In above replace <code>your_user_name<\/code> with desired name, you will be asked for couple of details including  password and you have will have new user added to the system.<\/li>\n\n\n\n<li>One your new user is added, we need to add to <code>sudo<\/code> group which will give it sudo privileges. <pre class=\"wp-block-code\"><code>usermod -aG wheel your_user_name<\/code><\/pre><\/li>\n<\/ul>\n<\/div><\/div>\n\n\n\n<p class=\"has-background has-small-font-size\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>Sometimes you may not have <code>sudo<\/code> installed by default, you can add it easily using <code>dnf install sudo -y<\/code> on RHEL based systems and <code>apt-get install sudo -y<\/code> on debian based systems.<\/p>\n\n\n\n<p>Now we have new limited user with <code>sudo<\/code> privileges added, you should open another terminal or session and login using new user and try to run some Administrative commands without sudo, it should give you permission error. Now if you want to run Administrative commands, you can run following way : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf update<\/code><\/pre>\n\n\n\n<p>OR<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update<\/code><\/pre>\n\n\n\n<p>It will ask you for user&#8217;s password and should be able to run the Administrative commands. If there is no error and you are able to use sudo command with newly created sudo user, you may now logout the previous root user session and now on continue with <code>sudo<\/code> user session we just used to login a moment ago.<\/p>\n\n\n\n<div style=\"height:45px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"updateSystem\">Updating the system<\/h2>\n\n\n\n<p>Since you have just created a new limited user with sudo privileges, we will move forward now with updating the system. Keeping your system updated is the most basic yet very important security measure. By updating you are getting most secure and patched version of  software as mostly security issues and vulnerability in software are patched quickly and are made available via updates. Although there are various system but most common system can be updated using following methods: <br><\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p><strong>CentOS stream 8 \/ CentOS 8, AlmaLinux, Rocky Linux, Fedora and other latest RHEL distributions:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf upgrade<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p><strong>Debian \/ Ubuntu based distributions:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update &amp;&amp; sudo apt upgrade<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"ssh\">Hardening SSH access<\/h2>\n\n\n\n<p>SSH, (or Secure Shell Protocol)  is a remote administration protocol that is used to to manage and access remote resources and service, control, and modify servers on network via secure layer over unsecured network. In short, the SSH is gateway over internet to your server and keeping it secure is essential part. SSH security can be hardened in multiple ways depending upon the use case. Here we will implement basic security measures so that access to your server is more secures through SSH. <\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\">Configure key-based SSH authentication<\/h4>\n\n\n\n<p>By default, you can login to ssh using password as well ssh-keys, however, password based login is considered relatively unsafe, and hence it is suggested to use key-based authentication. It is enabled by default in SSH.<br><br>Before making any changes ssh configuration, we have to generate ssh-keys which works in public and private key pair ie. we generate a private key and then public key based on that key. As as the name suggest, private key should be kept with you and never shared with anyone while the public key need to be copied on remote system which want login. <\/p>\n\n\n\n<p>Generating SSH public-private key pair is easy, first on the system from where you will login to remote system using SSH, you need to run following command to generate the key pair: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -b 4096 -t rsa<\/code><\/pre>\n\n\n\n<p>It will ask you for locations to save newly generated files, just press enter and if asks for passphrase then again press enter to choose no passphrase. If you provide any password there, then it will add extra layer of security, along with key will also ask for that password whenever you want to login. <\/p>\n\n\n\n<p>Once done, it will create two files <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/home\/your_user_name\/.ssh\/id_rsa<\/code>  Your private key, never share with anyone. <\/li>\n\n\n\n<li><code>\/home\/your_user_name\/.ssh\/id_rsa.pub<\/code> Your public key, you need to copy this to remote system where you want to connect.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-background has-small-font-size\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>Above command will create ssh key pair for the  as user you are logged in local system. It has nothing to do with remote  system user. For example, if you run above command as root user then keys will be generated in files <code>\/root\/.ssh\/id_rsa.pub<\/code> and <code>\/root\/.ssh\/id_rsa<\/code><\/p>\n\n\n\n<p>Now upload your public key to remote system, ideally we are required copy content of <code>\/home\/your_user_name\/.ssh\/id_rsa.pub<\/code> to remote user&#8217;s <code>~\/.ssh\/authorized_keys<\/code> file. Lets have an example, for  user &#8220;tech1&#8221;, it would go in file <code>\/home\/tech1\/.ssh\/authorized_keys<\/code>. You can also use built-in utility <code>ssh-copy-id<\/code> which can do that part for you easily.<\/p>\n\n\n\n<p>To copy public key to remote server over ssh use following command, it will require that you have access to remote user using password : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-copy-id -i ~\/.ssh\/id_rsa.pub tech1@1.2.3.4<\/code><\/pre>\n\n\n\n<p>Once you run above command successfully from your local system where you generated the keys, it will ask for ssh password and then will add entry to remote server&#8217;s (here its with ip <code>1.2.3.4<\/code>) authorized_keys file for remote user <code>tech1<\/code>.<\/p>\n\n\n\n<p>Now run following command to test to see if you can login to remote user tech1 on server 1.2.3.4 without providing password. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh -p 22 tech1@1.2.3.4<\/code><\/pre>\n\n\n\n<p>If everything is fine, running above command should allow you to login to remote system ssh without password. In above, -p 22 is default ssh port, if ssh is running on non-standard port for remote server, then  replace 22 with desired port. Further, <code>tech1<\/code> is user and we are connecting to server with ip <code>1.2.3.4<\/code>. <\/p>\n<\/div><\/div>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\" id=\"disableRootLogin\">Disable root user login via SSH<\/h4>\n\n\n\n<p>As SSH is gateway to your server, it is always best practice to disable direct root access, we have already created <a href=\"#limitedUser\">sudo user<\/a> earlier and tested that its able to login. Now we can disable access root via SSH, this way we are making sure that no one can log in using root user even if they are able to guess or obtain root login credentials.<\/p>\n\n\n\n<p>Open sshd configuration file in editor of your choice, we prefer <code>nano<\/code>.  <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/ssh\/sshd_config<\/code><\/pre>\n\n\n\n<p>In that file look for directive &#8220;PermitRootLogin&#8221; and set it to no. Although we suggest to disable root login completely, however, in some cases you may want to disable password login but allow key-based authentication which is considered sufficiently secure. <\/p>\n\n\n\n<p>To disable root ssh login completely, make sure &#8220;PermitRootLogin&#8221; is set to no in ssh configuration file. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PermitRootLogin no<\/code><\/pre>\n\n\n\n<p>To disable password login but allow key-based access: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PermitRootLogin prohibit-password<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\" id=\"sshPort\">Change SSH port<\/h4>\n\n\n\n<p>By default, SSH uses port 22, it means there are always bad actors looking for port 22 to break the password using repeat dictionary attack known as brute force attack. We have already made it harder by disabling root access by SSH as now attacker also need to guess the username since root is disabled. Further we can change ssh port to something else so that attacker will have hard time connecting to SSH on this server. We can change to something like &#8220;12200&#8221;<\/p>\n\n\n\n<p>Open ssh configuration file in editor like nano with command <code>sudo nano \/etc\/ssh\/sshd_config<\/code>, find Port and change to anything you like : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Port 12200<\/code><\/pre>\n\n\n\n<p class=\"has-background has-small-font-size\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>It is suggested to use on of the privileged port ie &lt;1024, however you can use any port your prefer as long its not used by any other service on your server. <\/p>\n\n\n\n<p>Also, no matter what port you use, it is easy to find running port through simple port scanning but by changing ports, you will definitely turn away bots those are looking SSH running over  port 22. <\/p>\n<\/div><\/div>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h4 class=\"wp-block-heading\">Disable password authentication for all users<\/h4>\n\n\n\n<p>If you have configured key-based authentication successfully, it is recommended to disable password based authentication for all users. To do that, open ssh configuration file in editor like nano with command <code>sudo nano \/etc\/ssh\/sshd_config<\/code>,  and set &#8220;PasswordAuthentication&#8221; to &#8220;no&#8221;. Make sure its not commented out. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PasswordAuthentication no<\/code><\/pre>\n\n\n\n<p class=\"has-background has-small-font-size\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>Although its recommended to disable password authentication completely but you may want to enable password authentication for non-root users so that you can access your server using password where your private key is not available eg. accessing it form some one else&#8217;s computer.  Since we have already disabled <a href=\"#disableRootLogin\">ssh root login<\/a>, then you may leave <code>PasswordAuthentication yes<\/code> and only non-root users can access server via SSH.<\/p>\n\n\n\n<p>Once you are done with modifying your <code>\/etc\/ssh\/sshd_config<\/code> file, to apply the changes, we need to reload the sshd daemon. We also need to make sure there is no errors in config files after we made the changes. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sshd -t <\/code><\/pre>\n\n\n\n<p>If there is no error, you can now restart sshd daemon and changes we made so far will be applied. Remember, if there is any mistake, you may get locked out of your system after applying sshd config changes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart sshd<\/code><\/pre>\n\n\n\n<p>Now after this, you can login to SSH on the server using new port, you can verify using : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh -p 12200 tech1@1.2.3.4<\/code><\/pre>\n\n\n\n<p>In above, -p 12200 tells to use port 12200 which we <a href=\"#sshPort\">set earlier<\/a>, it should login without asking password. <code>tech1<\/code> is the user we are using as example, <code>1.2.3.4<\/code> is IP of remote server. <\/p>\n\n\n\n<div style=\"height:45px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n<\/div><\/div>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"firewall\">Set up Firewall<\/h2>\n\n\n\n<p>Although you have taken basic measures to secure your server but you still need firewall to enhance the security further. A firewall can be piece of software or hardware which control access of services to and from your server from outside. A properly configured firewall helps to reduce security breaches in a server. For example, if you are running a public webserver and a private sql server then using firewall we can make sure only webserver is accessible from outside your network or server. <\/p>\n\n\n\n<p>Firewalls can be comprehensive and depends upon how you want to use them, however we will focus on basic security which you may use as base to start with.  Linux primarily uses iptables or more recently nftables for network packet filtering however, instead of manipulating them directly, we will explore ufw (Uncomplicated Firewall) for Debian \/ Ubuntu \/ Arch based Linux Distributions and FirewallD for RedHat based system such Fedora, CentOS, AlmaLinux etc. Both UFW and FirewallD act as frontend for lower level iptables \/ nftables packet filtering system. <\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\" id=\"ufw\">Configuring UFW (Uncomplicated Firewall)<\/h3>\n\n\n\n<p>UFW is fairly easy and recommended way to configure firewall in Debian and Ubuntu based Linux distributions. UFW comes by default in Ubuntu, however, you will need to install it on  Debian and other system. You can verify using following : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status<\/code><\/pre>\n\n\n\n<p>If you get error like <code>ufw: command not found<\/code>, you have to install it which is few seconds tasks.<\/p>\n\n\n\n<p><strong>Install in Debian \/ Ubuntu <\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get install ufw<\/code><\/pre>\n\n\n\n<p><strong>Install on Arch Linux<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo pacman -S ufw<\/code><\/pre>\n\n\n\n<p>Once installed, running command <code>sudo ufw status<\/code> should give output like following. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status\nStatus: inactive<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p>Now we know that ufw firewall is there and it is inactive, time to configure it. First we will set firewall to deny all incoming connections while allowing all outgoing connections. Our goal is to only allow access services those are necessary, we can also fine tune rules further to allow access to certain services from specified hosts etc. <\/p>\n\n\n\n<p>Setting up the default policies of deny all incoming connections to server while allowing all outgoing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw default allow outgoing<\/code><\/pre>\n\n\n\n<p>By default, ufw comes with various pre-defined list of applications, for example, allowing http will open port 80, while allowing https will open port 443 on server. You can see list of all predefined application profiles using: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw app list <\/code><\/pre>\n\n\n\n<p>Now lets allow http (port 80), https (port 443) and FTP (port 21) traffic. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow http\nsudo ufw allow https\nsudo ufw allow ftp<\/code><\/pre>\n\n\n\n<p>We can also enable incoming ssh traffic similar way if your sshd is listening on standard port 22, however, since in this tutorial we changed <a href=\"#ssh\">ssh port<\/a> (port 12200) earlier, to add custom ports, you can use following method: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 12200\/tcp<\/code><\/pre>\n\n\n\n<p><strong>Allow specific port ranges: <\/strong><\/p>\n\n\n\n<p>Sometimes for services like passive ftp connection, you have to open port range, for example we want to use 34000 to 35000 for passive ftp connection.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 34000:35000\/tcp<\/code><\/pre>\n\n\n\n<p><strong>Allow access from specific IP address: <\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow from 2.3.4.5<\/code><\/pre>\n\n\n\n<p><strong>Deny access from specific IP address:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw deny from 3.4.5.6<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<p>Although we have configured the ufw firewall, it is still not working, we need to enable it. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw enable<\/code><\/pre>\n\n\n\n<p>Now if we check the status of firewall using sudo <code>ufw status verbose<\/code>, we will get:<\/p>\n\n\n\n<p><em>Sample output: <\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Status: active\nLogging: on (low)\nDefault: deny (incoming), allow (outgoing), disabled (routed)\nNew profiles: skip\n\nTo                         Action      From\n--                         ------      ----\n22\/tcp                     ALLOW IN    Anywhere\n80\/tcp                     ALLOW IN    Anywhere\n443\/tcp                    ALLOW IN    Anywhere\n21\/tcp                     ALLOW IN    Anywhere\n20000:21000\/tcp            ALLOW IN    Anywhere\nAnywhere                   DENY IN     3.4.5.6\nAnywhere                   ALLOW IN    2.3.4.5\n22\/tcp (v6)                ALLOW IN    Anywhere (v6)\n80\/tcp (v6)                ALLOW IN    Anywhere (v6)\n443\/tcp (v6)               ALLOW IN    Anywhere (v6)\n21\/tcp (v6)                ALLOW IN    Anywhere (v6)\n34000:35000\/tcp (v6)       ALLOW IN    Anywhere (v6)<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\" id=\"firewalld\">Configuring Firewalld<\/h3>\n\n\n\n<p>Another most commonly used firewall utility or frontend for iptables \/ nftables is firewalld. Firewalld provides a dynamically managed firewall with support for network\/firewall zones that define the trust level of network connections or interfaces. It has support for IPv4, IPv6 firewall settings, ethernet bridges and IP sets. There is a separation of runtime and permanent configuration options. It also provides an interface for services or applications to add firewall rules directly.<\/p>\n\n\n\n<p>If above sounds little complicated, then don&#8217;t worry about it, since our objective is to only allow required traffic, we will explore most basic part. You may go for extensive version of firewalld configuration later if you need. <\/p>\n\n\n\n<p>Firewalld is default firewall application for RHEL 7 and newer CentOS 7 and newer, Fedora 18 and newer, SUSE 15 and newer, OpenSUSE 15 and newer. Though you can also install it on most of other distributions. <\/p>\n\n\n\n<p>If firewalld is not installed on your system, then you can install it using dnf.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install firewalld -y<\/code><\/pre>\n\n\n\n<p>Once installed, you need to enable the firewalld using systemctl and once enabled, it will automatically load not next server boot. Enable and start firewalld:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl enable firewalld<br>sudo systemctl start firewalld<\/code><\/pre>\n\n\n\n<p class=\"has-background has-small-font-size\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>You have to be careful before starting the firewall, incorrect configuration may lock you out from your server.<\/p>\n\n\n\n<p>Now, once you have firewall up and running, its time to configure it. its uses <code>firewall-cmd <\/code>command to carry out manipulation tasks. Firewalld uses zones which can be seen as group of firewall rules, for example, &#8220;home&#8221; zone can be used for when you are connecting to home network which is more trusted while can use &#8220;public&#8221; zone for a web-server where it runs public facing services. Firewalld comes with certain built in zones and you can select one which you find most suitable for your use-case.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --get-zones<\/code><\/pre>\n\n\n\n<p><em>Sample Output<\/em> : List of the available zones in firewalld. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>block dmz drop external home internal nm-shared public trusted work<\/code><\/pre>\n\n\n\n<p>Firewalld comes with &#8220;public&#8221; zone as default zone, you can verify it using <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --get-default-zone<\/code><\/pre>\n\n\n\n<p><em>Sample output : <\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public<\/code><\/pre>\n\n\n\n<p>In order to keep it simple, now we will go ahead and configure our firewall for &#8220;public&#8221; zone which is also our default zone. Any changes made to this will be automatically enforced in our firewall. <\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><strong>Allowing services in firewalld<\/strong><\/p>\n\n\n\n<p>Firewalld support predefined services like http, https, ftp, samba etc. (see all available services <code>sudo firewall-cmd --get--services<\/code>). For example, we want to enable access to http (port 80), https (port 443) on our server under public zone.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --add-service=http --add-service=https<\/code><\/pre>\n\n\n\n<p>On successful addition, it should greet you with messages <code>success<\/code>. In above, we are using <code>--permanent<\/code> so that changes we made to firewall are consistent on next firewall reload or server boot. <\/p>\n\n\n\n<p>In order to apply changes, we have reload the firewall.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --reload<\/code><\/pre>\n\n\n\n<p>Now you can verify changes by using following command : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --zone=public --list-all <\/code><\/pre>\n\n\n\n<p>Sample Output: It will show you state of &#8220;public&#8221; default services, along with the services we just enabled ie. https and http.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public (active)<br>target: default<br>icmp-block-inversion: no<br>interfaces: eth0<br>sources:<br>services: cockpit dhcpv6-client http https ssh<br>ports:<br>protocols:<br>forward: no<br>masquerade: no<br>forward-ports:<br>source-ports:<br>icmp-blocks:<br>rich rules:<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><strong>Removing services from firewalld<\/strong><\/p>\n\n\n\n<p>The way you have added services to firewall, you can also remove services easily. Just use <code>--remove-service=&lt;services_name&gt;<\/code> and you are done. For example, removing http service.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --remove-service=http<\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><strong>Adding or allowing ports in firewalld<\/strong><\/p>\n\n\n\n<p>The way you added services to firewalld, you can also allow custom ports. For example, we had configured port 12200 for ssh <a href=\"#sshPort\" data-type=\"internal\" data-id=\"#sshPort\">earlier<\/a> in this tutorial, hence default ssh services will not work here. Hence to add port 12200 permanently in &#8220;public&#8221; zone: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --add-port=12200\/tcp<\/code><\/pre>\n\n\n\n<p>If there is no error, then it should greet you with <code>success<\/code> message. In above, we we need to specify port protocol after port number, generally its either <code>tcp<\/code> or <code>udp<\/code>.<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><strong>Remove ports in firewalld<\/strong><\/p>\n\n\n\n<p>In same fashion, you can easily remove ports from firewalld. Lets say, we want to remove the port which just added above (12200) from &#8220;public&#8221; zone. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --remove-port=12200\/tcp <\/code><\/pre>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><strong>Add or allow port range in firewalld<\/strong><\/p>\n\n\n\n<p>Sometimes you need to allow port range, eg. you need to allow port 34000-35000 for your passive ftp connections. Other than allowing ftp service, you can run following command to allow above mentioned port range in firewalld. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --add-port=34000-35000<\/code><\/pre>\n\n\n\n<p class=\"has-background\" style=\"background-color:#f5f5f5\"><strong>Note:<\/strong> <br>You can omit the <code>--zone=public<\/code> part, and it will then add those rules to current default zone, in our case it would be &#8220;public&#8221;.<\/p>\n\n\n\n<p>There are certainly a lot more features in firewalld however, by now we have achieved basic firewall goal. Make sure you run <code>sudo firewall-cmd --reload<\/code> to apply the changes you made to firewalld so far.<\/p>\n<\/div><\/div>\n\n\n\n<div style=\"height:45px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"fail2ban\">Basic Intrusion detection and blocking using fail2ban <\/h2>\n\n\n\n<p>For securing Linux server, you can have firewall, disable unwanted services and also take multiple hardening steps but still there will be some of the public facing services like ssh, ftp etc. And there will always be bots and bad actors trying to gain access. Even though they will have all fail attempts but still hundreds or thousands of bots can eat up significant resources serving those failed requests.<\/p>\n\n\n\n<p>Here <a rel=\"noreferrer noopener\" href=\"http:\/\/www.fail2ban.org\/wiki\/index.php\/Main_Page\" target=\"_blank\">Fail2Ban<\/a> comes in play which is a log-parsing application that bans IP addresses from logging into your server after too many failed login attempts. For example, you can configure Fail2ban to block an IP from access to server if it makes 5 failed consecutive attempts in 30 mins. This way, legit users can still log into the server while bad-actors trying to brute-force will be blocked.<\/p>\n\n\n\n<p>For the sake of clarity, we have covered installation and configuration for various distribution in separate tutorials. Once you have have followed tutorial as per your Linux distribution you are using, mostly under 5 minutes you will be able to configure basic intrusion detection and blocking system ready for most common services like ssh, ftp, http authentication etc. As long as a service is using password based authentication with log files, you can configure fail2ban to monitor them.<\/p>\n\n\n\n<p>Here is the list of Fail2ban installation tutorial for : <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Configure Fail2ban on RedHat \/ CentOS \/ AlmaLinux \/ RockyLinux 8.x with firewalld integration<\/strong><\/li>\n\n\n\n<li><strong>Configure Fail2ban on Ubuntu \/ Debian \/ Arch Linux for brute force protection<\/strong><\/li>\n\n\n\n<li><strong>How to Install and Configure Fail2ban on CentOS 6 \/ 7.x<\/strong> <\/li>\n<\/ul>\n<\/div><\/div>\n\n\n\n<div style=\"height:45px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Final thought<\/h2>\n\n\n\n<p>The methods we used above should be considered as overview of security measures you can implement with your Linux servers. Implementations of above security practices should be considered as your Linux server&#8217;s security starting point and then as per your use-case or need you can enhance or tweak it. <\/p>\n\n\n\n<p>There could be many more ways to enhance security like &#8220;Enabling Automatic Updates&#8221; which will make sure that your system is always using latest packages and updates keeping it safe from most common software vulnerabilities with no or minimal intervention. <\/p>\n\n\n\n<p>You may also use firewall packages like <a rel=\"noreferrer noopener\" href=\"https:\/\/www.configserver.com\/cp\/csf.html\" data-type=\"URL\" data-id=\"https:\/\/www.configserver.com\/cp\/csf.html\" target=\"_blank\">CSF<\/a> which is a Stateful Packet Inspection (SPI) firewall, Login\/Intrusion Detection and Security application. It alone may replace functionalities of firewall like ufw, firewalld and intrusion detection like fail2ban.<\/p>\n\n\n\n<p>Remember, server security is an ongoing process and you have to keep it updated and tweaked as per your modification or configuration of your Linux server environment. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once you get an unmanaged server from MGCSpace.com, the first step you should perform is securing the server. In case of managed services, MGCSpace team will take of your server&#8217;s&hellip;<\/p>\n","protected":false},"author":1,"featured_media":72,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[12,8,11,10,9],"class_list":["post-76","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","tag-firewall","tag-firewalld","tag-ssh","tag-sudo","tag-ufw"],"_links":{"self":[{"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/posts\/76","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/comments?post=76"}],"version-history":[{"count":26,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/posts\/76\/revisions"}],"predecessor-version":[{"id":127,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/posts\/76\/revisions\/127"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/media\/72"}],"wp:attachment":[{"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/media?parent=76"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/categories?post=76"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mgcspace.com\/content\/wp-json\/wp\/v2\/tags?post=76"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}