blog/content/posts/iptables-basics.md
2024-10-20 15:54:18 -03:00

229 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

+++
date = '2024-10-20T14:22:33-03:00'
title = 'Mastering iptables: Basic Firewall Configurations for a Newly Deployed GNU/Linux Server'
description = "The basic usage of iptables for a new GNU/Linux webserver"
tags = [
"webserver",
"GNU/Linux",
"Basics Series",
]
+++
When setting up a new Linux server, one of the first things youll want to do is secure it by configuring a firewall. iptables, a powerful firewall tool available on most Linux distributions, is an excellent choice for managing traffic rules.
In this post, Ill walk you through setting up some basic iptables configurations for a freshly deployed server. By the end, youll have a solid firewall to protect your services while keeping things simple.
## What is iptables?
iptables is a command-line firewall utility that uses policy chains to manage network traffic. Each chain is a list of rules that apply to incoming and outgoing packets. You can filter traffic based on things like IP addresses, ports, and protocols.
Securing a server is a top priority for any sysadmin, and firewalls are one of the most important layers of defense. With iptables, you can:
- [ ] Block unwanted traffic
- [ ] Allow trusted connections (e.g., SSH, HTTP/HTTPS)
- [ ] Protect against DoS attacks and port scanning
- [ ] Log suspicious activity for future analysis
## How a packet flows in iptables
I highly suggest that you read more about the packet flow in iptables before applying firewall rules.
You can check those well made diagrams by [nerdalert on Github](https://gist.github.com/nerdalert/a1687ae4da1cc44a437d)
## Basic iptables Commands
Lets start with a quick overview of essential iptables commands:
### Show current rules:
```bash
iptables -L
```
### Flush (delete) all existing rules:
```bash
iptables -F
```
### Save iptables rules
If you are running Debian, you need to install the `iptables-persistent` package, and then you can use the following commands:
```bash
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
```
Restore iptables rules:
```bash
iptables-restore < /etc/iptables/rules.v4
ip6tables-restore < /etc/iptables/rules.v6
```
## Setting Up iptables for a New Server
Now, lets walk through some basic rules you can apply to secure your server right from the start. Well allow essential services like SSH and HTTP/HTTPS while blocking everything else.
### Step 1: Clear Existing Rules
Before setting up new rules, lets clear any pre-existing configurations:
```bash
iptables -F
```
This ensures youre starting with a clean slate.
Be careful with the following commands, since you can get locked you of your own server! That happens to every sysadmin sooner or later. The easiest way to be sure that it doesn't happen is to do it physically, or remotely via a KVM access.
### Step 2: Set Default Policies
Next, well define the default behavior for incoming, outgoing, and forwarded traffic. By default, its a good idea to block all incoming traffic and allow outgoing traffic:
```bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
```
This means any incoming connection will be dropped unless you explicitly allow it. Outgoing traffic, on the other hand, is allowed by default.
### Step 3: Allow SSH Traffic (Port 22)
Youll need SSH access to manage your server, so well allow traffic on port 22. Its important to only allow connections from trusted IP addresses, but for simplicity, well start by allowing all connections on SSH:
```bash
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
```
The `-A` is for "Append", this inserts the rule at the bottom, you can insert at the top with `-I` flag.
It is a good idea to always add comments to your rules, so in the future you can troubleshoot it faster.
In iptables, the syntax to add comments is as follows:
```bash
iptables -m comment --comment "Your comments here"
```
If you want to restrict SSH access to a specific IP (for example, your home IP), use this instead:
```bash
iptables -A INPUT -p tcp -s <your-ip-address> -m comment --comment "Allow SSH from my home IP" --dport 22 -j ACCEPT
```
### Step 4: Allow HTTP and HTTPS Traffic (Ports 80 and 443)
If youre running a web server, youll want to allow HTTP and HTTPS traffic:
```bash
iptables -A INPUT -m comment --comment "Allow HTTP" -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow HTTPS" -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow QUIC" -p udp --dport 443 -j ACCEPT
```
This allows visitors to access your website over both HTTP (port 80) and HTTPS (port 443).
The 443/udp port is for QUIC protocol, QUIC is a transport layer protocol developed by Google, designed for faster, more secure internet connections by combining features of TCP, TLS, and HTTP/2 with lower latency and improved performance. I highly suggest that you search more about this, maybe I write an article about it in the future.
### Step 5: Allow Loopback Traffic
Your server needs to communicate with itself via the loopback interface. Lets make sure traffic on lo is allowed:
```bash
iptables -A INPUT -m comment --comment "Allow loopback traffic" -i lo -j ACCEPT
```
### Step 6: Drop Invalid Packets
Invalid packets can often indicate an attack or misconfiguration, so its good practice to drop them:
```bash
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
```
### Step 7: Allow Established and Related Connections
To allow responses to outgoing connections (like when your server requests updates), youll need to allow established and related connections:
```bash
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```
This ensures your server can accept responses to any requests it makes.
### Step 8: Don't forget IPv6 rules!
For IPv6, the syntax is the same, you mostly need to change the command from `iptables` to `ip6tables`
The main difference is the ICMP protocol, you really need to allow ICMPv6 to your server function properly.
Here is a good starting point, where we explicity accept ICMPv6 control packets, while droppping all others.
```bash
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j DROP
```
### Step 9: Save Your iptables Rules
Once youve added all your rules, dont forget to save them. This ensures they persist after a reboot:
```bash
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
```
### Step 10: Testing Your Configuration
After setting up iptables, its a good idea to test it by attempting to connect to your server. You should be able to access SSH, HTTP, and HTTPS services while all other traffic is blocked.
## Summary
In summary, this is a good starting point for your rules, remember to save and test everything afterwards!
### IPv4
```bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p tcp -s <your-ip-address> -m comment --comment "Allow SSH from my home IP" --dport 22 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow HTTP" -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow HTTPS" -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow QUIC" -p udp --dport 443 -j ACCEPT
iptables -A INPUT -m comment --comment "Allow loopback traffic" -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables-save > /etc/iptables/rules.v4
```
### IPv6
```bash
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -p tcp -s <your-ip-address> -m comment --comment "Allow SSH from my home IP" --dport 22 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Allow HTTP" -p tcp --dport 80 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Allow HTTPS" -p tcp --dport 443 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Allow QUIC" -p udp --dport 443 -j ACCEPT
ip6tables -A INPUT -m comment --comment "Allow loopback traffic" -i lo -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables-save > /etc/iptables/rules.v6
```
## Conclusion
Congratulations! Youve successfully configured basic iptables rules for your newly deployed Linux server. By blocking all incoming traffic except for trusted services and connections, youve added a crucial layer of security to your server.