Back to Compendiums

How to configure firewalls for VPS security?

by matsjfunke

Introduction

Firewalls are essential for securing your Virtual Private Server because they act as a barrier between your server and potential threats from the internet. Firewalls allow you to block or accept incoming and outgoing network traffic. Most large hosting providers offer firewall configuration through their websites, but since servers are usually just Linux machines, you can also set up firewalls via the command line interface.

General Firewall Considerations

  1. Determine Necessary Services:

    Identify which services your VPS needs to provide (e.g., web server, SSH access) and ensure only those ports are open. Common ports include 80 and 443 for HTTP/HTTPS, and 22 for SSH.

  2. Block Unnecessary Ports:

    Close all ports that are not required for your server's operations to minimize potential attack vectors.

  3. Use Default Deny Policy:

    Implement a default deny policy where all incoming traffic is blocked by default, and only explicitly allowed traffic is permitted. This approach minimizes exposure to potential threats by ensuring only necessary services are accessible.

  4. Consider Rate Limiting:

    Implement rate limiting on services like SSH to prevent brute force attacks.

  5. Logging and Alerts:

    Enable logging for firewall activity and set up alerts for suspicious activities to respond quickly to potential threats.

Tools to Implement firewalls

iptables:

  • iptables is a legacy firewall system with linear rule processing, fragmented tooling (ip6tables, arptables), and performance limitations when handling complex configurations.
  • offers fine-grained control over network packet filtering

UFW:

  • Simplified and user-friendly, ideal for straightforward setups and beginners. It abstracts the complexity of iptables with easy-to-use commands.
bash
1# UFW Basic Commands
2ufw default deny incoming     # Block all incoming traffic
3ufw deny from 203.0.113.0/24  # Block traffic from a specific subnet
4ufw default allow outgoing    # Allow all outgoing traffic
5ufw allow ssh                 # Allow SSH (port 22)
6ufw allow http                # Allow HTTP (port 80)
7ufw allow https               # Allow HTTPS (port 443)
8ufw allow 53                  # Allow DNS
9ufw allow 25                  # Allow SMTP
10

nftables:

  • modern replacement for iptables, improved syntax and functionality
  • more powerful and flexible, suitable for complex configurations and advanced users. It offers improved syntax and functionality over iptables.

In nftables, a table is a container that organizes chains, typically by traffic type (e.g., inet for IPv4 and IPv6). A chain is a sequence of rules associated with specific network hooks (e.g., input, output) that determine how packets are processed. Rules are individual instructions within chains that specify criteria and actions for handling packets, such as accepting or dropping them.

nftables can be used in two ways:

  1. Command-Line Interface: Enter commands directly in the terminal for quick, interactive rule changes and testing.
bash
1# Flush Existing Rules
2nft flush ruleset
3
4# Create a Table
5nft add table inet filter
6
7# Create Chains
8nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
9nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
10nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
11
12# Allow Established Connections
13nft add rule inet filter input ct state {established, related} accept
14
15# Allow Loopback Traffic
16nft add rule inet filter input iifname lo accept
17
18# Allow Specific Services (like SSH, HTTP, and HTTPS)
19nft add rule inet filter input tcp dport {22, 80, 443} accept
20
21# Rate Limiting (SSH example)
22nft add rule inet filter input tcp dport 22 ct state new limit rate 15/minute accept
23
24# Logging
25nft add rule inet filter input counter log prefix "nftables drop: " drop
26
  1. Scripted Configuration: Use scripts for a consistent, repeatable setup, ideal for structured and automated deployments.

Create the script using vim: vim setup_nftables.sh then, add the following content to the script:

bash
1#!/usr/bin/env nft -f
2
3# Flush existing rules
4flush ruleset
5
6# Create a new table
7table inet filter {
8    # Create input chain
9    chain input {
10        type filter hook input priority 0;
11        policy drop; # Default deny policy for incoming traffic
12
13        # Allow established and related connections
14        ct state {established, related} accept
15
16        # Allow loopback interface traffic
17        iifname lo accept
18
19        # Allow SSH, HTTP, and HTTPS
20        tcp dport {22, 80, 443} accept
21    }
22
23    # Create forward chain
24    chain forward {
25        type filter hook forward priority 0;
26        policy drop; # Default deny policy for forwarded traffic
27    }
28
29    # Create output chain
30    chain output {
31        type filter hook output priority 0;
32        policy accept; # Default allow policy for outgoing traffic
33    }
34}
35
36# Rate limiting for SSH to prevent brute force attacks
37nft add rule inet filter input tcp dport 22 ct state new limit rate 15/minute accept
38
39# Logging for dropped packets
40nft add rule inet filter input counter log prefix "nftables drop: " drop
41

then make script executable and run it:

bash
1chmod +x setup_nftables.sh
2sudo ./setup_nftables.sh
3

Save the configuration to make these rules persistent across reboots

bash
1sudo cp setup_nftables.sh /etc/nftables.conf
2