Last active
January 7, 2024 22:51
-
-
Save jbfriedrich/63914bd57b1be9a50d59be09bb2fb026 to your computer and use it in GitHub Desktop.
IPtables firewall on a router virtual machine running on a remote VMware ESXi host (it ran on Hetzner in this example). It requires a separate subnet, a dedicated vm router IP address and only supports IPv4.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
################################################################################ | |
# 2014-08-03 | Jason Friedrich | |
#------------------------------------------------------------------------------- | |
# Version history: | |
# v1.2 | 2022-06-27 | |
# - Partial rewrite for net network structure | |
# v1.1 | 2014-08-03 | |
# - Complete rewrite for new network structure | |
################################################################################ | |
################################################################################ | |
## VARIABLES | |
################################################################################ | |
## BINARIES | |
IPT='/sbin/iptables -v' | |
## ROUTER INTERFACES | |
EXTINT='eth0' | |
SUBINT='eth6' | |
ALPHAINT='eth1' | |
BETAINT='eth2' | |
SRVINT='eth5' | |
DOCKERINT='eth3' | |
K8SINT='eth4' | |
## ROUTER NETWORKS | |
SUBNET='1.2.3.4/29' | |
ALPHANET='10.20.0.0/24' | |
BETANET='10.30.0.0/24' | |
SRVNET='10.200.0.0/24' | |
DOCKERNET='10.50.0.0/24' | |
K8SNET='10.60.0.0/24' | |
## ROUTER IPS | |
EXTIP='2.3.4.5' | |
SUBIP='3.4.5.6' | |
ALPHAIP='10.20.0.1' | |
BETAIP='10.30.0.1' | |
SRVIP='10.200.0.1' | |
DOCKERIP='10.50.0.1' | |
K8SIP='10.60.0.1' | |
## PUBLIC INTERNET HOSTS | |
HOMEOFFICE='4.5.6.7/24' | |
TAILSCALE='xxx.xx.0.0/10' | |
HETZNERBACKUP='188.40.2.186/32' | |
HETZNERDNS01='213.133.98.98' | |
HETZNERDNS02='213.133.99.99' | |
HETZNERDNS03='213.133.100.100' | |
QUADDNS01='1.1.1.1' | |
QUADDNS02='9.9.9.9' | |
################################################################################ | |
## FUNCTIONS | |
################################################################################ | |
function delfwrules { | |
## DELETE ALL EXISTING RULES | |
echo 'INFO: Deleting all existing firewall rules' | |
${IPT} -F | |
${IPT} -X | |
${IPT} -t nat -F | |
${IPT} -t nat -X | |
} | |
function enablefwd { | |
## ENABLE IPV4 FORWARDING | |
echo 'INFO: Enabling IPV4 forwarding' | |
echo 1 > /proc/sys/net/ipv4/ip_forward | |
echo 1 > /proc/sys/net/ipv4/conf/all/forwarding | |
#echo 1 > /proc/sys/net/ipv6/conf/all/forwarding | |
} | |
function disablefwd { | |
## DISABLE IPV4 FORWARDING | |
echo 'INFO: Disabling IPV4 forwarding' | |
echo 0 > /proc/sys/net/ipv4/ip_forward | |
echo 0 > /proc/sys/net/ipv4/conf/all/forwarding | |
#echo 0 > /proc/sys/net/ipv6/conf/all/forwarding | |
} | |
function setdefpol { | |
if [ "${1}" == "drop" ]; then | |
## DEFAULT POLICY = DROP | |
echo 'INFO: Setting default policy to: DROP' | |
${IPT} -P INPUT DROP | |
${IPT} -P OUTPUT DROP | |
${IPT} -P FORWARD DROP | |
elif [ "${1}" == "reject" ]; then | |
## DEFAULT POLICY = REJECT | |
echo 'INFO: Setting default policy to: REJECT' | |
${IPT} -P INPUT REJECT | |
${IPT} -P OUTPUT REJECT | |
${IPT} -P FORWARD REJECT | |
elif [ "${1}" == "accept" ]; then | |
## DEFAULT POLICY = ACCEPT | |
echo 'INFO: Setting default policy to: ACCEPT' | |
${IPT} -P INPUT ACCEPT | |
${IPT} -P OUTPUT ACCEPT | |
${IPT} -P FORWARD ACCEPT | |
else | |
## DEFAULT POLICY = DROP | |
echo 'WARN: Keyword not identified, setting default policy to DROP' | |
${IPT} -P INPUT DROP | |
${IPT} -P OUTPUT DROP | |
${IPT} -P FORWARD DROP | |
fi | |
} | |
function enablefw { | |
# enable ip forwarding | |
enablefwd | |
# set default policy to drop | |
setdefpol drop | |
################################################################################ | |
## BLACKLIST | |
################################################################################ | |
# ${IPT} -A INPUT -i ${EXTINT} -s 37.187.195.49 -j DROP | |
# ${IPT} -A INPUT -i ${EXTINT} -s 212.156.115.16 -j DROP | |
# ${IPT} -A INPUT -i ${EXTINT} -s 195.93.172.17 -j DROP | |
################################################################################ | |
## FAILSAFE RULES | |
################################################################################ | |
## RELATED AND ESTABLISHED CONNECTIONS | |
#${IPT} -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
#${IPT} -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
#${IPT} -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT | |
${IPT} -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT | |
${IPT} -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT | |
${IPT} -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT | |
## FAILSAFE SSH | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -s ${HOMEOFFICE} -p tcp --dport 22 -j ACCEPT | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -s ${TAILSCALE} -p tcp --dport 22 -j ACCEPT | |
################################################################################ | |
## RULES FOR SUBNET | |
################################################################################ | |
## ALLOW EVERTYTHING IN, OUT AND FORWARD FOR SUBNET | |
${IPT} -A INPUT -d ${SUBNET} -i ${EXTINT} -p all -j ACCEPT | |
${IPT} -A FORWARD -d ${SUBNET} -i ${EXTINT} -o ${SUBINT} -p all -j ACCEPT | |
${IPT} -A FORWARD -s ${SUBNET} -i ${SUBINT} -o ${EXTINT} -p all -j ACCEPT | |
${IPT} -A OUTPUT -s ${SUBNET} -o ${EXTINT} -p all -j ACCEPT | |
################################################################################ | |
## INTERNAL NETWORKS | |
################################################################################ | |
## ALLOW INCOMING ALL FROM ALPHA NET OVER ALPHA INT | |
${IPT} -A INPUT -s ${ALPHANET} -i ${ALPHAINT} -p all -j ACCEPT | |
## ALLOW OUTGOING ALL TO ALPHA NET OVER ALPHA INT | |
${IPT} -A OUTPUT -d ${ALPHANET} -o ${ALPHAINT} -p all -j ACCEPT | |
## ALLOW FORWARDING ALL FROM ALPHA NET INCOMING ALPHA INT OUTGOING EXT INT | |
${IPT} -A FORWARD -s ${ALPHANET} -i ${ALPHAINT} -o ${EXTINT} -p all -j ACCEPT | |
## MASQUERADE INTERNAL IPS TO ALLOW INTERNET ACCESS FROM INTERNAL NETWORK | |
${IPT} -t nat -A POSTROUTING -s ${ALPHANET} -o ${EXTINT} -j MASQUERADE | |
## ALLOW INCOMING ALL FROM BETA NET OVER BETA INT | |
${IPT} -A INPUT -s ${BETANET} -i ${BETAINT} -p all -j ACCEPT | |
## ALLOW OUTGOING ALL TO BETA NET OVER BETA INT | |
${IPT} -A OUTPUT -d ${BETANET} -o ${BETAINT} -p all -j ACCEPT | |
## ALLOW FORWARDING ALL FROM BETA NET INCOMING BETA INT OUTGOING EXT INT | |
${IPT} -A FORWARD -s ${BETANET} -i ${BETAINT} -o ${EXTINT} -p all -j ACCEPT | |
## MASQUERADE INTERNAL IPS TO ALLOW INTERNET ACCESS FROM INTERNAL NETWORK | |
${IPT} -t nat -A POSTROUTING -s ${BETANET} -o ${EXTINT} -j MASQUERADE | |
## ALLOW INCOMING ALL FROM DOCKER NET OVER DOCKER INT | |
${IPT} -A INPUT -s ${DOCKERNET} -i ${DOCKERINT} -p all -j ACCEPT | |
## ALLOW OUTGOING ALL TO DOCKER NET OVER DOCKER INT | |
${IPT} -A OUTPUT -d ${DOCKERNET} -o ${DOCKERINT} -p all -j ACCEPT | |
## ALLOW FORWARDING ALL FROM DOCKER NET INCOMING DOCKER INT OUTGOING EXT INT | |
${IPT} -A FORWARD -s ${DOCKERNET} -i ${DOCKERINT} -o ${EXTINT} -p all -j ACCEPT | |
## MASQUERADE INTERNAL IPS TO ALLOW INTERNET ACCESS FROM INTERNAL NETWORK | |
${IPT} -t nat -A POSTROUTING -s ${DOCKERNET} -o ${EXTINT} -j MASQUERADE | |
## ALLOW INCOMING ALL FROM K8S NET OVER K8S INT | |
${IPT} -A INPUT -s ${K8SNET} -i ${K8SINT} -p all -j ACCEPT | |
## ALLOW OUTGOING ALL TO K8S NET OVER K8S INT | |
${IPT} -A OUTPUT -d ${K8SNET} -o ${K8SINT} -p all -j ACCEPT | |
## ALLOW FORWARDING ALL FROM K8S NET INCOMING K8S INT OUTGOING EXT INT | |
${IPT} -A FORWARD -s ${K8SNET} -i ${K8SINT} -o ${EXTINT} -p all -j ACCEPT | |
## MASQUERADE INTERNAL IPS TO ALLOW INTERNET ACCESS FROM INTERNAL NETWORK | |
${IPT} -t nat -A POSTROUTING -s ${K8SNET} -o ${EXTINT} -j MASQUERADE | |
################################################################################ | |
## ADMIN / SRV NETWORK ACCESS | |
################################################################################ | |
## ALLOW ALL INCOMING FROM SRV NET OVER SRV INT | |
${IPT} -A INPUT -s ${SRVNET} -i ${SRVINT} -p all -j ACCEPT | |
## ALLOW ALL OUTGOING TO SRV NET OVER SRV INT | |
${IPT} -A OUTPUT -d ${SRVNET} -o ${SRVINT} -p all -j ACCEPT | |
## ALLOW ALL FORWARDING FROM SRV NET OVER SRV INT TO ANY | |
${IPT} -A FORWARD -s ${SRVNET} -i ${SRVINT} -p all -j ACCEPT | |
## MASQUERADE SRV NET OVER EXT INT TO INTERNET | |
${IPT} -t nat -A POSTROUTING -s ${SRVNET} -o ${EXTINT} -j MASQUERADE | |
################################################################################ | |
## ROUTER VM | |
################################################################################ | |
## ALLOW INCOMING, OUTGOING, FORWARDING FROM LO OVER LO INT | |
${IPT} -A INPUT -i lo -j ACCEPT | |
${IPT} -A OUTPUT -o lo -j ACCEPT | |
${IPT} -A FORWARD -i lo -o lo -j ACCEPT | |
## ALLOW INCOMING USEFUL ICMP TO EXT IP OVER EXT INT | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -p icmp --icmp-type 0 -j ACCEPT -m comment --comment "ICMP Echo Reply" | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -p icmp --icmp-type 3 -j ACCEPT -m comment --comment "ICMP Echo Request" | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -p icmp --icmp-type 8 -j ACCEPT -m comment --comment "ICMP Echo Request" | |
${IPT} -A INPUT -d ${EXTIP} -i ${EXTINT} -p icmp --icmp-type 11 -j ACCEPT -m comment --comment "ICMP Time Exceeded" | |
## ALLOW INCOMING USEFUL ICMP TO SUB IP OVER EXT INT (STRANGE HETZNER ROUTING) | |
${IPT} -A INPUT -d ${SUBIP} -i ${EXTINT} -p icmp --icmp-type 0 -j ACCEPT -m comment --comment "ICMP Echo Reply" | |
${IPT} -A INPUT -d ${SUBIP} -i ${EXTINT} -p icmp --icmp-type 3 -j ACCEPT -m comment --comment "ICMP Echo Request" | |
${IPT} -A INPUT -d ${SUBIP} -i ${EXTINT} -p icmp --icmp-type 8 -j ACCEPT -m comment --comment "ICMP Echo Request" | |
${IPT} -A INPUT -d ${SUBIP} -i ${EXTINT} -p icmp --icmp-type 11 -j ACCEPT -m comment --comment "ICMP Time Exceeded" | |
## ALLOW OUTGOING ALL FROM EXT IP OVER EXT INT | |
${IPT} -A OUTPUT -s ${EXTIP} -o ${EXTINT} -j ACCEPT | |
## ALLOW OUTGOING ALL FROM SUB IP OVER SUB INT, EXT INT | |
${IPT} -A OUTPUT -s ${SUBIP} -o ${SUBINT} -j ACCEPT | |
${IPT} -A OUTPUT -s ${SUBIP} -o ${EXTINT} -j ACCEPT | |
################################################################################ | |
## LOGGING | |
################################################################################ | |
# create new rule for loggin | |
${IPT} -N LOGGING | |
# apply rule to all chains | |
${IPT} -A INPUT -j LOGGING | |
${IPT} -A OUTPUT -j LOGGING | |
${IPT} -A FORWARD -j LOGGING | |
# limit logging | |
${IPT} -A LOGGING -m limit --limit 5/min -j LOG --log-prefix "[iptables-dropped]: " --log-level 4 | |
# only log dropped packages | |
${IPT} -A LOGGING -j DROP | |
} | |
function disablefw { | |
disablefwd | |
setdefpol accept | |
} | |
function fwdonly { | |
enablefwd | |
setdefpol accept | |
${IPT} -t nat -A POSTROUTING -s ${ALPHANET} -j MASQUERADE | |
${IPT} -t nat -A POSTROUTING -s ${BETANET} -j MASQUERADE | |
${IPT} -t nat -A POSTROUTING -s ${DOCKERNET} -j MASQUERADE | |
${IPT} -t nat -A POSTROUTING -s ${K8SNET} -j MASQUERADE | |
${IPT} -t nat -A POSTROUTING -s ${SRVNET} -j MASQUERADE | |
} | |
################################################################################ | |
## MAIN | |
################################################################################ | |
if [ "${1}" == "enable" ]; then | |
delfwrules | |
enablefw | |
elif [ "${1}" == "disable" ]; then | |
delfwrules | |
disablefw | |
elif [ "${1}" == "fwdonly" ]; then | |
delfwrules | |
fwdonly | |
else | |
echo "Usage: $(basename \"$0\") enable | disable | fwdonly" | |
echo " enable: Enable firewall" | |
echo " disable: Disable firewall" | |
echo " fwdonly: Forwarding only (default policy: ACCEPT)" | |
exit 0 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment