#!/bin/bash # # If you change this file and want them to be used when the machine reboots, # 1. Install the package iptables-persistent # 2a. Save the iptables rules to the file /etc/iptables/rules.v4 # # iptables-save > /etc/iptables/rules.v4 # # 2b. Or use the save command from one of these # iptables-persistent save # netfilter-persistent save # # (C) Richard Brown 2018 # This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. # https://creativecommons.org/licenses/by-sa/4.0/ # https://creativecommons.org/licenses/by-sa/4.0/legalcode # # Get the firewall into a known clean state, that is empty and fully open. echo "Turn off the firewall and remove all existing rules" /root/bin/fw.stop echo "Enable rules to block stuff" # Setup some variables to make moving these rules simpler # ======================================================= WAN_IF=enp0s3 WAN_IP=192.168.0.20 WAN_IPS=192.168.0.0/24 LAN_IF=enp0s8 LAN_IP=10.1.200.1 LAN_IPS=10.1.200.0/24 # Addresses and ports for SSH ALLOW_SSH="1" SSH_PORT=22 SSH_ALT_PORT=2222 SSH_PORTS="${SSH_PORT},${SSH_ALT_PORT}" # Addresses and ports for HTTP/HTTPS, web stuff ALLOW_HTTP="0" HTTP_PORT=80 HTTPS_PORT=443 HTTP_OPT_PORT=8080 HTTP_PORTS="${HTTP_PORT},${HTTPS_PORT},${HTTP_OPT_PORT}" # Addresses and ports for Mail servers ALLOW_MAIL="0" SMTP_PORT=25 POP3_PORT=110 IMAP_PORT=143 SMTP_PORT2=587 IMAPS_PORT=993 POP3S_PORT=995 MAIL_PORTS="${SMTP_PORT},${POP3_PORT},${IMAP_PORT},${SMTP_PORT2},${IMAPS_PORT},${POP3S_PORT}" # IP addresses inside your test lab LABSERVER1_IP=10.1.200.10 LABDESKTOP1_IP=10.1.200.20 LABWEBSERVER_IP=10.1.200.7 LABMAIL_IP=10.1.200.7 LAB_IPS=10.1.200.0/24 # real LAN IP addresses allowed to connect to servers/services in the test lab # Useful for testing, use cases when only one IP address can connect INT1_IP=192.168.0.9 INT2_IP=192.168.0.11 # Set Default policy variables # ============================ # Set the values for a default policy to DROP all remaining INPUT and # FORWARD packets for OUTPUT we will allow everything. INPUT_DEF=DROP FORWARD_DEF=DROP OUTPUT_DEF=ACCEPT TRACELOGGING=0 TRACE_DEF=ACCEPT # Set Default policy # ================== # If the default for the OUTPUT chain is ACCEPT we do not need any OUTPUT rules. # If OUTPUT is set to DROP, then we need an OUTPUT rule for each INPUT rule. iptables -P INPUT $INPUT_DEF iptables -P FORWARD $FORWARD_DEF iptables -P OUTPUT $OUTPUT_DEF # Create the INPUT logging chain # =============================== if [ "$TRACELOGGING" == "1" ]; then iptables -N INPUTLOG iptables -N FORWARDLOG iptables -N OUTPUTLOG iptables -N TRACELOG fi # Allow all INPUT loopback traffic # ================================ # Any traffic on lo should be allowed at the start of the INPUT chains iptables -A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT # Allow all INPUT LAN traffic # =========================== iptables -A INPUT -i ${LAN_IF} -j ACCEPT # Stop null, invalid or syn-flood packets # ======================================= # DROP known bad and useless packets ASAP, no point wasting CPU # cycles testing them againsts other rules. iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -m conntrack --ctstate INVALID -j DROP # Try and stop DoS attacks # ======================== # get these rules at the beginning of the chain so we get rid of the packets ASAP. # # -m limit: This uses the limit iptables extension # --limit 25/minute: This limits maximum of 25 connection per minute. # --limit-burst 50: This value indicates that the limit/minute will be enforced only # after the total number of connection have reached the limit-burst level. #iptables -A INPUT -i ${WAN_IF} -p tcp -m multiport --dports 21,22,25,110,143,587,993,995 -m state --state NEW -m limit --limit 4/minute --limit-burst 5 -j ACCEPT #iptables -A INPUT -i ${WAN_IF} -p tcp -m multiport --dports 80,443,8080 -m state --state NEW -m limit --limit 25/minute --limit-burst 50 -j ACCEPT # Allow replies to established connections # ======================================== # If the INPUT packet is a reply or "because of" a request we # sent out allow the answer back in. iptables -A INPUT -i ${WAN_IF} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Sort out NATing for lab machines # ================================ # NAT from LAN to WAN as we use local IP address in the test lab # these cannot get out to the internet. iptables -t nat -A POSTROUTING -o ${WAN_IF} -s ${LAN_IPS} -j SNAT --to-source ${WAN_IP} # Stop some known services coming in # ================================== # These only stop new requests, they do not stop data being returned from a request # that started in the test lab. # NTP iptables -A INPUT -i ${WAN_IF} -p tcp --dport 123 -m conntrack --ctstate NEW -j DROP iptables -A INPUT -i ${WAN_IF} -p udp --dport 123 -m conntrack --ctstate NEW -j DROP # NETBIOS-NS iptables -A INPUT -i ${WAN_IF} -p tcp --dport 137 -m conntrack --ctstate NEW -j DROP iptables -A INPUT -i ${WAN_IF} -p udp --dport 137 -m conntrack --ctstate NEW -j DROP # Multicast DNS iptables -A INPUT -i ${WAN_IF} -p tcp -m multiport --dports 53,5353 -m conntrack --ctstate NEW -j DROP iptables -A INPUT -i ${WAN_IF} -p udp -m multiport --dports 53,5353 -m conntrack --ctstate NEW -j DROP # Block connections from known spammers # ===================================== # Block one IP address or range as CIDR # iptables -A INPUT -s 11.22.33.44 -j DROP # or even a range # iptables -I INPUT -m iprange --src-range 1.2.3.4-1.2.255.255 -j DROP # or range as CIDR # iptables -I INPUT -m iprange --src-range 1.2.3.4/16 -j DROP # Allow a bunch of ports & services through # ========================================= # Wrap them in an if statement so they can be turned on # and off with a flag at the top of the script. if [ "$ALLOW_SSH" == "1" ]; then echo "SSH rules" # Incoming on port 22 goes to localhost, so allow it in. iptables -A INPUT -i ${WAN_IF} -s ${WAN_IPS} -p tcp --dport ${SSH_PORT} -j ACCEPT # forward port 2222 on to 22 (ssh) for lab-server1, Only allow ssh via 2222 externally to lab-server # Use ssh -p 2222 user@lab_router -> lab-server1 on {LABSERVER1_IP}:${SSH_PORT} iptables -t nat -A PREROUTING -p tcp --dport ${SSH_ALT_PORT} -i ${WAN_IF} -j DNAT --to ${LABSERVER1_IP}:${SSH_PORT} # allow IP addresses from our real LAN iptables -A FORWARD -i ${WAN_IF} -s ${WAN_IPS} -p tcp --dport ${SSH_PORT} -j ACCEPT # Or from anywhere # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${SSH_PORT} -j ACCEPT fi if [ "$ALLOW_HTTP" == "1" ]; then echo "HTTP & HTTPS rules" iptables -t nat -A PREROUTING -i ${WAN_IF} -p tcp -m multiport --dport ${HTTP_PORTS} -j DNAT --to ${LABWEBSERVER_IP} iptables -A FORWARD -i ${WAN_IF} -p tcp -m multiport --dport ${HTTP_PORTS} -d ${LABWEBSERVER_IP} -j ACCEPT fi if [ "$ALLOW_MAIL" == "1" ]; then echo "Mail rules" iptables -t nat -A PREROUTING -p tcp -m multiport --dports ${MAIL_PORTS} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP} iptables -A FORWARD -i ${WAN_IF} -p tcp -m multiport --dports ${MAIL_PORTS} -d ${LABMAIL_IP} -j ACCEPT # To forward a bunch of ports to the same same server and port you could try, e.g. a mail and web server might need # To get the same thing with single ports per line # iptables -t nat -A PREROUTING -p tcp --dport ${SMTP_PORT} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${SMTP_PORT} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${SMTP_PORT} -d ${LABMAIL_IP} -j ACCEPT # iptables -t nat -A PREROUTING -p tcp --dport ${POP3_PORT} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${POP3_PORT} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${POP3_PORT} -d ${LABMAIL_IP} -j ACCEPT # iptables -t nat -A PREROUTING -p tcp --dport ${IMAP_PORT} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${IMAP_PORT} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${IMAP_PORT} -d ${LABMAIL_IP} -j ACCEPT # iptables -t nat -A PREROUTING -p tcp --dport ${SMTP_PORT2} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${SMTP_PORT2} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${SMTP_PORT2} -d ${LABMAIL_IP} -j ACCEPT # iptables -t nat -A PREROUTING -p tcp --dport ${IMAPS_PORT} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${IMAPS_PORT} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${IMAPS_PORT} -d ${LABMAIL_IP} -j ACCEPT # iptables -t nat -A PREROUTING -p tcp --dport ${POP3S_PORT} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${POP3S_PORT} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${POP3S_PORT} -d ${LABMAIL_IP} -j ACCEPT # You could even do the above like this, assuming they all go to the same host # it is less typing and easier to debug # for port in ${SMTP_PORT} ${POP3_PORT} ${IMAP_PORT} ${SMTP_PORT2} ${IMAPS_PORT} ${POP3S_PORT} # do # iptables -t nat -A PREROUTING -p tcp --dport ${port} -i ${WAN_IF} -j DNAT --to ${LABMAIL_IP}:${port} # iptables -A FORWARD -i ${WAN_IF} -p tcp --dport ${port} -d ${LABMAIL_IP} -j ACCEPT # done fi ## End if [ "$ALLOW_MAIL" == "1" #=============== # Other examples #=============== # To forward a range of ports, to the same port on another machine. #iptables -t nat -A PREROUTING -i ${WAN_IF} -p tcp --dport 64000:65000 -j DNAT --to ${LABMAIL_IP} #iptables -A FORWARD -i ${WAN_IF} -p tcp --dport 64000:65000 -d ${LABMAIL_IP} -j ACCEPT # Forward a range of ports but to a different range on the destination. #iptables -t nat -A PREROUTING -i ${WAN_IF} -p tcp --dport 64000:65000 -j DNAT --to ${LABMAIL_IP}:44000:45000 #iptables -A FORWARD -i ${WAN_IF} -p tcp --dport 64000:65000 -d ${LABMAIL_IP} -j ACCEPT # Routing rules # ============= # Allow routing from LAN to WAN iptables -A FORWARD -i ${LAN_IF} -o ${WAN_IF} -j ACCEPT # Allow routing from WAN to LAN # Allow only replies from existing connections. i.e. HTTP requests, DNS, ssh iptables -A FORWARD -i ${WAN_IF} -o ${LAN_IF} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # This rule routes all ports through from WAN to LAN. Just in case. #iptables -A FORWARD -i ${WAN_IF} -o ${LAN_IF} -j ACCEPT # PING # ==== # Allow pings from every where iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # Allow pings from a range of IPs, our real LAN iptables -A INPUT -i ${WAN_IF} -s ${WAN_IPS} -p icmp --icmp-type echo-request -j ACCEPT # Only allow pings from the WAN from one IP address ${INT1_IP} #iptables -A INPUT -i ${WAN_IF} -s ${INT1_IP} -p icmp --icmp-type echo-request -j ACCEPT # Logging any remianing packets # ============================= # If tracelogging is turned on log remiaining packets as they would have # been DROPped, but only 2 per minute so we do not spam ourselves. # if [ "$TRACELOGGING" == "1" ]; then # Send all remaining INPUT chain packets to INPUTLOG echo "Logging rules" iptables -A INPUT -j INPUTLOG iptables -A INPUTLOG -m limit --limit 2/min -j LOG --log-prefix "INPUT $INPUT_DEF " --log-level 7 iptables -A INPUTLOG -j $INPUT_DEF #iptables -A OUTPUT -j OUTPUTLOG iptables -A OUTPUTLOG -j LOG --log-prefix "OUTPUT $OUTPUT_DEF " --log-level 7 #iptables -A OUTPUTLOG -m limit --limit 2/min -j LOG --log-prefix "OUTPUT $OUTPUT_DEF " --log-level 7 iptables -A OUTPUTLOG -j $OUTPUT_DEF iptables -A FORWARD -j FORWARDLOG iptables -A FORWARDLOG -m limit --limit 2/min -j LOG --log-prefix "FORWARD $FORWARD_DEF " --log-level 7 iptables -A FORWARDLOG -j $FORWARD_DEF iptables -A TRACELOG -m limit --limit 2/min -j LOG --log-prefix "TRACE $TRACE_DEF " --log-level 7 iptables -A TRACELOG -j $TRACE_DEF fi