#!/bin/bash ## http://www.ibm.com/developerworks/edu/l-dw-linuxfw-i.html # Our complete stateful firewall script. This firewall can be customized for a # laptop, workstation, router or even a server. :) # All your network interfaces, including lo. #interfaces=(lo eth0 wlan0) interfaces=(lo enp4s0 wlp0s29u1u8) # The interfaces that provides your "uplink". #uplink=(eth0 wlan0) uplink=(enp4s0 wlp0s29u1u8) # The local (ie., trusted) interfaces. local_interfaces=(lo) # Local network address range (with mask). lan="192.168.1.0/24" # Change this line so that it lists the assigned numbers or symbolic names # (from /etc/services) of all the services that you'd like to provide to the # general public. If you don't want any services enabled, set it to (). services_tcp=() services_udp=() lan_services_tcp=(ssh) lan_services_udp=() # Our default INPUT policy: DROP. default_input_policy=DROP function start_fw() { echo -n "Starting IPv4 firewall... " local has_ssh_22=false # Input table default policy. iptables -P INPUT "$default_input_policy" # Accept local (trusted) traffic. for i in "${local_interfaces[@]}" do iptables -A INPUT -i "$i" -j ACCEPT done # Accept ESTABLISHED or RELATED connections. iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Enable public access to global services. for s in "${services_tcp[@]}" do iptables -A INPUT -p tcp --dport "$s" -m conntrack --ctstate NEW -j LOG --log-prefix "[iptables] $s TCP svc:" iptables -A INPUT -p tcp --dport "$s" -m conntrack --ctstate NEW -j ACCEPT # Check whether ssh is part of our service set [[ "$s" == "ssh" ]] && has_ssh_22=true done for s in "${services_udp[@]}" do iptables -A INPUT -p udp --dport "$s" -m conntrack --ctstate NEW -j LOG --log-prefix "[iptables] $s UDP svc:" iptables -A INPUT -p udp --dport "$s" -m conntrack --ctstate NEW -j ACCEPT done # Enable LAN access to LAN services. for s in "${lan_services_tcp[@]}" do iptables -A INPUT -p tcp --dport "$s" -m conntrack --ctstate NEW -s "$lan" -j LOG --log-prefix "[iptables] $s TCP lan-svc:" iptables -A INPUT -p tcp --dport "$s" -m conntrack --ctstate NEW -s "$lan" -j ACCEPT # Check whether ssh is part of our service set [[ "$s" == "ssh" ]] && has_ssh_22=true done for s in "${lan_services_udp[@]}" do iptables -A INPUT -p udp --dport "$s" -m conntrack --ctstate NEW -s "$lan" -j LOG --log-prefix "[iptables] $s UDP lan-svc:" iptables -A INPUT -p udp --dport "$s" -m conntrack --ctstate NEW -s "$lan" -j ACCEPT done # Log and reject attempts at SSH connection on port 22 separately. if ! $has_ssh_22 then iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j LOG --log-prefix "[iptables] ssh22fail:" iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j "$default_input_policy" fi # Other rejected attempts. iptables -A INPUT -p tcp -j LOG --log-prefix "[iptables] bad TCP:" iptables -A INPUT -p udp -j LOG --log-prefix "[iptables] bad UDP:" iptables -A INPUT -p tcp -j "$default_input_policy" iptables -A INPUT -p udp -j "$default_input_policy" # Only non-UDP/TCP eth0/wlan0 traffic might end up here: low-level traffic. iptables -A INPUT -j LOG --log-prefix "[iptables] bad other:" # Output table default policy: ACCEPT. iptables -P OUTPUT ACCEPT # Enable reverse path filtering on all interfaces. for i in "${interfaces[@]}" do echo 1 > "/proc/sys/net/ipv4/conf/$i/rp_filter" done echo "done" } function stop_fw() { echo -n "Stopping IPv4 firewall... " iptables -F INPUT iptables -P INPUT ACCEPT iptables -F OUTPUT iptables -P OUTPUT ACCEPT echo "done" } if [ "$1" = "start" ] then start_fw elif [ "$1" = "stop" ] then stop_fw elif [ "$1" = "restart" ] then stop_fw start_fw else echo "Syntax: ${0##*/} " fi