Skip to content

Instantly share code, notes, and snippets.

@jbfriedrich
Last active January 7, 2024 22:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbfriedrich/63914bd57b1be9a50d59be09bb2fb026 to your computer and use it in GitHub Desktop.
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.
#!/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