Table of Contents
iptables
There are three tables in total. The first is the mangle table which is responsible for the alteration of quality of service bits in the TCP header. This is hardly used in a home or SOHO environment.
The second table is the filter queue which is responsible for packet filtering. It has three built-in chains in which you can place your firewall policy rules. These are the:
Forward chain: Filters packets to servers protected by the firewall. Input chain: Filters packets destined for the firewall. Output chain: Filters packets originating from the firewall.
The third table is the nat queue which is responsible for network address translation. It has two built-in chains; these are:
Pre-routing chain: NATs packets when the destination address of the packet needs to be changed. Post-routing chain: NATs packets when the source address of the packet needs to be changed
Avoid Locking Yourself
Create a minimal rules that always allow you to ssh to the machine after reboot
cat<<'EOF'>/etc/iptables.up.rules *filter # Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT # Accepts all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allows all outbound traffic # You could modify this to only allow certain traffic -A OUTPUT -j ACCEPT # Allows HTTP and HTTPS connections from anywhere (the normal ports for websites) -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Allows SSH connections # The --dport number is the same as in /etc/ssh/sshd_config -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT # Now you should read up on iptables rules and consider whether ssh access # for everyone is really desired. Most likely you will only allow access from certain IPs. # Allow ping # note that blocking other types of icmp packets is considered a bad idea by some # remove -m icmp --icmp-type 8 from this line to allow all kinds of icmp: # https://security.stackexchange.com/questions/22711 -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # log iptables denied calls (access via 'dmesg' command) -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 # Reject all other inbound - default deny unless explicitly allowed policy: -A INPUT -j REJECT -A FORWARD -j REJECT COMMIT EOF
T o make sure the iptables rules are started on a reboot we'll create a new file:
cat<<'EOF'>/etc/network/if-pre-up.d/iptables #!/bin/sh /sbin/iptables-restore < /etc/iptables.up.rules EOF
The file needs to be executable so change the permissions:
chmod +x /etc/network/if-pre-up.d/iptables
Persist changes to iptables
iptables-save > iptables.dump iptables-restore < iptables.dump
Upon stopping the service, the current iptables Rules are saved in a file, and upon starting the service, this file is restored. The affected files are:
/etc/sysconfig/iptables
for IPv4
/etc/sysconfig/ip6tables
for IPv6
For fedora 22, save the current rules:
sudo /usr/libexec/iptables/iptables.init save
Securing Your Server
sysctl.conf
root@visrc00:/home/td# vim /etc/sysctl.conf root@visrc00:/home/td# sysctl -p net.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 net.ipv4.conf.all.log_martians = 1
iptables
Allow all traffic on subnet
# this will APPEND, which will not work work if the last line of iptable -L is reject all: # REJECT all -- anywhere anywhere /* 9999 - Reject remaining traffic */ reject-with icmp-host-prohibited
sudo /sbin/iptables -A INPUT --src 10.20.21.2/24 -j ACCEPT sudo /sbin/iptables -A OUTPUT --src 10.20.21.2/24 -j ACCEPT
User INSERT instead:
sudo /sbin/iptables -I INPUT --src 10.20.21.2/24 -j ACCEPT sudo /sbin/iptables -I OUTPUT --src 10.20.21.2/24 -j ACCEPT
Allow Input from subnet:
iptables -I INPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED iptables -I INPUT -j ACCEPT -m conntrack --ctstate NEW -p tcp --source 123.123.0.0/16 iptables -I OUTPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
Headline
#!/bin/bash
### BEGIN INIT INFO
# Provides: dansgardian_firewall
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: firewall
# Description: Start, stop or reload firewall.
### END INIT INFO
#heavily adapted from the ubuntu_ce_firewall script from an older version of Ubuntu Christian Edition
set -e
case "$1" in
start)
echo -e "\nStarting Dansguardian firewall .....\n"
# Clears chains in filter table
/sbin/iptables -F
# Deletes any user-define chains
/sbin/iptables -X
# Clears chains in nat table
/sbin/iptables -t nat -F
# Deletes any user-defined chains in nat table
/sbin/iptables -t nat -X
# Clears chains in the mangle table (which is rarely using in SOHO)
/sbin/iptables -t mangle -F
# Deletes any user defined chains in mangle table
/sbin/iptables -t mangle -X
# Sets policy for filter FORWARD chain to accept all incoming/outgoing traffic
/sbin/iptables -P FORWARD ACCEPT
# Sets policy for filter OUTPUT table to accept all outgoing traffic
/sbin/iptables -P OUTPUT ACCEPT
# Prevents any tcp packets from any user except dansguardian from being accepted on 127.0.0.1:8118
# thus bypassing dansguarding through to the proxy
/sbin/iptables -A OUTPUT -d 127.0.0.1 -p tcp --dport 8118 -m owner ! --uid-owner dansguardian -j DROP
# Changes any tcp packets over the localhost adapter from another IP number destined for port 8080
# (where dansguardian listens) changing the source IP to localhost (127.0.0.1)
/sbin/iptables -A POSTROUTING -t nat -o lo -p tcp --dport 8080 -j SNAT --to 127.0.0.1
## This section is needed if printing to a network printing over Internet Printing Protocol (IPP) with CUPS
## needing tcp port 631 and udp 5353 open
/sbin/iptables -A INPUT -p tcp --dport 631 -j ACCEPT
# /sbin/iptables -A OUTPUT -p tcp --sport 631 -j ACCEPT #enable this if OUTPUT policy is DROP
/sbin/iptables -A INPUT -p udp --dport 5353 -j ACCEPT
# /sbin/iptables -A OUTPUT -p udp --sport 5353 -j ACCEPT #enable this if OUTPUT policy is DROP
/sbin/iptables -A INPUT -p udp --dport 161 -j ACCEPT
# /sbin/iptables -A OUTPUT -p udp --sport 161 -j ACCEPT #enable this if OUTPUT policy is DROP
## End IPP/CUPS section
# This does the magic directing any tcp packet NOT from root to any IP number that is NOT localhost
# destined to port 80 (web site ports) redirecting it to port 8080 where dansguardian is listening
/sbin/iptables -A OUTPUT -t nat ! -d 127.0.0.1 -p tcp --dport 80 -m owner ! --uid-owner root -j REDIRECT --to-ports 8080
# Sets the policy for all INPUT packets to be dropped setting up good security for the computer
# protecting it from the outside world.
/sbin/iptables -P INPUT DROP
# This is allowing all packets in to the localhost adapter adapter to be accepted
# (which is needed by the some programs on the computer to be able to communicate)
/sbin/iptables -A INPUT -i lo -j ACCEPT
# This causes all packets INTO the computer that are related to or extablished with an OUTPUT
# packet into the system (such as a response from a web host)
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
## Open port for ssh server (22), web server (80), and mail server (25)
/sbin/iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
#/sbin/iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
#/sbin/iptables -A INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT
## Uncomment below to open NSF port, edit the port accoring actual setting
## the mountd (32771) and lockmanager port (4045) must be set to be a
## static port or NFS will not work through the firewall (it is normally dynamically assigned)
## see this thread for more info on how to do this http://ubuntuforums.org/showthread.php?t=1263114
/sbin/iptables -A INPUT -p tcp --dport 111 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 111 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 2049 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 2049 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 4045 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 4045 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 32771 -m state --state NEW -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 32771 -m state --state NEW -j ACCEPT
## Open ports for NSF end
#Accept Ping request
/sbin/iptables -A INPUT -p icmp -j ACCEPT
## Drop other packets, Logging, and closing firewall.
/sbin/iptables -A INPUT -d 255.255.255.255/0.0.0.255 -j DROP #drop broadcast packets
/sbin/iptables -A INPUT -d 224.0.0.1 -j DROP #drop multicast packets
/sbin/iptables -A INPUT -j LOG #log all other packets making it through
/sbin/iptables -A INPUT -j REJECT #reject all other packets sending it through sending a tcp RST packet back
;;
stop)
echo -e "\nFlushing firewall and setting default policies to ACCEPT\n"
/sbin/iptables -F
/sbin/iptables -X
/sbin/iptables -t nat -F
/sbin/iptables -t nat -X
/sbin/iptables -t mangle -F
/sbin/iptables -t mangle -X
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P FORWARD ACCEPT
/sbin/iptables -P OUTPUT ACCEPT
;;
status)
echo "FILTER POLICY"
/sbin/iptables -L OUTPUT
/sbin/iptables -L INPUT
echo ; echo "NAT POLICY"
/sbin/iptables -t nat -L OUTPUT
/sbin/iptables -t nat -L POSTROUTING
;;
restart|force-reload)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
;;
esac
NAT Setup
- SNAT & MASQUERADE in POSTROUTING chain: https://terrywang.net/2016/02/02/new-iptables-gotchas.html
Troubleshooting
sudo iptables -t nat -v -x -n -L sudo iptables -v -x -n -L