Linux Firewalls
Netfilter Framework
Section titled “Netfilter Framework”Netfilter is the Linux kernel subsystem that provides network packet filtering, NAT, and other Packet manipulation. It is the foundation for all Linux firewall tools — iptables, nftables, Firewalld, and ufw are all frontends to Netfilter.
Netfilter defines five hook points in the network stack where packets can be inspected and modified:
flowchart LR
IN["Incoming Packet"] --> PRE["PREROUTING"]
PRE --> DECIDE{"Routing<br />Decision"}
DECIDE -->|Local| INPUT["INPUT"]
DECIDE -->|Forward| FORWARD["FORWARD"]
INPUT --> LOCAL["Local Process"]
LOCAL --> OUTPUT["OUTPUT"]
FORWARD --> POST["POSTROUTING"]
OUTPUT --> POST
POST --> OUT["Outgoing Packet"]| Hook | Triggers When |
|---|---|
| PREROUTING | Any incoming packet, before routing |
| INPUT | Packet destined for the local process |
| FORWARD | Packet being forwarded to another host |
| OUTPUT | Packet generated by local process |
| POSTROUTING | Any outgoing packet, after routing |
Tables
Section titled “Tables”| Table | Purpose |
|---|---|
| filter | Packet filtering (accept/drop/reject) |
| nat | Network Address Translation (SNAT/DNAT/masquerade) |
| mangle | Packet modification (TOS, TTL, marks) |
| raw | Connection tracking exemptions |
| security | LSM security hooks (used by SELinux/AppArmor) |
Chains
Section titled “Chains”Each table contains built-in chains that correspond to Netfilter hooks:
filter table: INPUT, FORWARD, OUTPUTnat table: PREROUTING, OUTPUT, POSTROUTINGmangle table: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTINGraw table: PREROUTING, OUTPUTsecurity table: INPUT, FORWARD, OUTPUTPacket Flow
Section titled “Packet Flow”Packet arrives on interface: 1. raw:PREROUTING. Connection tracking exemptions 2. mangle:PREROUTING. Packet marking 3. nat:PREROUTING. DNAT (destination NAT) 4. Routing decision. Local or forward?
If local: 5. mangle:INPUT. Packet marking 6. filter:INPUT. Filtering rules 7. Local process
If forward: 5. mangle:FORWARD. Packet marking 6. filter:FORWARD. Filtering rules
Local process generates packet: 8. raw:OUTPUT. Connection tracking exemptions 9. mangle:OUTPUT. Packet marking 10. nat:OUTPUT. DNAT for locally-generated packets 11. filter:OUTPUT. Filtering rules 12. Routing decision
Outgoing packet: 13. mangle:POSTROUTING. Final packet marking 14. nat:POSTROUTING. SNAT/MASQUERADEiptables
Section titled “iptables”Rule Syntax
Section titled “Rule Syntax”# Basic rule formatiptables -t TABLE -A CHAIN [matches] -j TARGET
# Add rule to INPUT chainiptables -A INPUT -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPT
# Insert at position (1 = first rule)iptables -I INPUT 1 -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPT
# Append to endiptables -A INPUT -j DROP
# Delete a rule (exact match)iptables -D INPUT -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPT
# Delete by line numberiptables -D INPUT 3
# List rulesiptables -L -n -viptables -L INPUT -n -v --line-numbers
# Flush all rules in a chainiptables -F INPUTiptables -F # flush all chains
# Delete user-defined chainsiptables -X
# Set default policyiptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPTCommon Matches
Section titled “Common Matches”# Source/destination address-s 10.0.0.0/24 # source network-d 10.0.0.1 # destination IP! -s 10.0.0.0/24 # NOT from this network
# Protocol-p tcp # TCP protocol-p udp # UDP protocol-p icmp # ICMP protocol-p all # all protocols
# Ports (requires -p tcp or -p udp)--sport 22 # source port--dport 22 # destination port--dport 80:1024 # port range--dport 80,443 # multiple ports (multiport match)-m multiport --dports 80,443,8080 # up to 15 ports
# Interface-i eth0 # input interface-o eth1 # output interface
# State (connection tracking)-m state --state ESTABLISHED,RELATED-m conntrack --ctstate ESTABLISHED,RELATED # newer syntax
# TCP flags-p tcp --tcp-flags SYN,RST,ACK SYN # SYN packets only-p tcp --syn # shorthand for above
# ICMP types-p icmp --icmp-type echo-request-p icmp --icmp-type echo-reply-p icmp --icmp-type destination-unreachable
# MAC address-m mac --mac-source aa:bb:cc:dd:ee:ff
# Comment-m comment --comment "Allow SSH from office"
# Limit (rate limiting)-m limit --limit 10/minute --limit-burst 5
# Recent (dynamic block list)-m recent --set --name SSH-m recent --update --seconds 60 --hitcount 4 --name SSH
# Owner (OUTPUT chain only)-m owner --uid-owner 1000-m owner --gid-owner 1000
# IP range-m iprange --src-range 10.0.0.1-10.0.0.50Common Targets
Section titled “Common Targets”-j ACCEPT # allow the packet-j DROP # silently discard-j REJECT # discard and send error response-j LOG # log to syslog (then continue to next rule)-j RETURN # return to calling chain-j DNAT # destination NAT-j SNAT # source NAT-j MASQUERADE # source NAT (auto-detect outgoing IP)-j REDIRECT # redirect to local port-j MARK # set packet mark-j QUEUE # send to userspace (NFQUEUE)Connection Tracking
Section titled “Connection Tracking”# Connection statesNEW # new connectionESTABLISHED # established connection (bidirectional traffic seen)RELATED # related to an established connection (FTP data, ICMP errors)INVALID # not matching any known connectionUNTRACKED # exempted from tracking (raw table NOTRACK)
# Allow established and related connectionsiptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Drop invalid packetsiptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# View connection tracking tableconntrack -Lconntrack -L -s 10.0.0.50conntrack -L -d 10.0.0.1 -p tcp --dport 443
# Adjust conntrack limitssysctl -w net.netfilter.nf_conntrack_max=262144sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=7200
# Connection tracking timeout (seconds)cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established# 432000 (5 days default)NAT Types
Section titled “NAT Types”# SNAT — Source NAT (change source IP for outgoing packets)iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j SNAT --to-source 203.0.113.1
# MASQUERADE — SNAT with auto-detection of outgoing IP (for dynamic IPs)iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# DNAT — Destination NAT (redirect incoming packets to internal host)iptables -t nat -A PREROUTING -d 203.0.113.1 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.10:80
# REDIRECT — redirect to local portiptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
# Port forwarding (external:80 to internal:8080)iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.10:8080iptables -t nat -A POSTROUTING -j MASQUERADE
# Enable IP forwarding for NATsysctl -w net.ipv4.ip_forward=1echo "net.ipv4.ip_forward=1' >> /etc/sysctl.d/99-forward.confLogging
Section titled “Logging”# LOG target (packet continues to next rule after logging)iptables -A INPUT -p tcp --dport 22 -j LOG --log-prefix "[SSH] " --log-level 4
# NFLOG (more efficient, sends to netlink)iptables -A INPUT -j NFLOG --nflog-group 1
# ulogd for logging to files/databases# /etc/ulogd.conf# log to /var/log/ulogd.log
# View firewall logsjournalctl -k | grep "SSH"dmesg | grep "SSH"Rate Limiting
Section titled “Rate Limiting”# Limit new SSH connections to 10 per minute, burst of 5iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \ -m limit --limit 10/minute --limit-burst 5 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -j DROP
# Using recent module — block after 4 failed attempts in 60 secondsiptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \ -m recent --set --name SSHiptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \ -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP
# Using hashlimit — limit per source IPiptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW \ -m hashlimit --hashlimit-above 100/sec --hashlimit-mode srcip \ --hashlimit-name http_limit --hashlimit-burst 200 -j DROPnftables
Section titled “nftables”nftables is the modern successor to iptables, providing better performance, a cleaner syntax, and Atomic rule replacement.
Basic Usage
Section titled “Basic Usage”# List the current rulesetnft list ruleset
# Create a tablenft add table inet filter
# Create chainsnft add chain inet filter input { type filter hook input priority 0 \; }nft add chain inet filter forward { type filter hook forward priority 0 \; }nft add chain inet filter output { type filter hook output priority 0 \; }
# Add rulesnft add rule inet filter input ct state established,related acceptnft add rule inet filter input iif lo acceptnft add rule inet filter input icmp type echo-request limit rate 5/second acceptnft add rule inet filter input tcp dport { 22, 80, 443 } acceptnft add rule inet filter input counter reject
# Set default policynft chain inet filter input { type filter hook input priority 0 \; policy drop \; }Sets and Maps
Section titled “Sets and Maps”# Create a named setnft add set inet filter allowed_ports { type inet_service \; elements = { 22, 80, 443 } }
# Use the set in a rulenft add rule inet filter input tcp dport @allowed_ports accept
# Create a set for IP addressesnft add set inet filter office_ips { type ipv4_addr \; }nft add element inet filter office_ips { 10.0.0.0/24, 192.168.1.0/24 }
# Use the IP setnft add rule inet filter input ip saddr @office_ips accept
# Named maps (value mapping)nft add map inet filter port_forward { type inet_service : ipv4_addr \; }nft add element inet filter port_forward { 80 : 10.0.0.10, 443 : 10.0.0.11 }
# Verdict maps (map input to action)nft add map inet filter verdict_map { type ipv4_addr : verdict \; }nft add element inet filter verdict_map { 10.0.0.50 : accept, 192.168.1.0/24 : drop }nft add rule inet filter input ip saddr vmap @verdict_mapConcatenations
Section titled “Concatenations”# Multi-dimensional sets (match on IP + port)nft add set inet filter services { type ipv4_addr . inet_service \; }nft add element inet filter services { 10.0.0.10 . 80, 10.0.0.10 . 443 }
# Rule using concatenationnft add rule inet filter input ip saddr . tcp dport @services acceptRuleset File
Section titled “Ruleset File”# Flush and reload from filenft flush rulesetnft -f /etc/nftables.conf#!/usr/sbin/nft -f
table inet filter { set allowed_tcp_ports { type inet_service elements = { 22, 80, 443 } }
set allowed_ips { type ipv4_addr elements = { 10.0.0.0/24, 127.0.0.0/8 } }
chain input { type filter hook input priority 0; policy drop;
ct state established,related accept ct state invalid counter drop iif lo accept ip saddr @allowed_ips accept tcp dport @allowed_tcp_ports accept icmp type echo-request limit rate 5/second accept counter reject with icmpx type admin-prohibited }
chain forward { type filter hook forward priority 0; policy drop; }
chain output { type filter hook output priority 0; policy accept; }}NAT with nftables
Section titled “NAT with nftables”# Masquerading (SNAT with auto IP detection)nft add table ip natnft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }nft add rule ip nat postrouting masquerade
# DNAT (port forwarding)nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }nft add rule ip nat prerouting iif eth0 tcp dport 80 dnat to 10.0.0.10:8080
# SNAT (static source NAT)nft add rule ip nat postrouting ip saddr 10.0.0.0/24 snat to 203.0.113.1nftables vs iptables
Section titled “nftables vs iptables”| Aspect | iptables | nftables |
|---|---|---|
| Syntax | Multiple commands | Single atomic ruleset |
| Performance | Linear rule evaluation | Better (sets, maps, concatenations) |
| IPv4/IPv6 | Separate commands | Unified inet family |
| Atomic updates | No (rules applied one by one) | Yes (entire ruleset replaced atomically) |
| Extensibility | Kernel modules | Extensible expressions |
| Configuration | Scattered across commands | Single file |
| Connection tracking | Same backend (nf_conntrack) | Same backend |
# Convert iptables rules to nftablesiptables-save > /tmp/iptables.rules# nftables can import iptables rules for compatibility# But native nftables syntax is recommended for new deploymentsfirewalld
Section titled “firewalld”firewalld is a dynamic firewall manager that uses nftables (or iptables) as a backend and Provides a zone-based configuration model.
Zones define trust levels: drop — all incoming packets dropped, only outgoing block — incoming rejected (ICMP error), only established public — don't trust, selected incoming connections external — masquerading enabled, selected incoming dmz — limited access from public work — mostly trusted, selected incoming home — mostly trusted, most incoming internal — fully trusted, all incoming trusted — all connections acceptedCommands
Section titled “Commands”# View active zonesfirewall-cmd --get-active-zones
# View current configurationfirewall-cmd --list-allfirewall-cmd --list-all --zone=public
# Set default zonefirewall-cmd --set-default-zone=public
# Add a servicefirewall-cmd --permanent --zone=public --add-service=httpfirewall-cmd --reload
# Add a portfirewall-cmd --permanent --zone=public --add-port=8080/tcpfirewall-cmd --reload
# Add a port rangefirewall-cmd --permanent --zone=public --add-port=5000-5100/tcp
# Remove a servicefirewall-cmd --permanent --zone=public --remove-service=httpfirewall-cmd --reload
# Rich rules (advanced)firewall-cmd --permanent --zone=public \ --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" service name="ssh" accept'
firewall-cmd --permanent --zone=public \ --add-rich-rule='rule family="ipv4" source address="10.0.0.50" forward-port port="80" protocol="tcp" to-port="8080"'
# Port forwardingfirewall-cmd --permanent --zone=public \ --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=10.0.0.10
# Masqueradingfirewall-cmd --permanent --zone=external --add-masquerade
# Direct rules (pass-through to nftables/iptables)firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 9090 -j ACCEPT
# Panic mode (drop all traffic)firewall-cmd --panic-onfirewall-cmd --panic-off
# Runtime-only changes (lost on reload)firewall-cmd --add-port=9999/tcp
# List all servicesfirewall-cmd --get-services
# Lockdown (restrict firewall changes to authorized users)firewall-cmd --lockdown-onfirewalld Configuration Files
Section titled “firewalld Configuration Files”<?xml version="1.0" encoding="utf-8"?><zone> <short>Public</short> <description>For use in public areas.</description> <service name="ssh"/> <service name="http"/> <service name="https"/> <port protocol="tcp" port="8080"/> <rule family="ipv4"> <source address="10.0.0.0/24"/> <service name="mysql"/> <accept/> </rule></zone>ufw (Uncomplicated Firewall) is a user-friendly frontend for iptables/nftables.
Commands
Section titled “Commands”# Enable/disableufw enableufw disable
# Set default policyufw default deny incomingufw default allow outgoing
# Allow/deny servicesufw allow sshufw allow httpufw allow httpsufw deny 22/tcp
# Allow specific portsufw allow 8080/tcpufw allow 53/udpufw allow 60000:61000/tcp
# Allow from specific sourceufw allow from 10.0.0.0/24 to any port 22ufw allow from 10.0.0.50 to any port 3306
# Delete rulesufw delete allow httpufw delete allow from 10.0.0.0/24 to any port 22
# Limit (rate limiting — useful for SSH)ufw limit ssh# Blocks if more than 6 connections in 30 seconds
# Route (forwarding)ufw route allow in on eth0 out on eth1 to 10.0.0.0/24 port 80
# NAT/masquerading# /etc/ufw/sysctl.conf: net.ipv4.ip_forward=1# /etc/ufw/before.rules: add NAT rulesufw reload
# Application profilesufw app listufw allow 'Nginx Full'ufw allow 'OpenSSH'
# Statusufw statusufw status verboseufw status numbered
# Resetufw reset # removes all rules and resets to defaults
# Loggingufw logging onufw logging lowufw logging mediumufw logging highufw logging fullCustom Application Profiles
Section titled “Custom Application Profiles”[MyApp]title=My Applicationdescription=Custom application firewall rulesports=8080/tcp|9090/tcpCommon Firewall Patterns
Section titled “Common Firewall Patterns”Web Server
Section titled “Web Server”# iptablesiptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPTiptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPTiptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPTiptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPTiptables -A INPUT -j DROPiptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPTSSH Hardening
Section titled “SSH Hardening”# iptables — limit SSH to specific network and rate-limitiptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/24 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \ -m recent --set --name sshiptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \ -m recent --update --seconds 60 --hitcount 4 --name ssh -j DROPiptables -A INPUT -p tcp --dport 22 -j DROPNAT Gateway
Section titled “NAT Gateway”# Enable forwardingecho 1 > /proc/sys/net/ipv4/ip_forward
# NAT for internal networkiptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADEiptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPTiptables -A FORWARD -i eth0 -o eth1 -j ACCEPTFirewall Troubleshooting
Section titled “Firewall Troubleshooting”# List all rules with packet countersiptables -L -n -v --line-numbersnft list ruleset
# Check connection trackingconntrack -Lconntrack -L -s 10.0.0.50conntrack -E # watch events in real-time
# Count dropped packetsiptables -L INPUT -n -v | grep DROPnft list chain inet filter input | grep counter
# Trace packet pathiptables -t raw -A PREROUTING -p tcp --dport 80 -j TRACE# Check dmesg for trace outputdmesg | grep TRACE
# Packet capture on specific interfacetcpdump -i eth0 -nn port 80
# Check if a specific rule matchesiptables -A INPUT -s 10.0.0.50 -j LOG --log-prefix "[TEST] "# Then check: dmesg | grep TEST
# Verify the kernel module is loadedlsmod | grep nf_modprobe nf_conntrackmodprobe nf_nat
# Reset all rules (emergency)iptables -Fiptables -Xiptables -t nat -Fiptables -t nat -Xiptables -P INPUT ACCEPTiptables -P FORWARD ACCEPTiptables -P OUTPUT ACCEPTCommon Pitfalls
Section titled “Common Pitfalls”Pitfall: Rule Order Matters
Section titled “Pitfall: Rule Order Matters”# WRONG — DROP comes before ACCEPT, so SSH is blockediptables -A INPUT -p tcp --dport 22 -j DROPiptables -A INPUT -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPT
# CORRECT — ACCEPT comes before DROPiptables -A INPUT -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -j DROP
# Use -I to insert at the topiptables -I INPUT 1 -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPTPitfall: Forgetting to Save Rules
Section titled “Pitfall: Forgetting to Save Rules”# iptables rules are lost on reboot unless saved
# Debian/Ubuntuiptables-save > /etc/iptables/rules.v4# Or install iptables-persistentapt-get install iptables-persistent
# RHEL/CentOSiptables-save > /etc/sysconfig/iptables# Or use firewalld/nftables which persist automatically
# nftables — save rulesetnft list ruleset > /etc/nftables.confPitfall: conntrack Table Full
Section titled “Pitfall: conntrack Table Full”# If the conntrack table fills up, new connections are droppeddmesg | grep "nf_conntrack: table full"cat /proc/sys/net/netfilter/nf_conntrack_max
# Increase the limitsysctl -w net.netfilter.nf_conntrack_max=262144echo 'net.netfilter.nf_conntrack_max=262144' >> /etc/sysctl.d/99-conntrack.conf
# Reduce timeouts for faster cleanupsysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600Pitfall: Loopback Interface
Section titled “Pitfall: Loopback Interface”# Always allow loopback trafficiptables -A INPUT -i lo -j ACCEPTiptables -A OUTPUT -o lo -j ACCEPT
# Without this, many local services break:# - Database connections to localhost# - Application health checks# - systemd socket activationPitfall: REJECT vs DROP
Section titled “Pitfall: REJECT vs DROP”# DROP — silently discard (no response)# Pro: harder to scan/discover services# Con: clients hang until timeout
# REJECT — send ICMP port unreachable# Pro: clients get immediate feedback# Con: reveals that a host exists and has a firewall
# Best practice: use DROP for INPUT, REJECT for specific casesiptables -A INPUT -j DROPiptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-resetPitfall: Mixing iptables and nftables
Section titled “Pitfall: Mixing iptables and nftables”# iptables and nftables use the same Netfilter backend# Rules from both are applied, which can cause unexpected behavior
# Check which backend is activeiptables --versionnft --version
# On modern systems, iptables may be a compatibility layer over nftablesiptables-legacy --version # original iptablesiptables-nft --version # iptables using nftables backend
# Recommendation: choose one and stick with it# New deployments: nftables# Legacy systems: iptables (plan migration to nftables)Advanced Firewall Patterns
Section titled “Advanced Firewall Patterns”IPv6 Firewalling
Section titled “IPv6 Firewalling”# iptables IPv6 uses ip6tablesip6tables -A INPUT -p ipv6-icmp -j ACCEPTip6tables -A INPUT -i lo -j ACCEPTip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTip6tables -A INPUT -p tcp --dport 22 -j ACCEPTip6tables -A INPUT -j DROP
# nftables handles both IPv4 and IPv6 with the inet familynft add rule inet filter input ip6 nexthdr icmpv6 acceptnft add rule inet filter input ip6 nexthdr icmpv6 icmpv6 type echo-request acceptBridge Filtering (ebtables/nftables)
Section titled “Bridge Filtering (ebtables/nftables)”# Filter traffic between VMs on the same bridge# Using nftables bridge familynft add table bridge filternft add chain bridge filter forward { type filter hook forward priority 0 \; }nft add rule bridge filter forward ether type ip ip daddr 10.0.0.1 drop
# Isolate guest VMs from each othernft add rule bridge filter forward iifname != vnet0 dropIP Sets for Large Block Lists
Section titled “IP Sets for Large Block Lists”# Create an IP set for blocking known bad IPsipset create blacklist hash:ip hashsize 4096 maxelem 100000
# Add IPsipset add blacklist 192.0.2.1ipset add blacklist 198.51.100.0/24
# Use in iptablesiptables -A INPUT -m set --match-set blacklist src -j DROP
# Save and restoreipset save > /etc/ipset.confipset restore < /etc/ipset.conf
# Automatically update from a threat feed#!/usr/bin/env bashipset create blacklist hash:ip hashsize 4096 maxelem 100000curl -s https://feeds.example.com/threat-list.txt | \ while read -r ip; do ipset add blacklist "$ip"; doneFail2ban Integration with nftables
Section titled “Fail2ban Integration with nftables”[DEFAULT]banaction = nftables-multiportbanaction_allports = nftables-allports
[sshd]enabled = trueport = sshmaxretry = 3findtime = 600bantime = 3600Network Segmentation with Zones
Section titled “Network Segmentation with Zones”# Example: three-zone firewall (DMZ, internal, management)# Using nftables
nft add table inet firewall
# Define setsnft add set inet firewall dmz_hosts { type ipv4_addr \; }nft add set inet firewall internal_hosts { type ipv4_addr \; }nft add set inet firewall mgmt_hosts { type ipv4_addr \; }nft add set inet firewall dmz_ports { type inet_service \; elements = { 80, 443 } }nft add set inet firewall internal_ports { type inet_service \; elements = { 22, 3306, 6379 } }
# Input chainnft add chain inet firewall input { type filter hook input priority 0 \; policy drop \; }nft add rule inet firewall input iif lo acceptnft add rule inet firewall input ct state established,related acceptnft add rule inet firewall input ct state invalid drop
# DMZ zone — allow web traffic from anywherenft add rule inet firewall input ip saddr @dmz_hosts tcp dport @dmz_ports accept
# Internal zone — allow from internal hosts onlynft add rule inet firewall input ip saddr @internal_hosts tcp dport @internal_ports accept
# Management zone — allow SSH from management hosts onlynft add rule inet firewall input ip saddr @mgmt_hosts tcp dport 22 accept
# Forward chain — zone isolationnft add chain inet firewall forward { type filter hook forward priority 0 \; policy drop \; }nft add rule inet firewall forward ct state established,related accept
# DMZ can talk to internal on specific portsnft add rule inet firewall forward ip saddr @dmz_hosts ip daddr @internal_hosts tcp dport 3306 accept
# Internal can talk to DMZ on web portsnft add rule inet firewall forward ip saddr @internal_hosts ip daddr @dmz_hosts tcp dport @dmz_ports acceptLogging and Alerting
Section titled “Logging and Alerting”# Log dropped packets with rate limiting (prevent log flooding)iptables -A INPUT -j LOG -m limit --limit 10/minute --limit-burst 5 \ --log-prefix "[FW DROP] " --log-level 4
# Log specific suspicious patternsiptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG \ --log-prefix "[FW SCAN] "
# nftables loggingnft add rule inet filter input counter log prefix "DROP: " level warn
# Send logs to a dedicated file# /etc/rsyslog.d/30-firewall.conf:msg, contains, "[FW DROP]" -/var/log/firewall.log& stopDDoS Mitigation
Section titled “DDoS Mitigation”# SYN flood protectioniptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROPiptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROP
# Limit new connections per source IPiptables -A INPUT -p tcp --syn -m hashlimit \ --hashlimit-above 10/sec --hashlimit-burst 20 \ --hashlimit-mode srcip --hashlimit-name syn_flood -j DROP
# Limit ICMP (prevent ping floods)iptables -A INPUT -p icmp --icmp-type echo-request -m limit \ --limit 1/s --limit-burst 5 -j ACCEPTiptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# nftables SYN flood protectionnft add rule inet filter input tcp flags syn tcp dport != 0 \ meter synflood { ip saddr timeout 10s limit rate 10/second } acceptnft add rule inet filter input tcp flags syn tcp dport != 0 dropSummary
Section titled “Summary”This topic covers the core concepts of linux firewalls, including underlying theory, practical implementation, and key applications.
Key concepts include:
- TCP/IP and the OSI model
- network topologies
- protocols (HTTP, FTP, SMTP)
- encryption and security
- client-server and peer-to-peer
Understanding these concepts thoroughly is essential for both examinations and practical programming, and requires both theoretical knowledge and hands-on practice.
Worked Examples
Section titled “Worked Examples”Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.