diff --git a/install.bash b/install.bash index f8e5daa..2d28fbb 100755 --- a/install.bash +++ b/install.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -e # root check if [[ "$UID" -ne 0 ]]; then @@ -6,17 +6,19 @@ if [[ "$UID" -ne 0 ]]; then exit 1 fi +RULES_FILE='/etc/jfw/jfw.rules' + # Make /etc/jfw directory with "rules" file # (which is really the iptables script) -if [[ -f /etc/jfw/jfw.rules ]]; then +if [[ -f $RULES_FILE ]]; then echo "Found existing jfw configuration, do you wish to overwrite (y/n)?" read -n 1 if [[ "$REPLY" == "y" ]];then - echo "Overwriting '/etc/jfw/jfw.rules'" + echo "Overwriting '$RULES_FILE'" cp jfw.rules /etc/jfw/ chmod -R 700 /etc/jfw else - echo "Not overwriting '/etc/jfw/jfw.rules' ." + echo "Not overwriting '$RULES_FILE' ." fi else mkdir -p /etc/jfw @@ -24,11 +26,12 @@ else chmod -R 700 /etc/jfw fi -# Create symlink to jfw.rules: -ln -s /etc/jfw/jfw.rules /usr/sbin/jfw +# Copy executable in place: +cp jfw /usr/local/sbin/jfw +chown root:wheel /usr/local/sbin/jfw +chmod 750 /usr/local/sbin/jfw # Install systemd service file, -# Still needs to be enabled automatically cp jfw.service /etc/systemd/system systemctl daemon-reload @@ -39,6 +42,6 @@ if [[ "$REPLY" == "yes" ]]; then systemctl enable --now jfw else echo "You can edit the iptables rules to your liking by editing" - echo "'/etc/jfw/jfw.rules'. Afterwards you can use systemct to start" + echo "'$RULES_FILE'. Afterwards you can use systemct to start" echo "and/or enable the firewall." fi diff --git a/jfw b/jfw new file mode 100755 index 0000000..a38f1bf --- /dev/null +++ b/jfw @@ -0,0 +1,94 @@ +#!/bin/bash + +PATH="/usr/sbin:/sbin:/usr/bin:/bin" +RULES_FILE="/etc/jfw/jfw.rules" +VERSION=1.0 + +flush() { + iptables -P INPUT ACCEPT + iptables -P OUTPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -F INPUT + iptables -F OUTPUT + iptables -F FORWARD + iptables -F -t nat + iptables -F -t mangle + + ip6tables -P INPUT ACCEPT + ip6tables -P OUTPUT ACCEPT + ip6tables -P FORWARD ACCEPT + ip6tables -F INPUT + ip6tables -F OUTPUT + ip6tables -F FORWARD + ip6tables -F -t nat + ip6tables -F -t mangle +} + +load () { + if [[ -f "$RULES_FILE" ]]; then + flush + . $RULES_FILE + echo "Firewall rules applied" + else + echo "Could not find $RULES_FILE, flushing rules and exiting." + flush + exit 1 + fi +} + +usage () { + printf "Usage: $0 ACTION + Available ACTIONs: + flush restore default rules + edit edit and apply rules + logs view dmesg logs, add log rules via edit + list list current ruleset + reload (re)apply rules + + JFW version $VERSION +" + +} + +if [[ "$#" -eq 0 ]]; then + usage +elif [[ "$1" == "flush" ]]; then + flush + echo "Firewall rules flushed." +elif [[ "$1" == "edit" ]]; then + if ! systemctl is-active jfw.service &> /dev/null; then + printf "JFW is not running, you can edit the rules but\nthe changes won't take effect until you enable the service\n" + OFFLINE=true + fi + sudoedit $RULES_FILE + [[ "$OFFLINE" != "true" ]] && systemctl reload jfw.service + echo "Firewall rules updated." +elif [[ "$1" == "logs" ]]; then + dmesg -T | grep JFW +elif [[ "$1" == "list" ]]; then + echo "********** IPv4 **********" + iptables -S -v + echo "********** IPv6 **********" + ip6tables -S -v +elif [[ "$1" == "load" ]]; then + load +elif [[ "$1" == "test" ]]; then + load + echo "Waiting 60 seconds before flushing rules.." + SPINNER=('[* ]' '[ * ]' '[ * ]' '[ *]') + j=0 + SLEEP=0 + while [[ "$SLEEP" -lt 60 ]]; do + printf "${SPINNER[${j}]}\r" + sleep 0.25 + let j=$j+1 + [[ "$j" -gt 3 ]] && j=0 && let SLEEP=$SLEEP+1 + done + flush + echo "Firewall test finished, rules flushed." +elif [[ "$1" == "reload" ]]; then + load +elif [[ "$1" == "status" ]]; then + systemctl status jfw.service +fi +exit 0 diff --git a/jfw.rules b/jfw.rules index 7eac666..40b3eb8 100755 --- a/jfw.rules +++ b/jfw.rules @@ -1,81 +1,45 @@ #!/bin/bash -PATH="/usr/sbin:/sbin:/usr/bin:/bin" - -flush() { - iptables -P INPUT ACCEPT - iptables -P OUTPUT ACCEPT - iptables -P FORWARD ACCEPT - iptables -F INPUT - iptables -F OUTPUT - iptables -F FORWARD - iptables -F -t nat - iptables -F -t mangle - - ip6tables -P INPUT ACCEPT - ip6tables -P OUTPUT ACCEPT - ip6tables -P FORWARD ACCEPT - ip6tables -F INPUT - ip6tables -F OUTPUT - ip6tables -F FORWARD - ip6tables -F -t nat - ip6tables -F -t mangle -} - -if [[ "$1" == "flush" ]]; then - flush - echo "Firewall rules flushed." - exit 0 -elif [[ "$1" == "edit" ]]; then - sudoedit /etc/jfw/jfw.rules && systemctl reload jfw.service - echo "Firewall rules updated." - exit 0 -elif [[ "$1" == "logs" ]]; then - dmesg -T | grep JFW - exit 0 -elif [[ "$1" == "list" ]]; then - echo "********** IPv4 **********" - iptables -S -v - echo "********** IPv6 **********" - ip6tables -S -v - exit 0 -fi - -flush - -######### -# IPv4 # -######### - -## Loop device -iptables -A INPUT -i lo -j ACCEPT - -## Ping, router advertisements etc -iptables -A INPUT -p icmp -j ACCEPT -iptables -A INPUT -p ALL -d 224.0.0.1 -j ACCEPT - -## established inbound -iptables -A INPUT -p ALL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT - -## MDNS -iptables -A INPUT -p udp --dport 5353 -j ACCEPT - -## Wireguard network -## Replace AND -#iptables -A INPUT -p udp --dport -j ACCEPT -#iptables -A INPUT -i -j ACCEPT - -## SSH access -iptables -A INPUT -p tcp --dport 22 -j ACCEPT - -## Logging and dropping other inbound packets -## "log lines" may generate too much log entries -## uncomment the following lines to enable logging -#iptables -A INPUT -p ALL -j LOG --log-prefix "JFW IPv4 DROP::" -#iptables -A INPUT -p ALL -j DROP +## These variables make setting up NAT easier, just uncomment the NAT sections +## below +PUBLIC_INTERFACE= +LAN_INTERFACE= +JFW_LOG_4='-j LOG --log-prefix "[ JFW IPv4 DROP ]"' +JFW_LOG_6='-j LOG --log-prefix "[ JFW IPv6 DROP ]"' -## Default policies for IPv4 + + + + ######### + # IPv4 # + ######### + +##======== General required =======## +iptables -A INPUT -i lo -m conntrack --ctstate NEW -j ACCEPT ## Loop device +iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ACCEPT ## ICMP, e.g. ping +iptables -A INPUT -p ALL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT ## Existing and related to outgoing + +##============== NAT ==============## +# iptables -A FORWARD -i $LAN_INTERFACE -o $PUBLIC_INTERFACE -m conntrack --ctstate NEW -j ACCEPT +# iptables -A FORWARD -p ALL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +# iptables -t nat -A POSTROUTING -i $LAN_INTERFACE -o $PUBLIC_INTERFACE -j MASQUERADE + +##============ Public =============## +# iptables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT +# iptables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT +iptables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT + +##========== LAN enp4s0 ===========## +iptables -A INPUT -i enp4s0 -m conntrack --ctstate NEW -j ACCEPT +# iptables -A INPUT -i enp4s0 -p ALL -d 224.0.0.1 -m conntrack --ctstate NEW -j ACCEPT +# iptables -A INPUT -i enp4s0 -p udp --dport 5353 -m conntrack --ctstate NEW -j ACCEPT ## MDNS + +##=========== Logging =============## +# iptables -A INPUT -p ALL $JFW_LOG_4 +# iptables -A INPUT -p ALL -j DROP + +## Default policies for IPv4 ## iptables -P INPUT DROP iptables -P OUTPUT ACCEPT iptables -P FORWARD DROP @@ -85,50 +49,42 @@ iptables -P FORWARD DROP -######## -# IPv6 # -######## + ######## + # IPv6 # + ######## -## Loop device -ip6tables -A INPUT -i lo -j ACCEPT +##=========== General ===========## +ip6tables -A INPUT -i lo -m conntrack --ctstate NEW -j ACCEPT ## Loop device +ip6tables -A INPUT -p ipv6-icmp -m conntrack --ctstate NEW -j ACCEPT ## ICMP, e.g. ping +ip6tables -A INPUT -p icmpv6 -m conntrack --ctstate NEW -j ACCEPT ## These are required for IPv6 +ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT ## Existing and related to outgoing +ip6tables -A INPUT -d fe80::/10 -p udp -m conntrack --ctstate NEW -m udp --dport 546 -j ACCEPT ## DHCPv6-client +# ip6tables -A INPUT -i enp4s0 -p udp --dport 547 -m conntrack --ctstate NEW -j ACCEPT ## DHCPv6 server -## Ping, router advertisements etc -ip6tables -A INPUT -p icmpv6 -j ACCEPT +##============= NAT ===============## +# ip6tables -A FORWARD -i $LAN_INTERFACE -o $PUBLIC_INTERFACE -m conntrack --ctstate NEW -j ACCEPT +# ip6tables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +# +# NAT may not be desired for IPv6, if the clients on your LAN get +# a public IPv6 address from the DHCP server, you may want to leave this +# commented +# ip6tables -t nat -A POSTROUTING -o $PUBLIC_INTERFACE -j MASQUERADE -## established inbound -ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +##============ Public =============## +# ip6tables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT +# ip6tables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT +ip6tables -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT -## MDNS -ip6tables -A INPUT -p udp --dport 5353 -j ACCEPT +##============= LAN ===============## +ip6tables -A INPUT -i $LAN_INTERFACE -m conntrack --ctstate NEW -j ACCEPT +# ip6tables -A INPUT -i enp4s0 -p udp --dport 5353 -j ACCEPT ## MDNS -## Wireguard network -## Replace and and uncomment the following lines -#ip6tables -A INPUT -p udp --dport -j ACCEPT -#ip6tables -A INPUT -i -j ACCEPT - -## Logging and dropping other inbound packets -## "log lines" may generate too much log entries -## uncomment the following lines to enable logging -# ip6tables -A INPUT -p ALL -j LOG --log-prefix "JFW IPv6 DROP::" +##=========== Logging =============## +# ip6tables -A INPUT -p ALL $JFW_LOG_6 # ip6tables -A INPUT -p ALL -j DROP -## Default policies for IPv6 +##=== Default policies for IPv6 ===## ip6tables -P INPUT DROP ip6tables -P OUTPUT ACCEPT ip6tables -P FORWARD DROP - - - -## test-parameter for testing, flushes rules after 60 seconds -## reload for resetting temporary changes to those defined in this file -if [[ "$1" == "test" ]]; then - sleep 60 - flush - echo "Firewall test finished, rules flushed." - exit 0 -elif [[ "$1" == "reload" ]]; then - echo "Firewall rules reloaded." - exit 0 -fi - diff --git a/jfw.service b/jfw.service index 2a51060..af7dc18 100644 --- a/jfw.service +++ b/jfw.service @@ -3,9 +3,9 @@ Description=iptables rules After=network.target [Service] -ExecStart=/etc/jfw/jfw.rules -ExecStop=/etc/jfw/jfw.rules flush -ExecReload=/etc/jfw/jfw.rules +ExecStart=/usr/local/sbin/jfw load +ExecStop=/usr/local/sbin/jfw flush +ExecReload=/usr/local/sbin/jfw reload RemainAfterExit=yes [Install] diff --git a/uninstall.bash b/uninstall.bash index 369567d..904c445 100755 --- a/uninstall.bash +++ b/uninstall.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -e if [[ "$UID" -ne 0 ]]; then echo "This script must be run as root."