{"id":11541,"date":"2025-05-13T08:00:30","date_gmt":"2025-05-13T08:00:30","guid":{"rendered":"https:\/\/www.ssdnodes.com\/?p=11541"},"modified":"2025-11-19T20:01:41","modified_gmt":"2025-11-19T20:01:41","slug":"vps-security-critical-steps-to-secure-vps-servers","status":"publish","type":"post","link":"https:\/\/www.ssdnodes.com\/blog\/vps-security-critical-steps-to-secure-vps-servers\/","title":{"rendered":"VPS Security: 6 Critical Steps to Secure Your VPS Servers"},"content":{"rendered":"<p>So, you just purchased a <strong><a href=\"http:\/\/ssdnodes.com\" target=\"_blank\" rel=\"noopener\">super reliable and affordable VPS<\/a><\/strong> from SSD Nodes, and you're now ready to deploy your applications or install <a href=\"https:\/\/www.ssdnodes.com\/blog\/what-is-self-hosting\/\">self-hosted<\/a> software. But wait, you need to put first things first, and you must secure your VPS. This guide will walk you through exactly that! I will show you all of the essential steps you must take for strong VPS security.<\/p>\n<h2>Why You Should Secure Your VPS Server<\/h2>\n<p>VPS Security gives back exactly what you put into it.<\/p>\n<p>No matter how small or big the project you\u2019re running on your VPS is, you need to be vigilant. Attackers are continually probing the entire internet for servers that they can easily commandeer, whether that\u2019s through misconfigured SSH, weak passwords, or security bugs in server-side software. Attackers look for easy targets, move quick, and leave a lot of damage in their wake.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11629 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/1-2.jpg\" alt=\"Secure Your VPS Server\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/1-2.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/1-2-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<h2>How to Secure Your VPS Servers<\/h2>\n<p>The goal of this guide is to give you easy-to-follow, high-value strategies for protecting your server. You should follow these steps when you first create an account with your VPS hosting provider and whenever you provision a new server. These tips will work on most VPS-hosted servers running one of the popular variants of Linux, such as Debian,Ubuntu, Fedora, or RockyLinux.<\/p>\n<p><strong>Note:<\/strong> This guide is just the start of server security, but by following these steps, you'll avoid being an easy target, which is a crucial first step. For a more in-depth guide, check out <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/7\/html-single\/security_guide\/index\" target=\"_blank\" rel=\"noopener\">Red Hat\u2019s security guidebook<\/a>.<\/p>\n<h2>Step 1) Perform Regular Security Updates<\/h2>\n<p>No matter what OS, software, and services you\u2019re using on your new server, you want to ensure that they\u2019re always up-to-date. The developers behind Linux distributions (Ubuntu, Debian, CentOS, and so on) are constantly updating software to patch and mitigate security issues. Not upgrading regularly can leave your server vulnerable to known, exploitable flaws. Luckily, most Linux distributions (and all those available through SSD Nodes) come with a package manager that makes updates incredibly easy.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11630 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/2-1.jpg\" alt=\"VPS Security Updates\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/2-1.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/2-1-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<h3>Ubuntu\/Debian<\/h3>\n<p>For Ubuntu\/Debian, the updating process uses a tool called <code>apt<\/code>.<\/p>\n<pre><code class=\"language-bash\">sudo apt update\r\nsudo apt upgrade<\/code><\/pre>\n<p>The first command updates the list of available software, and the second downloads and installs any new updates for software you currently have installed.<\/p>\n<h3>Rocky Linux\/AlmaLinux\/CentOS\/RHEL<\/h3>\n<p>For Rocky Linux, AlmaLinux, CentOS, and RHEL, the updating process uses a tool called <code>dnf<\/code>.<\/p>\n<pre><code class=\"language-bash\">sudo dnf check-update\r\n\r\nsudo dnf upgrade<\/code><\/pre>\n<p>The first command checks for updates and the second updates the list of available packages and installs any new updates for the software currently installed.<\/p>\n<h3>Avoid Installations With Deb\/Rpm<\/h3>\n<p>It can be tempting to use the tools behind these package management systems such as <code>deb<\/code> and <code>rpm<\/code> to install external packages. At SSD Nodes, we recommend against this practice, namely because it creates dependency issues if you aren\u2019t fully aware of the consequences of installing a certain package.<\/p>\n<p>As a rule of thumb, only install software with the appropriate package manager for your system: <code>apt<\/code> or <code>dnf<\/code>.<\/p>\n<p>If you must install software not in the package manager, you can use developer-created repositories like Ubuntu's PPAs, which integrate with the system for updates but come with lower security than official repositories.<\/p>\n<h3>Update Other Software<\/h3>\n<p>If your VPS server hosts a web app with its own package manager, like Node.js with <code>npm<\/code>, keep its packages updated. Popular platforms like WordPress also require timely updates due to their large codebases and frequent security patches.<\/p>\n<h2>Step 2) Implement Strong, Unique Passwords<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11631 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/3-1.jpg\" alt=\"VPS Passwords\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/3-1.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/3-1-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Before we dive into VPS-specific strategies, we need to talk about <a href=\"https:\/\/nordvpn.com\/cybersecurity\/what-is-cybersecurity\/\" target=\"_blank\" rel=\"noopener\">cybersecurity<\/a> at its most fundamental: passwords.<\/p>\n<p>There are three ways for attackers to successfully acquire your password to any service: they can make educated guesses based on what they learn about you as a person (your birthday, your favorite hobby, the name of your child), they can use computer programs that use \u201cbrute force\u201d by trying millions of passwords until one actually works, or they can download lists of common passwords in hope that you\u2019re the kind of person who uses \u201cpassword123\u201d on every website.<\/p>\n<p>It should come as no surprise then that the more complex your password is, the more difficult it will be to guess using any of two strategies. You want your passwords to be both strong and unique.<\/p>\n<h3>What Is a Strong Password?<\/h3>\n<p>Here at SSD Nodes, we have some general guidelines:<\/p>\n<ul>\n<li>A minimum of 10 characters<\/li>\n<li>No words you can find in a dictionary(\u201ccot,\u201d\"password,\u2019\u201ctree\u201d)<\/li>\n<li>No words or numbers that reference personal information, such as a birthday or the name of a child<\/li>\n<li>Both upper and lowercase letters<\/li>\n<li>At least one symbol (# $!% &amp;)<\/li>\n<\/ul>\n<h3>Why Does Uniqueness Matter?<\/h3>\n<p>You want to use a different password for every website. That way, if an attacker manages to figure out one of your passwords, they can\u2019t then use that same password to access all your other accounts. The same policy goes for your virtual private servers.<\/p>\n<h3>How Do I Create Strong, Unique Passwords?<\/h3>\n<p>The easiest way is using a password manager like LastPass or 1Password, which stores and generates strong passwords, requiring you to remember only a secure master password. Alternatively, you can create unique passwords using a pattern or mnemonic device.<\/p>\n<h3>Dashboard Area<\/h3>\n<p>To change your password on the SSD Nodes dashboard, visit\u00a0the <a href=\"https:\/\/www.ssdnodes.com\/manage\/index.php?rp=\/user\/password\">Change Password<\/a> page.<\/p>\n<p>You want to ensure that any user account that you\u2019ll use to connect to your server is protected with a strong password.<\/p>\n<p>The first time you connect to a newly-provisioned VPS, we recommend changing the root password. This can be done easily with the <code>passwd<\/code> command:<\/p>\n<pre><code class=\"language-bash\">$ passwd<\/code><\/pre>\n<h3>Two-factor Authentication<\/h3>\n<p>Two-factor authentication (2FA) is increasingly common for accounts holding sensitive information, like emails, and bank accounts. With 2FA enabled, you\u2019ll need both your password and another verification method, such as a code sent to your phone. This adds an extra layer of security, requiring attackers to compromise both your password and your physical device.<\/p>\n<p>For example, Facebook may send a 6-digit code to your phone if you log in from a new device. By entering the code, you prove your identity and gain access. SSD Nodes supports 2FA and strongly recommends enabling it for your dashboard account. Set it up by clicking your user icon, selecting <strong>Security settings<\/strong>, and following the prompts.<\/p>\n<p>For more details, check out our tutorial: <a href=\"https:\/\/www.ssdnodes.com\/blog\/ssd-nodes-enabling-2fa\/\"><em>Enabling Two-Factor Authentication with SSD Nodes<\/em><\/a>.<\/p>\n<h3>Database Passwords<\/h3>\n<p>Hackers will often probe for easy access to databases (such as MySQL), which they can use as an access point for the entire server.<br \/>\nAlways ensure your database root password is strong and unique.<\/p>\n<p>Later, we\u2019ll cover restricting access to MySQL\u2019s port (<code>3306<\/code>) for added security, but a strong password can deter further damage if your server is compromised.<\/p>\n<h2>Step 3) Use SSH Keys<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11632 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/4-2.jpg\" alt=\"Secure SSH Keys\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/4-2.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/4-2-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Secure Shell (SSH) is the primary way people connect to their servers. SSH is a secure,encrypted protocol on its own, but there is a way to make it even stronger: SSH authentication keys.<\/p>\n<p>Using authentication keys is similar to using 2FA on your SSD Nodes dashboard. Instead of relying solely on passwords to log into your server, you\u2019re using a secret key that only you have. You can even password-protect these keys for maximum security.<\/p>\n<h3>Generate an SSH Key Pair<\/h3>\n<p>On your Linux or OS X machine, you can create an SSH key pair using the <code>ssh-keygen<\/code> tool.<\/p>\n<p>Follow the prompts to create your public\/private key pair.<\/p>\n<p>On Windows machines, you can use <a href=\"https:\/\/www.putty.org\/\" target=\"_blank\" rel=\"noopener\">PuTTY<\/a>, our recommended tool for Windows users who want to connect to their VPS.<\/p>\n<p>For SSH keys that you\u2019ll use to log into your VPS and make administrative changes,install programs, or edit files, we highly recommend password-protecting this file. But, you can also opt to leave the key unprotected, which is more useful for tasks that need to be completed without your intervention, such as automated backups.<\/p>\n<p>Once you create the key, you can copy the public key to your server. This will allow you to log into your server using the SSH key rather than your user password. It\u2019s a far more secure method of connecting to your VPS, as someone would have to steal your SSH key to get in.<\/p>\n<h3>Disable Password-based Logins<\/h3>\n<p>After you have SSH-based logins working, you can disable password-based logins for an additional layer of security against brute-force attacks. However, before you do this, you want to be sure your SSH-based authentication is working, and that the user has <code>sudo<\/code> access. You will then want to edit the <code>\/etc\/sshd_config<\/code> file on your server so that both the <code>PermitRootLogin<\/code> and <code>PasswordAuthentication<\/code> lines are followed by no, as in the following:<\/p>\n<pre><code class=\"language-bash\">PermitRootLogin no\r\n\r\nPasswordAuthentication no<\/code><\/pre>\n<p>You\u2019ll then want to restart the SSH server with the following command: <code>sudo systemctl restart ssh<\/code>.<\/p>\n<p>For a more comprehensive look into SSH keys, how to set them up, and step-by-step directions of the entire process, visit our tutorial on the topic: <a href=\"https:\/\/www.ssdnodes.com\/blog\/connecting-vps-ssh-security\/\">SSH authentication setup and improved security<\/a>.<\/p>\n<p>Once these steps are complete, your server will be significantly more resilient to intrusion by brute-force attackers.<\/p>\n<h2>Step 4) Configure Your Firewall with nftables<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11633 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/5-2.jpg\" alt=\"Securing a VPS with Firewalls\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/5-2.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/5-2-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>The core of modern Linux firewall systems is <a href=\"https:\/\/wiki.nftables.org\/wiki-nftables\/index.php\/What_is_nftables%3F\" target=\"_blank\" rel=\"noopener\">nftables<\/a>, which replaces the legacy iptables framework. nftables offers several advantages:<\/p>\n<ul>\n<li>Simpler syntax and rule organization.<\/li>\n<li>Better performance.<\/li>\n<li>You only need one tool, <code>nft<\/code>, to add, edit, or delete rules.<\/li>\n<li>Better support for dynamic rule updates.<\/li>\n<li>Modern features like sets, maps, and concatenations; these tools let you create more efficient and powerful rules.<\/li>\n<li>Managing both IPv4 and IPv6 rules together is simpler than iptables.<\/li>\n<\/ul>\n<p><strong>Note:<\/strong> nftables can be difficult for those new to Linux administration, so many distributions come with a wrapper tool that helps make configuration easier. For example, Ubuntu comes with <code>ufw<\/code>, which offers a more user-friendly method of creating firewall rules. In Rocky Linux\/AlmaLinux\/RHEL distros, the default wrapper is <code>firewalld<\/code>.<\/p>\n<h3>Basic nftables Setup<\/h3>\n<p>First, make sure nftables is installed:<\/p>\n<pre><code class=\"language-bash\"># Ubuntu\/Debian\r\nsudo apt install nftables\r\nsudo systemctl enable nftables\r\nsudo systemctl start nftables\r\n\r\n# Rocky Linux\/AlmaLinux\/RHEL\r\nsudo dnf install nftables\r\nsudo systemctl enable nftables\r\nsudo systemctl start nftables<\/code><\/pre>\n<h3>Creating a Basic Firewall Configuration<\/h3>\n<p>Here's a basic secure configuration file (<code>\/etc\/nftables.conf<\/code>):<\/p>\n<pre><code>#!\/usr\/sbin\/nft -f\r\n\r\n# Clear any existing rules\r\nflush ruleset\r\n\r\n# Create a new table for filtering traffic\r\ntable inet filter {\r\n    # Input chain: handles incoming traffic\r\n    chain input {\r\n        type filter hook input priority 0;\r\n        policy drop;\r\n\r\n        # Allow traffic from established connections\r\n        ct state established,related accept\r\n\r\n        # Allow localhost traffic\r\n        iif lo accept\r\n\r\n        # Allow SSH (port 22)\r\n        tcp dport 22 accept\r\n\r\n        # Allow HTTP\/HTTPS (ports 80, 443)\r\n        tcp dport { 80, 443 } accept\r\n    }\r\n\r\n    # Output chain: handles outgoing traffic\r\n    chain output {\r\n        type filter hook output priority 0;\r\n        policy accept;\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Let's break it down line by line:<\/p>\n<ol>\n<li><code>#!\/usr\/sbin\/nft -f<\/code>: This tells the system to use <code>nft<\/code> to process this file<\/li>\n<li><code>flush ruleset<\/code>: Clears any existing rules to start fresh<\/li>\n<li><code>table inet filter<\/code>: Creates a table named \"filter\" that handles both IPv4 and IPv6 traffic\n<ul>\n<li><code>inet<\/code> means it handles both IPv4 and IPv6<\/li>\n<li><code>filter<\/code> is just the table name - you could name it anything<\/li>\n<\/ul>\n<\/li>\n<li>Inside the input chain:\n<ul>\n<li><code>type filter hook input<\/code> means these rules apply to incoming traffic<\/li>\n<li><code>policy drop<\/code> means \"deny all traffic by default\"<\/li>\n<li><code>ct state established,related accept<\/code> allows responses to come back for connections you initiated<\/li>\n<li><code>iif lo accept<\/code> allows traffic on the localhost interface (needed for many applications)<\/li>\n<li><code>tcp dport 22 accept<\/code> allows SSH connections<\/li>\n<li><code>tcp dport { 80, 443 } accept<\/code> allows web traffic (HTTP and HTTPS)<\/li>\n<\/ul>\n<\/li>\n<li>The output chain:\n<ul>\n<li><code>policy accept<\/code> means \"allow all outgoing traffic\"<\/li>\n<li>This is generally safe because connections have to be initiated from your server<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>To use this configuration:<\/p>\n<pre><code class=\"language-bash\"># Test the configuration\r\nsudo nft -c -f \/etc\/nftables.conf\r\n\r\n# If no errors, apply it\r\nsudo nft -f \/etc\/nftables.conf\r\n\r\n# View the current rules\r\nsudo nft list ruleset\r\n<\/code><\/pre>\n<p>This is a minimalist configuration that:<\/p>\n<ul>\n<li>Blocks all incoming traffic by default<\/li>\n<li>Allows SSH and web traffic<\/li>\n<li>Allows all outgoing traffic<\/li>\n<li>Maintains existing connections<\/li>\n<li>Works for both IPv4 and IPv6<\/li>\n<\/ul>\n<p>You can add more rules as needed, like:<\/p>\n<pre><code class=\"language-bash\"># Allow another port (example: for MySQL)\r\ntcp dport 3306 accept\r\n\r\n# Allow specific IP address\r\nip saddr &lt;YOUR-IP&gt; accept<\/code><\/pre>\n<h3>Allow Only a Certain IP Address to Access Your SSH Server<\/h3>\n<p>For extra SSH security, you can choose to allow only a specific IP address to access your SSH server while denying all other IPs, you can use the <code>ip saddr<\/code> (source IP address) match in your nftables rule:<\/p>\n<pre><code class=\"language-bash\">ip saddr &lt;YOUR-IP&gt; tcp dport 22 accept<\/code><\/pre>\n<p>Your updated <code>chain input<\/code> section of your <code>nftables<\/code> configuration would look this:<\/p>\n<pre><code># Input chain: handles incoming traffic\r\nchain input {\r\n    type filter hook input priority 0;\r\n    policy drop;\r\n\r\n    # Allow traffic from established connections\r\n    ct state established,related accept\r\n\r\n    # Allow localhost traffic\r\n    iif lo accept\r\n\r\n    # Allow SSH only from a specific IP\r\n    ip saddr <mark>&lt;YOUR-IP&gt;<\/mark> tcp dport 22 accept\r\n\r\n    # Allow HTTP\/HTTPS (ports 80, 443)\r\n    tcp dport { 80, 443 } accept\r\n}<\/code><\/pre>\n<p><strong>Note:<\/strong> Allowing SSH only from a specific IP is a great way to harden your server\u2019s security. It minimizes risk by restricting connections to trusted locations and devices. However, it can be limiting if your IP changes frequently, or if you need access from multiple devices or networks. This setup also requires careful testing, locking yourself out is easier than you think! So make sure you have a backup access method (e.g., a management console or an out-of-band connection).<\/p>\n<h3>Managing Rules<\/h3>\n<p>Here are some common <code>nftables<\/code> commands to help you manage your rules.<\/p>\n<p>To display the current ruleset:<\/p>\n<pre><code class=\"language-bash\">sudo nft list ruleset<\/code><\/pre>\n<p>To add a new rule, use <code>add<\/code>. For example, to allow MySQL traffic on port 3306:<\/p>\n<pre><code class=\"language-bash\">sudo nft add rule inet filter input tcp dport 3306 accept<\/code><\/pre>\n<p>To delete a rule, first, get the handle number of the rule:<\/p>\n<pre><code class=\"language-bash\">sudo nft -a list ruleset<\/code><\/pre>\n<p>Then, delete the rule using the handle number (replace <code>X<\/code> with the actual number):<\/p>\n<pre><code class=\"language-bash\">sudo nft delete rule inet filter input handle X<\/code><\/pre>\n<h3>Firewall Strategies<\/h3>\n<p>When it comes to setting up your firewall, there are two main approaches, similar to what you might already know from working with <code>iptables<\/code>. These approaches determine how your firewall treats traffic by default:<\/p>\n<ol>\n<li><strong>Default Drop (Recommended)<\/strong>\n<ul>\n<li>Deny all traffic by default.<\/li>\n<li>Explicitly allow needed services.<\/li>\n<li>This approach ensures that your server has a strong security baseline, but it does require careful planning to ensure that you don\u2019t accidentally block legitimate traffic or lock yourself out.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Default Accept<\/strong>\n<ul>\n<li>Allow all traffic by default.<\/li>\n<li>Block specific threats.<\/li>\n<li>This can be a good starting point for beginners or for less critical setups since it\u2019s easier to configure and less likely to cause access issues.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>Protip: Don\u2019t Get Locked Out!<\/h3>\n<p>Unfortunately, it\u2019s common for firewall beginners to lock themselves out of their VPS when creating new rules. In the worst-case scenario, you would need to reinstall your operating system from the SSD Nodes dashboard and begin again.<\/p>\n<p>To prevent a lockout, you can test the configuration without applying:<\/p>\n<pre><code class=\"language-bash\">sudo nft -c -f \/etc\/nftables.conf<\/code><\/pre>\n<p>It\u2019s a good idea to schedule <code>nftables<\/code> to restart a few minutes after making changes to the rules. This acts as a safety net. If you accidentally lock yourself out, the restart will revert to the saved configuration (if persistence is set up) or clear the active rules, giving you a fresh start.<\/p>\n<pre><code class=\"language-bash\">echo \"sudo systemctl restart nftables\" | at now + 5 minutes<\/code><\/pre>\n<h3>Persistence<\/h3>\n<p><code>nftables<\/code> rules are automatically persistent when managed through <code>systemd<\/code>.<\/p>\n<p>You can save the current ruleset using the following command:<\/p>\n<pre><code class=\"language-bash\">sudo nft list ruleset &gt; \/etc\/nftables.conf<\/code><\/pre>\n<p>Then enable automatic loading at boot:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl enable nftables<\/code><\/pre>\n<h3>Monitoring and Debugging<\/h3>\n<p>If you want to log dropped packets, you can add a rule like so:<\/p>\n<pre><code class=\"language-bash\">nft add rule inet filter input log prefix \\\"nftables-dropped: \\\" drop<\/code><\/pre>\n<p>The dropped packets are logged in <code>journalctl<\/code>:<\/p>\n<pre><code class=\"language-bash\">sudo journalctl -f<\/code><\/pre>\n<p>You can use the <code>nft monitor<\/code> command to get real-time information about changes to your firewall rules. It shows events like when rules are added, modified, or deleted, helping you track the changes in your firewall configuration:<\/p>\n<pre><code class=\"language-bash\">sudo nft monitor<\/code><\/pre>\n<p>Now that you've successfully configured your firewall with <code>nftables<\/code> and learned how to manage and monitor it, you're ready to move on to the next step: <strong>Limiting server-side application access to the internet<\/strong>. This is an important part of securing your server, as it allows you to control which applications or services can connect to the outside world.<\/p>\n<h2>Step 5) Limit Server-side Application Access to the Internet<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-11634 size-full\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/6-1.jpg\" alt=\"VPS Security: Limiting Internet Access\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/6-1.jpg 600w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/12\/6-1-300x200.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>If an application you\u2019re running on your VPS doesn\u2019t need to access the internet, you shouldn\u2019t let it. That\u2019s just common sense VPS security.<\/p>\n<p>Let\u2019s use a MySQL database as an example. Let\u2019s say you have a MySQL database connected to your WordPress blog. When someone visits your website and scopes out a few posts, they\u2019re not accessing your MySQL database directly. The WordPress application running on your VPS is actually doing the work to pull information from the database and display it on the user interface.<\/p>\n<p>In this setup, the MySQL database does not need to connect to the entire internet, only to WordPress. You should ensure the database refuses connections coming from outside the VPS itself.<\/p>\n<p>A simple way to do this is to edit the MySQL configuration file located in <code>\/etc\/mysql<\/code>. For MySQL 8.0+ the configuration file is located at:<\/p>\n<pre><code class=\"language-bash\">\/etc\/mysql\/mysql.conf.d\/mysqld.cnf<\/code><\/pre>\n<p>For MariaDB, this file is located at:<\/p>\n<pre><code class=\"language-bash\">\/etc\/mysql\/mariadb.conf.d\/50-server.cnf<\/code><\/pre>\n<p>You\u2019ll want to ensure that the <code>bind-address<\/code> setting points to what\u2019s called the loopback network device (essentially, the server itself).<\/p>\n<pre><code class=\"language-bash\">bind-address=127.0.0.1<\/code><\/pre>\n<h3>Using Firewalls for Securing Application Ports<\/h3>\n<p>Firewalls are also an effective method of preventing access to your server-side apps. For example, MySQL listens on the <code>3306<\/code> port for connections. It\u2019s possible to restrict this <code>3306<\/code> port directly, or restrict access based on groups. If you use the recommended <strong><em>Default Drop<\/em><\/strong> firewall setup, port <code>3306<\/code> will be blocked by default, and you should keep it that way!<\/p>\n<p><strong>Protip:<\/strong> For more detailed instructions on how to secure MySQL\/MariaDB, check out the <em>Securing The MariaDB Database Server<\/em> section in our <a href=\"https:\/\/www.ssdnodes.com\/blog\/installing-lamp-on-ubuntu-22-04-lts-jammy-jellyfish\/\">LAMP tutorial<\/a>. It details how to use the <code>mysql_secure_installation<\/code> script to improve your database\u2019s security by ensuring that root accounts have passwords, removes root accounts that are accessible from outside the server itself, removes anonymous users, and more.<\/p>\n<p>The MySQL example above is just a quick look into the <em>philosophy<\/em> behind limiting server-side applications from accessing the internet. There are too many other examples to possibly cover them here.<\/p>\n<p>But, keep in mind this rule: If an application or service doesn\u2019t <strong>need<\/strong> to directly access traffic from the internet, it shouldn\u2019t be allowed to.<\/p>\n<h2>Step 6) Block Intruders With fail2ban<\/h2>\n<p>As we\u2019ve said before, hackers are regularly probing servers-even those that rely on SSH keys rather than passwords-in search of ways to get access. Obviously,strong passwords and SSH key-based logins (while also disabling password-based logins) can help mitigate those issues, but it\u2019s also possible to prevent hackers from even trying a brute force attack to begin with.<\/p>\n<p>Enter <code>fai12ban<\/code>, an intrusion prevention system that blocks would-be intruders from gaining access to your server via a firewall. After a certain number of unsuccessful login attempts, that IP will automatically be added to a blocklist in the firewall, preventing any further access attempts.<\/p>\n<h3>Installing fail2ban<\/h3>\n<p>Before you install <code>fail2ban<\/code>, make sure you update your system packages then follow the instructions in this section.<\/p>\n<p>To install <code>fail2ban<\/code> on Debian\/Ubuntu:<\/p>\n<pre><code class=\"language-bash\">sudo apt install fail2ban<\/code><\/pre>\n<p>For Rocky Linux\/AlmaLinux\/RHEL, you need to enable the EPEL repository before installing <code>fail2ban<\/code>:<\/p>\n<pre><code class=\"language-bash\">sudo dnf install epel-release\r\nsudo dnf install fail2ban<\/code><\/pre>\n<h3>Start and Enable fail2ban<\/h3>\n<p>Once installed, start and enable the Fail2Ban service to ensure it runs on system boot:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl start fail2ban\r\nsudo systemctl enable fail2ban<\/code><\/pre>\n<p>Once installation completes, <code>fail2ban<\/code> will be running, and your VPS will immediately be more secure from automated tools that are trying to sneak their way in.<\/p>\n<h3>Verify Installation<\/h3>\n<p>Check if <code>fail2ban<\/code> is running correctly:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl status fail2ban<\/code><\/pre>\n<p>If the service is active, then you can use commands like <code>restart<\/code> to reload the service:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl restart fail2ban<\/code><\/pre>\n<h3>Configuring fail2ban<\/h3>\n<p>To customize Fail2Ban\u2019s behavior, such as setting the number of failed attempts before a ban or defining the ban duration, you\u2019ll need to edit its configuration file, often referred to as the \"jail file.\" Instead of modifying the default file directly, it\u2019s best practice to create a unique <code>.local<\/code> version for your server. To do this, copy the default configuration file to a <code>.local<\/code> file:<\/p>\n<pre><code class=\"language-bash\">sudo cp \/etc\/fail2ban\/jail.conf \/etc\/fail2ban\/jail.local<\/code><\/pre>\n<p>Then open it with your favorite editor, like <code>nano<\/code>.<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/fail2ban\/jail.local<\/code><\/pre>\n<p>Once you\u2019ve dialed in your configuration, just restart the fail2ban service:<\/p>\n<pre><code class=\"language-bash\"> sudo systemctl restart fail2ban<\/code><\/pre>\n<h3>Testing fail2ban<\/h3>\n<p>To test whether Fail2Ban is actively working, you can set up a test jail with shorter ban times for testing. Let\u2019s test with SSH.<\/p>\n<p>Open a new <code>sshd.local<\/code> configuration file:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/fail2ban\/jail.d\/sshd.local<\/code><\/pre>\n<p>Add the following:<\/p>\n<pre><code class=\"language-bash\">[sshd]\r\nenabled = true\r\nport = ssh\r\nfilter = sshd\r\nlogpath = %(syslog_authpriv)s\r\nmaxretry = 3\r\nfindtime = 300\r\nbantime = 300<\/code><\/pre>\n<ol>\n<li><strong><code>[sshd]<\/code><\/strong>defines settings specific to the SSH service.<\/li>\n<li><strong><code>enabled = true<\/code><\/strong> Activates this jail to monitor SSH login attempts.<\/li>\n<li><strong><code>port = ssh<\/code><\/strong> Monitors the default SSH port (port 22). You can specify a custom port if SSH runs on a different one (e.g., <code>port = 2222<\/code>).<\/li>\n<li><strong><code>filter = sshd<\/code><\/strong> Uses the <code>sshd<\/code> filter, which is a predefined Fail2Ban rule to identify failed SSH login attempts in the logs.<\/li>\n<li><strong><code>logpath<\/code><\/strong>Specifies the log file to monitor for SSH failures. In Fail2Ban, <code>%(syslog_authpriv)s<\/code> is a variable that dynamically points to the appropriate log file for authentication-related messages<\/li>\n<li><strong><code>maxretry = 3<\/code><\/strong> The number of failed login attempts allowed before the offending IP is banned.<\/li>\n<li><strong><code>findtime = 300<\/code><\/strong>The time window (in seconds) in which the <code>maxretry<\/code> attempts are counted. Here, 3 failures within 5 minutes (300 seconds) will trigger a ban.<\/li>\n<li><strong><code>bantime = 300<\/code><\/strong> The duration (in seconds) that the offending IP will remain banned. In this case, 5 minutes.<\/li>\n<\/ol>\n<p>Restart Fail2Ban:<\/p>\n<pre><code class=\"language-bash\"> sudo systemctl restart fail2ban<\/code><\/pre>\n<p>Now, on one terminal, you can watch real-time <code>fail2ban<\/code> logs:<\/p>\n<pre><code class=\"language-bash\">sudo tail -f \/var\/log\/fail2ban.log<\/code><\/pre>\n<p>On another terminal, you can monitor banned IPs:<\/p>\n<pre><code class=\"language-bash\">sudo fail2ban-client status sshd<\/code><\/pre>\n<p>Now try to connect to your server via SSH and use an incorrect passwords 3 times, you\u2019ll see the real-time logs reflecting the failed tries, and <code>\/var\/log\/fail2ban.log<\/code> will inform you that your IP is banned after 3 attempts:<\/p>\n<pre><code class=\"language-bash\">2024-12-16 22:52:06,517 fail2ban.actions        [15161]: NOTICE  [sshd] Ban your_IP_address<\/code><\/pre>\n<p>The output of <code>fail2ban-client status sshd<\/code> will include your IP in the banned IPs list:<\/p>\n<pre><code class=\"language-bash\">Status for the jail: sshd\r\n|- Filter\r\n|  |- Currently failed: 2\r\n|  |- Total failed: 6\r\n|  `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd\r\n`- Actions\r\n   |- Currently banned: 6\r\n   |- Total banned: 6\r\n   `- Banned IP list:  Banned_IP_1 Banned_IP_2 Banned_IP_3 your_IP_address<\/code><\/pre>\n<p>You may also see other IPs being banned in the same time-span, which tells you just how much the Internet is full of malicious bots.<\/p>\n<h3>Fail2ban Resources<\/h3>\n<p>For more information on fail2ban, check out the following resources:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/fail2ban\/fail2ban\/wiki\" target=\"_blank\" rel=\"noopener\">Official fail2ban Wiki<\/a><br \/>\n<a href=\"https:\/\/github.com\/fail2ban\/fail2ban\/wiki\/How-fail2ban-works\" target=\"_blank\" rel=\"noopener\">How fail2ban works<\/a><br \/>\n<a href=\"https:\/\/github.com\/fail2ban\/fail2ban\/wiki\/Proper-fail2ban-configuration\" target=\"_blank\" rel=\"noopener\">Proper fail2ban configuration<\/a><\/li>\n<\/ul>\n<h2>Beyond the 6 Steps to Secure Servers<\/h2>\n<p>This guide only covers six key steps for securing your new VPS-there are dozens, if not hundreds, more. Once you\u2019re finished with this guide, your VPS will be far more resilient to attack, but you can still take your security to the next level with additional resources.<\/p>\n<p>Thanks so much for reading, and congratulations on your new VPS!<\/p>\n<h3>Additional Security Measures<\/h3>\n<ul>\n<li>Turn off or uninstall unneeded services.<\/li>\n<li>Create unique user accounts for web server processes that have read access to only the relevant files\/directories.<\/li>\n<li>Restrict write access for web server users to all directories except when explicitly needed, such as for image uploads in WordPress.<\/li>\n<li>Change your SSH port to something other than 22, and then block 22 with your firewall.<\/li>\n<li>Enable automatic updates.<\/li>\n<li>Set up automated backups, and then test that they work!<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Protect your VPS like a pro! \ud83d\udee1\ufe0f Our step-by-step guide covers 6 critical steps to secure your server from vulnerabilities.<\/p>\n","protected":false},"author":19,"featured_media":11627,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[18,30],"tags":[],"class_list":["post-11541","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-tutorials"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/11541","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/comments?post=11541"}],"version-history":[{"count":15,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/11541\/revisions"}],"predecessor-version":[{"id":14686,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/11541\/revisions\/14686"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media\/11627"}],"wp:attachment":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media?parent=11541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/categories?post=11541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/tags?post=11541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}