#!/bin/sh ### BEGIN INIT INFO # Provides: firewall # Required-Start: $remote_fs $rsyslog # Required-Stop: $remote_fs $rsyslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Firewall initscript # Description: Firewall script for iptables # To test the script you can just use 'test' arg: # ./firewall test # service firewall test # Doc: * http://openvz.org/Using_NAT_for_container_with_private_IPs # * ... ### END INIT INFO # Author: Gardouille # ********************************************************************************************** # # Global var # # ----------------------------------------------------------- # iptables path IPT="/sbin/iptables" # testing for XX seconds TIME=42 #### Colors definition export REDB='\033[1;31m' export GREEN='\033[1;32m' export WHITEB='\033[1;37m' export RESET='\033[0m' fw_init() { ############# ## KERNEL ## ############# # Enable Cookie TCP SYN protection echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Enable IP spoofing protection # Check the ip source for SYS in /proc/sys/net/ipv4/conf/*/rp_filter do echo 1 > ${SYS} done # Disable ICMP redirect for SYS in /proc/sys/net/ipv4/conf/*/accept_redirects do echo 0 > ${SYS} done # Disable source-route packages for SYS in /proc/sys/net/ipv4/conf/*/accept_source_route do echo 0 > ${SYS} done # Enable ip forwarding #echo 1 > /proc/sys/net/ipv4/ip_forward ############# ## POLICY ## ############# # drop all traffic $IPT -P INPUT DROP $IPT -P FORWARD DROP $IPT -P OUTPUT DROP #$IPT -P INPUT ACCEPT #$IPT -P FORWARD ACCEPT #$IPT -P OUTPUT ACCEPT ############ ## BASE ## ############ # Drop all new connections without a syn flag $IPT -t filter -A INPUT -j DROP -p tcp ! --syn -m state --state NEW # Forbid local connections that doesn't come from localhost $IPT -A INPUT -j REJECT ! -i lo -d 127.0.0.1/8 -m comment --comment "Reject lo not from lo" # Allow loopback $IPT -A INPUT -j ACCEPT -i lo -m comment --comment "Loopback in" $IPT -A OUTPUT -j ACCEPT -o lo -m comment --comment "Loopback out" ############## ## OUTPUT ## ############## #### ICMP request (Ping) $IPT -A OUTPUT -j ACCEPT -p icmp -m state --state NEW -m comment --comment "ICMP out" } fw_start() { ############# ## INPUT ## ############# #### Pour tenter de s'y retrouver avec l'affichage des règles iptables, pour l'écriture des règles, # respecter cet ordre: # -t TABLE -A CHAINE -j TARGET -p PROTOCOLE -i ETH_IN -o ETH_OUT -s SOURCE -d DESTINATION --sport PORT_SRC --dport PORT_DST -m state --state LIST_OF_STATE -m comment --comment "tiny DESCRIPTION" #### #### Ne pas casser les connexions etablies $IPT -A INPUT -j ACCEPT -p all -i "${ILAN}" -d "${IPLAN}" -m state --state RELATED,ESTABLISHED # $IPT -A FORWARD -j ACCEPT -p all -o "${IVM}" -d "${LANVM}" -m state --state RELATED,ESTABLISHED ##### # $IPT -A INPUT -j ACCEPT -s 192.168.42.166 -d 192.168.42.1 -m comment --comment "TEST Rules" # $IPT -A OUTPUT -j ACCEPT -s 192.168.42.1 -d 192.168.42.166 -m comment --comment "TEST Rules" # # $IPT -A INPUT -j ACCEPT -p icmp -s ${LANVM} -d "${IPLAN}" -m comment --comment "ICMP req LANVM" #### ICMP (Ping) # Accept all ping #$IPT -A INPUT -p icmp -j ACCEPT # Accept icmp ping from LAN #$IPT -A INPUT -j ACCEPT -p icmp -i "${ILAN}" -s ${LAN} -d "${IPLAN}" -m comment --comment "ICMP req LAN" if [ $(command -v sshd) ]; then #### SSHD $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 22 -m state --state NEW -m comment --comment "New SSH in" fi ## BackupPC $IPT -A INPUT -j ACCEPT -p icmp -i "${ILAN}" -s 192.168.0.3 -d "${IPLAN}" -m comment --comment "ICMP FURY req" $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -s 192.168.0.3 -d "${IPLAN}" --dport 22 -m state --state NEW -m comment --comment "New SSH fury in" if [ $(command -v apache2) ] || [ $(command -v nginx) ]; then #### Web server $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 80 -m state --state NEW -m comment --comment "New HTTP in" $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 443 -m state --state NEW -m comment --comment "New HTTPS in" fi if [ $(command -v slapd) ]; then #### slapd #### if 389 is use, ldap connections should be in TLS $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 389 -m state --state NEW -m comment --comment "New LDAP in" $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 636 -m state --state NEW -m comment --comment "New LDAPS in" fi if [ $(command -v dhcpd) ]; then #### dhcpd $IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --sport 67:68 --dport 67:68 -m state --state NEW -m comment --comment "New DHCPD in" fi if [ -f /etc/init.d/puppetmaster ] || [ -f /etc/systemd/system/puppetmaster.service ]; then #### PuppetMaster $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -s "${LAN}" -d "${IPLAN}" --dport 8140 -m state --state NEW -m comment --comment "New Puppet in" fi if [ $(command -v nfsdcltrack) ]; then #### NFS Server $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 111 -m state --state NEW -m comment --comment "NFS in" $IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --dport 111 -m state --state NEW -m comment --comment "NFS in" $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 2049 -m state --state NEW -m comment --comment "NFS " $IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --dport 2049 -m state --state NEW -m comment --comment "NFS in" # 32769: rpc.quotad # For more informations see: https://wiki.debian.org/SecuringNFS $IPT -A INPUT -j ACCEPT -p tcp -i "${ILAN}" -d "${IPLAN}" --dport 32769 -m state --state NEW -m comment --comment "NFS quotad in" $IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --dport 32769 -m state --state NEW -m comment --comment "NFS quotad in" fi #### tftp allowed #$IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --dport 69 -m state --state NEW -m comment --comment "TFTPD in" if [ $(command -v cupsd) ]; then #### Printers $IPT -A INPUT -j ACCEPT -p udp -i "${ILAN}" -d "${IPLAN}" --sport 161 -m state --state NEW -m comment --comment "SNMP IN" fi ######################### ## {Multi,Broad}cast ## ######################### #### DROP Multicast & broadcast $IPT -t mangle -A PREROUTING -j DROP -p udp -i "${ILAN}" -d 255.255.255.255 -m comment --comment "DROP Broadcast1" $IPT -t mangle -A PREROUTING -j DROP -p udp -i "${ILAN}" -d 129.20.27.255 -m comment --comment "DROP Broadcast2" $IPT -t mangle -A PREROUTING -j DROP -p udp -i "${ILAN}" -d 129.20.255.255 -m comment --comment "DROP Broadcast3" $IPT -t mangle -A PREROUTING -j DROP -p udp -i "${ILAN}" -d 224.0.0.1 -m comment --comment "DROP Multicast1" $IPT -t mangle -A PREROUTING -j DROP -p udp -i "${ILAN}" -d 224.0.0.251 -m comment --comment "DROP Multicast2" ############## ## OUTPUT ## ############## #### Ne pas casser les connexions etablies $IPT -A OUTPUT -j ACCEPT -p all -o "${ILAN}" -s "${IPLAN}" -m state --state RELATED,ESTABLISHED,UNTRACKED # # #### ICMP reply (Ping) # #$IPT -A OUTPUT -j ACCEPT -p icmp -o "${ILAN}" --icmp-type 0 -s "${IPLAN}" -d 0/0 -m state --state ESTABLISHED,RELATED -m comment --comment "ICMP reply" if [ $(command -v ssh) ]; then #### SSH $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 22 -m state --state NEW -m comment --comment "SSH out" fi #### Mail SMTP ## Port 465 (SMTPS SSL) is deprecated) $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 25 -m state --state NEW -m comment --comment "SMTP out" $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 587 -m state --state NEW -m comment --comment "SMTP TLS out" #### Mail IMPA $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 143 -m state --state NEW -m comment --comment "IMAP out" $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 993 -m state --state NEW -m comment --comment "IMAPS out" #### DNS (résolution de noms de domaines, ... ...) $IPT -A OUTPUT -j ACCEPT -p udp -o ${ILAN} --dport 53 -m state --state NEW -m comment --comment "DNS out udp" $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --dport 53 -m state --state NEW -m comment --comment "DNS out tcp" if [ $(command -v dhclient) ]; then #### DHCP $IPT -A OUTPUT -j ACCEPT -p udp -o ${ILAN} -s "${IPLAN}" --sport 68 -m comment --comment "DHCPREQUEST" fi #### HTTP (maj, ...) $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --dport 80 -m state --state NEW -m comment --comment "HTTP out" $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --dport 443 -m state --state NEW -m comment --comment "HTTPS out" if [ $(command -v ntpd) ]; then #### NTP $IPT -A OUTPUT -j ACCEPT -p udp -o ${ILAN} --dport 123 -m state --state NEW -m comment --comment "NTP out" fi if [ $(command -v puppet) ]; then #### Puppet (connection, ... ) $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" --dport 8140 -m state --state NEW -m comment --comment "Puppet out" fi #### OpenPGP HTTP key server (add key, maj, ...) $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --dport 11371 -m state --state NEW -m comment --comment "OpenPGP req" if [ $(command -v apache2) ] || [ $(command -v nginx) ]; then #### Web server $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --sport 80 -m state --state NEW -m comment --comment "New HTTPD out" $IPT -A OUTPUT -j ACCEPT -p tcp -o ${ILAN} --sport 443 -m state --state NEW -m comment --comment "New HTTPDs out" fi if [ -d /etc/ldap ]; then #### ldap connection should be in TLS or at least in LDAPS/SSL $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 389 -m state --state NEW -m comment --comment "LDAP out" $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 636 -m state --state NEW -m comment --comment "LDAPS out" fi if [ $(command -v dhcpd) ]; then #### dhcpd $IPT -A OUTPUT -j ACCEPT -p udp -o "${ILAN}" -s "${IPLAN}" --sport 67:68 --dport 67:68 -m state --state NEW -m comment --comment "DHCPD out" fi if [ $(command -v nfsiostat) ]; then #### NFS Client $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 111 -m state --state NEW -m comment --comment "NFS out" $IPT -A OUTPUT -j ACCEPT -p udp -o "${ILAN}" -s "${IPLAN}" --dport 111 -m state --state NEW -m comment --comment "NFS out" $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 2049 -m state --state NEW -m comment --comment "NFS out" $IPT -A OUTPUT -j ACCEPT -p udp -o "${ILAN}" -s "${IPLAN}" --dport 2049 -m state --state NEW -m comment --comment "NFS out" # List of ports to use given by NFS server # For more informations see: https://wiki.debian.org/SecuringNFS $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 32767 -m state --state NEW -m comment --comment "NFS mountd out" $IPT -A OUTPUT -j ACCEPT -p udp -o "${ILAN}" -s "${IPLAN}" --dport 32767 -m state --state NEW -m comment --comment "NFS mountd out" fi if [ $(command -v cupsd) ]; then #### Printers $IPT -A OUTPUT -j ACCEPT -p udp -o "${ILAN}" -s "${IPLAN}" --dport 161 -m state --state NEW -m comment --comment "SNMP OUT" #### HP Printers $IPT -A OUTPUT -j ACCEPT -p tcp -o "${ILAN}" -s "${IPLAN}" --dport 9100 -m state --state NEW -m comment --comment "HP printer OUT" fi } # Règles pour de log fw_log() { ############# ## LOG ## ############# # LOG INPUT DROP PAQUET $IPT -N INPLOG $IPT -A INPUT -j INPLOG $IPT -A INPLOG -p tcp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-IN [tcp]: " $IPT -A INPLOG -p udp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-IN [udp]: " $IPT -A INPLOG -p icmp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-IN [icmp]: " # LOG OUTPUT DROP PAQUET $IPT -N OUTLOG $IPT -A OUTPUT -j OUTLOG $IPT -A OUTLOG -p tcp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-OUT [tcp]: " $IPT -A OUTLOG -p udp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-OUT [udp]: " $IPT -A OUTLOG -p icmp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-OUT [icmp]: " # LOG FORWARD DROP PAQUET $IPT -N FORLOG $IPT -A FORWARD -j FORLOG $IPT -A FORLOG -p tcp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-FOR [tcp]: " $IPT -A FORLOG -p udp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-FOR [udp]: " $IPT -A FORLOG -p icmp -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "Drop-FOR [icmp]: " } # Arrêt du firewall fw_stop() { # Supprimer une route ajouter automatiquement #ip route del 169.254.0.0/16 # Vider les tables actuelles $IPT -t filter -F # Vider les règles personnelles $IPT -t filter -X $IPT -t nat -F $IPT -t nat -X $IPT -t mangle -F $IPT -t mangle -X $IPT -P INPUT ACCEPT $IPT -P FORWARD ACCEPT $IPT -P OUTPUT ACCEPT $IPT -t nat -P PREROUTING ACCEPT $IPT -t nat -P OUTPUT ACCEPT $IPT -t nat -P POSTROUTING ACCEPT $IPT -t mangle -P PREROUTING ACCEPT $IPT -t mangle -P INPUT ACCEPT $IPT -t mangle -P FORWARD ACCEPT $IPT -t mangle -P OUTPUT ACCEPT $IPT -t mangle -P POSTROUTING ACCEPT } # VPN fw_vpn() { # Allow all traffic throught VPN $IPT -I INPUT -j ACCEPT -p all -i "${ILAN}" -m state --state NEW,RELATED,ESTABLISHED -m comment --comment "VPN in" $IPT -I OUTPUT -j ACCEPT -p all -o "${ILAN}" -m state --state NEW,RELATED,ESTABLISHED,UNTRACKED -m comment --comment "VPN out" } # ********************************************************************************************** # # Programme principale # # ----------------------------------------------------------- case "${1}" in start|restart) printf '%s\n' "Start firewall …" fw_stop fw_init # List all available interface except localhost for PATH_ILAN in $(find /sys/class/net/ ! \( -name lo -o -iname "tun*" \) -type l); do # Interface name ILAN=$(basename ${PATH_ILAN}) IS_UP=$(grep 1 ${PATH_ILAN}/carrier) # Test if interface is connected if [ ${IS_UP} ]; then # Interface IP IPLAN=$(ip route|grep -v "default"|grep ${ILAN}|grep src|awk '{print $NF}') # IP/MASK #IPLAN=$(ip a s "${ILAN}"|grep "inet "|awk '{print $2}') # Interface LAN LAN=$(ip route|grep -v "default"|grep "${IPLAN}"|awk '{print $1}') printf '%b' "${WHITEB}${ILAN} ${GREEN}connected${RESET}: \t${IPLAN} \ton ${LAN}\n" # Load rules for this interface fw_start else printf '%b' "${WHITEB}${ILAN} ${REDB}disconnected${RESET}\n" fi done # If exist, load local rules file if [ -f "${0}.local" ]; then printf '%b' "Load local rules file\n" ${0}.local fi fw_log ;; stop) printf '%s\n' "Clean all firewall rules" fw_stop ;; test) printf '%b' "Load firewall rules for ${TIME} secondes …\n" $0 start sleep ${TIME} fw_stop ;; vpn) printf '%s\n' "Special rules for VPN interfaces (TUN or TAP)" for PATH_ILAN in $(find /sys/class/net/ \( -iname "*tun*" -o -iname "*tap*" \) -type l ); do ILAN=$(basename ${PATH_ILAN}) IS_UP=$(grep 1 ${PATH_ILAN}/carrier) if [ ${IS_UP} ]; then # IP IPLAN=$(ip route|grep -v "default"|grep ${ILAN}|grep src|awk '{print $NF}') # IP/MASK #IPLAN=$(ip a s "${ILAN}"|grep "inet "|awk '{print $2}') LAN=$(ip route|grep -v "default"|grep "${IPLAN}"|awk '{print $1}') printf '%b' "${WHITEB}${ILAN} ${GREEN}connected${RESET}: \t${IPLAN} \ton ${LAN}\n" # Load special rules for this interface fw_vpn else printf '%b' "${WHITEB}${ILAN} ${REDB}disconnected${RESET}\n" fi done ;; *) echo "Usage: firewall ({start|stop|restart|test})" exit 1 ;; esac # Fin du script exit 0 # Fin de la boucle principale # -----------------------------------------------------------