Skip to content

Instantly share code, notes, and snippets.

@skinsch
Last active June 19, 2023 18:58
Show Gist options
  • Save skinsch/b6c311937f1a969412776ccea9ff3557 to your computer and use it in GitHub Desktop.
Save skinsch/b6c311937f1a969412776ccea9ff3557 to your computer and use it in GitHub Desktop.
IP Tables Cheat Sheet
FirewallD and IPTables Cheat Sheet (Rev: 20230619)
GET FIREWALL STATE
firewall-cmd --state
GET FIREWALL STATUS
systemctl status firewalld
RELOAD
firewall-cmd --reload
GET ALL PERMANENT DIRECT RULES
firewall-cmd --permanent --direct --get-all-rules
GET DEFAULT ZONE
firewall-cmd --get-default-zone
GET ACTIVE ZONES
firewall-cmd --get-active-zones
ADD AN INTERFACE TO A ZONE
firewall-cmd --permanent --zone=public --add-interface=eth0
firewall-cmd --permanent --zone=dmz --add-interface=eth1
LIST ALL RULES FOR A ZONE
firewall-cmd --zone=public --list-all
LIST ALL PUBLIC OPEN PORTS
firewall-cmd --zone=public --list-ports
ALLOW HTTP/HTTPS TO BE PUBLIC (for example 80)
firewall-cmd --permanent --zone=public --add-port=80/tcp
REMOVE PORTS FROM PUBLIC ZONE (for example 80)
firewall-cmd --permanent --zone=public --remove-port=80/tcp
How to Block outbound Access that's not part of your network
REMOVE EXISTING DIRECT OUTPUT RULES THEN ADD WHAT SHOULD BE ACCEPTABLE
firewall-cmd --permanent --direct --remove-rules ipv4 filter OUTPUT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -m state --state RELATED,ESTABLISHED -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -d 10.0.0.0/8 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 2 -d 172.16.0.0/12 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 3 -j DROP
SETUP SYSCONFIG TO LOG DENIED ATTEMPTS
vi /etc/sysconfig/firewalld
- Add the following
LogDenied=all
- Restart firewalld
systemctl restart firewalld
EXECUTE THE FOLLOWING COMMAND TO LOG DENIED TRAFFIC
firewall-cmd --set-log-denied=all
This typically adds logging rules just before reject/drop rules in the firewall, something like:
LOG all -- anywhere anywhere LOG level warning prefix "IN_drop_DROP: "
LOG all -- anywhere anywhere LOG level warning prefix "FINAL_REJECT: "
Create a file named /etc/rsyslog.d/iptables.conf and add the following statements to it:
:msg,contains,"_DROP" /var/log/iptables.log
& stop
:msg,contains,"_REJECT" /var/log/iptables.log
& stop
:msg,contains,"etcd_peer" ~
& stop
:msg,contains,"rancher" ~
& stop
TOUCH OUTPUT FILE iptables.log
touch /var/log/iptables.log 2>/dev/null
RESTART RSYSLOG
systemctl restart rsyslog
Now the dropped and rejected packets will be logged to /var/log/iptables.log
In regards to iptables now:
SHOW STATUS OF YOUR FIREWALL
# We can get a quick look at the firewall so far, what the policies are set to,
# and any rules which might exist.
iptables -L -n -v --line-numbers
# Or, just the INPUT chain only
iptables -L INPUT -n --line-numbers
REDIRECT / DNAT DESTINATION OUTBOUND TRAFFIC ELSEWHERE
# Scenario: an application on an internal system wants to talk to a Public IP (216.201.128.5) but
# it is unable to make outbound connections because of existing firewall NAT'ing when going outside.
# The application can not be changed, so we need to let the system connect to real internal IP
# which is a load-balancer Private IP (192.168.1.99). This rule will allow local traffic to connect
# to the the external IP because it is DNAT'ing to the Internal IP that it can ACTUALLY get to!
#
# This would be a good solution for any older environment that has a firewall blocking outside IP traffic
# from the inside like the older Cisco PIX 525 models.
iptables -t nat -A OUTPUT -p tcp -d 216.201.128.5 -j DNAT --to-destination 192.168.1.99
# Using firewalld vs. iptables? Do this instead:
firewall-cmd --permanent --direct --add-rule ipv4 nat OUTPUT 0 -p tcp -d 216.201.128.5 -j DNAT --to-destination 192.168.1.99
firewall-cmd --reload
# Check to make sure it shows up
firewall-cmd --direct --get-all-rules
REMOVE A RULE
# Use above command and note rule_number
iptables -D INPUT rule_number
LIST PREROUTING AND NAT RULES
iptables -t nat -v -L PREROUTING -n --line-numbers
REMOVE NAT RULE
iptables -t nat -D PREROUTING <rule_number>
INSERT A RULE (BASE ON LINE NUMBER)
# iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
ADD RULE with PORT and IPADDRESS
iptables -A INPUT -p tcp -m tcp --dport port_number -s ip_address -j ACCEPT
ADD RULE for PORT on all addresses
iptables -A INPUT -p tcp -m tcp --dport port_number --sport 1024:65535 -j ACCEPT
DROP IPADRESS
iptables -I INPUT -s x.x.x.x -j DROP
DELETE (FLUSH) EXISTING RULES
# Let's start by clearing out all pre-existing rules in the firewall.
# You can use the "Flush" command to do this.
iptables -F
SET DEFAULT CHAIN POLICIES
# Now that the firewall is empty, we can initialize the default policies. Any traffic that
# does not match a rule in the firewall will fallback on the default policy (in this case,
# we will block all traffic by default).
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
-A INPUT -i lo -j ACCEPT #allow lo input
-A OUTPUT -o lo -j ACCEPT #allow lo output
ALLOW MULTIPLE PORTS FROM A SPECIFIC SOURCE NETWORK
# i.e. FTP, SSH, HTTP, SNMP, HTTPS & RSYNC
-A INPUT -i eth1 -s 205.159.1.0/24 -m multiport -p tcp --dports 21,22,80,161,443,873 -j ACCEPT
-A INPUT -i eth1 -s 205.159.1.0/24 -m multiport -p udp --dports 161,873 -j ACCEPT
DROP INVALID PACKETS
-A INPUT -m conntrack --ctstate INVALID -j DROP
ALLOW ESTABLISHED CONNECTIONS FROM SERVER TO PERSIST
-A INPUT -i eth1 -m conntrack -j ACCEPT --ctstate RELATED,ESTABLISHED
-A INPUT -i eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i eth1 -j DROP
BLOCK A SINGLE IP ADDRESS
-A INPUT -s 1.2.3.4 -j DROP
RESTRICT ACCESS TO A REMOTE SITE
# If we wanted to block access from the inside of the network from being able to reach
# a remote resource, we can also do so easily. Feel free to use IPs, subnets, or even
# domain names (they will be automatically resolved).
-A OUTPUT -p tcp -d www.facebook.com -j DROP
-A OUTPUT -p tcp -d facebook.com -j DROP
ALLOW ICMP PING FROM THE OUTSIDE
# We can allow ICMP echo replies to allow for testing
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
-A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
ALLOW ICMP PING TO THE OUTSIDE
# Since our default policies are blocking, we will want to specify outbound ICMP as well.
-A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
ALLOW ALL INCOMING SSH TUNNELS TO EHT0
-A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
ALLOW INCOMING SSH TUNNELS ONLY FROM A SPECIFIC SOURCE
-A INPUT -i eth0 -p tcp -s 192.168.0.0/24 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
ALLOW INBOUND HTTP WEB TRAFFIC
-A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
LOAD BALANCE WEB TRAFFIC
# NetFilter can also be used for round-robin load balancing. In this example,
# we will route all port 80 traffic between 3 web servers on the inside.
-A PREROUTING -p tcp --dport 80 -m state -m nth --every 3 --packet 0 -j DNAT --to-destination 10.0.0.4
-A PREROUTING -p tcp --dport 80 -m state -m nth --every 3 --packet 1 -j DNAT --to-destination 10.0.0.5
-A PREROUTING -p tcp --dport 80 -m state -m nth --every 3 --packet 2 -j DNAT --to-destination 10.0.0.6
ALLOW OUTBOUND DNS QUERIES
# Since outbound traffic is blocked by default, we will want to open a few things.
# Let's start with DNS.
-A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
-A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
ALLOW INBOUND SMTP EMAIL TRAFFIC
-A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT
ALLOW INBOUND POP3 CONNECTIONS
-A INPUT -p tcp --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 110 -m state --state ESTABLISHED -j ACCEPT
PORT FORWARDING
# Ports can be forwarded from the external address to a machine on the
# private network easily.
-t nat -A PREROUTING -p tcp -d 1.2.3.4 --dport 422 -j DNAT --to 192.168.0.100:22
LOGGING
# Note: Add an entry in your /etc/rsyslogd.conf for kern.warn (log level 4) like this, then
# HUP the rsyslogd process
kern.warning /var/log/firewall.log
# Add Logging for ACCEPT and DROP
-N LOG_ACCEPT
-A LOG_ACCEPT -m limit --limit 30/sec -j LOG --log-prefix "INPUT:ACCEPT:" --log-level 4
-A LOG_ACCEPT -j ACCEPT
-N LOG_DROP
-A LOG_DROP -m limit --limit 30/sec -j LOG --log-prefix "INPUT:DROP: " --log-level 4
-A LOG_DROP -j DROP
# Now, use it to Log vs. using ACCEPT / REJECT / DROP
# iptables -A <your_chain_here> <your_conditions_here> -j LOG_ACCEPT
# iptables -A <your_chain_here> <your_conditions_here> -j LOG_DROP
ALLOW OUTPUT PING/MTR (or traceroute -I, traceroute by default uses UDP - force with ICMP)
-A OUTPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type 0 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type 11 -m state --state ESTABLISHED,RELATED -j ACCEPT
ALLOW INPUT PING/MTR
-A INPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -p icmp --icmp-type 0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ALLOW OUTPUT
-A OUTPUT -p tcp -m multiport --dports 80,443 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m multiport --sports 80,443 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p udp -m multiport --dports 53,123 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p udp -m multiport --sports 53,123 -m state --state ESTABLISHED -j ACCEPT
BASIC IPTABLES CONFIG
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 ! -i lo -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m limit --limit 2/min -j LOG --log-prefix "iptables: " --log-level 7
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -p udp -m udp --dport 161 -m state --state NEW,ESTABLISHED -m comment --comment "SNMP" -j ACCEPT
-A INPUT -p tcp -m multiport --sports 1024:65535 -m multiport --dports 21000:21100 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-A INPUT -s 172.16.33.0/24 -p tcp -m tcp --dport 32911 -m state --state NEW,ESTABLISHED -m comment --comment "SSH on port 32911" -j ACCEPT
-A INPUT -s 172.16.33.0/24 -p udp -m multiport --dports 111 -j ACCEPT
-A INPUT -s 172.16.33.0/24 -p tcp -m multiport --dports 111 -j ACCEPT
-A INPUT -s 172.16.33.0/24 -p udp -m multiport --dports 513:65535 -j ACCEPT
-A INPUT -s 172.16.33.0/24 -p tcp -m multiport --dports 513:65535 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -j LOG --log-prefix "iptables reject: "
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -p tcp -m tcp --sport 32911 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m multiport --sports 21000:21100 -m multiport --dports 1024:65535 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p udp -m udp --sport 161 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -m limit --limit 6/hour -j LOG --log-prefix "iptables allowed: "
-A OUTPUT -j ACCEPT
COMMIT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment