Skip to content

Instantly share code, notes, and snippets.

@starkers
Created October 2, 2015 15:39
Show Gist options
  • Select an option

  • Save starkers/4a3f7c5b2557f1de3e93 to your computer and use it in GitHub Desktop.

Select an option

Save starkers/4a3f7c5b2557f1de3e93 to your computer and use it in GitHub Desktop.
A reasonably secure iptables stack to port forward to containers and isolate internal LANs
#!/usr/bin/env bash
# I use this on servers hosting multiple containers.
# It lets me reasonably easily manage ports without typing too much
# Works on openvz and lxc... nothing really magical
# Beware the spoof detection ranges.. if you expect legit traffic from one of these networks the modify it
# There are a few bugs but generally this works well.. YMMV -david
#public IP on my host (eth0)
IP1=178.62.XX.XX
#Additional IPs, typically aliased on eth0:X or assigned to a VM on venet0
IP2=178.62.XX.XY
IP3=178.62.XX.XZ
IP4=178.62.XX.YX
#hint "ip a add 1.2.3.4/32 dev eth0:6"
#We specify internal LANs for VMs, this will allow us to control their egress traffic later
#IMPORTANT: export these as I'll want to parse variables called ^LAN* with env later on
#sites and generally not so security concious VMs
export LAN1=10.3.1.0/24
#blockchain stuffs
export LAN2=10.3.2.0/24
#a friends
export LAN3=10.3.3.0/24
#The physical device our host server has, typically eth0
HWNIC=eth0
#Path to iptables executable
IPT=/sbin/iptables
function : (){
#This function gets sent 4 variables
# it will allow us to bind a VM to one of our public IPs
## Setup the DNAT
$IPT -t nat -I PREROUTING -p tcp -d $IP_PUB --dport $PORT_PUB -j DNAT --to $IP_INT:$PORT_INT
## Allow it to forward
$IPT -A FORWARD -p tcp -d $IP_PUB --dport $PORT_INT -j ACCEPT
## Allow the inbound
$IPT -A INPUT -p tcp -d "$IP_PUB" --dport $PORT_PUB -j ACCEPT
echo "+ $IP_PUB:$PORT_PUB -> $IP_INT:$PORT_INT"
}
function :udp (){
#This function gets sent 4 variables
# it will allow us to bind a VM to one of our public IPs
## Setup the DNAT
$IPT -t nat -I PREROUTING -p udp -d $IP_PUB --dport $PORT_PUB -j DNAT --to $IP_INT:$PORT_INT
## Allow it to forward
$IPT -A FORWARD -p udp -d $IP_PUB --dport $PORT_INT -j ACCEPT
## Allow the inbound
$IPT -A INPUT -p udp -d "$IP_PUB" --dport $PORT_PUB -j ACCEPT
echo "+ $IP_PUB:$PORT_PUB -> $IP_INT:$PORT_INT"
}
function list (){
for policy in INPUT OUTPUT FORWARD ; do
echo "------------------------START $policy CHAIN------------------------"
$IPT -L "${policy}" -n --line-numbers
echo "------------------------END $policy" ; echo
done
for chain in PREROUTING OUTPUT POSTROUTING ; do
echo "------------------------START NAT chain: $policy ------------------------"
$IPT -t nat -L "$chain" -n --line-numbers
echo "------------------------END $policy" ; echo
done
}
stop(){
echo "# stopping firewall entirely"
$IPT -F
$IPT -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
}
start(){
echo "# starting firewall"
for spoofed in \
10.0.0.0/8 \
172.16.0.0/12 \
192.168.0.0/16 \
244.0.0.0/4 \
127.0.0.0/8 \
; do
echo "| blocking spoofed traffic on $HWNIC from $spoofed" # on $HWNIC"
$IPT -A INPUT -i "$HWNIC" -s "$spoofed" -j LOG --log-prefix "IP_SPOOF: "
$IPT -A INPUT -i "$HWNIC" -s "$spoofed" -j DROP
done
# echo "+ $BR_NET on $HWNIC"
# $IPT -A INPUT -i "$HWNIC" -s "$BR_NET" -j ACCEPT
# echo "+ ICMP PING responces only"
# ### ** assumed that default INPUT policy set to DROP ** #############
# $IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
# $IPT -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
# $IPT -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
# ## ** all our server to respond to pings ** ##
# $IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
echo "| setting INPUT policy to DROP"
$IPT -P INPUT DROP
echo "+ setting FORWARD policy to ACCEPT"
$IPT -P FORWARD ACCEPT
echo "+ setting OUTPUT policy to ACCEPT"
$IPT -P OUTPUT ACCEPT
########## allow loopback #############
echo "+ global: I/O ACCEPT on lo"
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
########## Global allows #############
echo "+ global: accept *:22 on $HWNIC"
$IPT -A INPUT -i "$HWNIC" -m tcp -p tcp --dport 22 -j ACCEPT
echo "+ global: accept PING replies"
$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
echo "+ allow established and related traffic (state based)"
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
########## LAN ISOLATION #############
# Here we ensure that $LAN1 cannot contact other internal LANS.. EG: $LAN2 or $LAN3 etc..
#
# First lets asses if there is more than one $LAN[x] variable
LAN_VARS="$(env | grep "^LAN[0-999]")"
LAN_TOTAL="$(wc -l <<<"$LAN_VARS" )"
if [ "$LAN_TOTAL" -gt 1 ]; then
# if we have more than 1 $LAN[x] variable, isolate them from each other"
function fwd_drop(){
echo "| blocking traffic between $1 and $2"
$IPT -A FORWARD -s $1 -d $2 -j DROP
}
fwd_drop $LAN1 $LAN2
fwd_drop $LAN1 $LAN3
fwd_drop $LAN2 $LAN1
fwd_drop $LAN2 $LAN3
fwd_drop $LAN3 $LAN1
fwd_drop $LAN3 $LAN2
fi
echo "# source NAT section"
echo "/ nat postrouting enabled from $LAN1 - $IP1"
$IPT -t nat -A POSTROUTING -s $LAN1 -o $HWNIC -j SNAT --to $IP1
echo "/ nat postrouting enabled from $LAN2 - $IP2"
$IPT -t nat -A POSTROUTING -s $LAN2 -o $HWNIC -j SNAT --to $IP2
echo "/ nat postrouting enabled from $LAN3 - $IP3"
$IPT -t nat -A POSTROUTING -s $LAN3 -o $HWNIC -j SNAT --to $IP3
# # Allow direct connections into our PRIMARY IP
# echo "# public IP rules: $IP1"
$IPT -A INPUT -p tcp --dport 80 -d $IP1 -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -d $IP1 -j ACCEPT
#OpenVZ Web panel
$IPT -A INPUT -p tcp --dport 3030 -d $IP1 -j ACCEPT
# # Route ports on our PRIMARY IP to VMs
# IP_PUB="$IP1" IP_INT=10.3.1.1 PORT_PUB=2222 PORT_INT=22 :
IP_PUB="$IP2" IP_INT=10.3.1.11 PORT_PUB=22 PORT_INT=22 :
# IP_PUB="$IP3" IP_INT=10.3.0.65 PORT_PUB=22 PORT_INT=22 :
# Route ports on our other IPs to other VMs
echo "# public IP rules: $IP2 git.fcplm.net"
IP_PUB="$IP2" IP_INT=10.3.7.5 PORT_PUB=22 PORT_INT=22 :
IP_PUB="$IP2" IP_INT=10.3.7.5 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP2" IP_INT=10.3.7.5 PORT_PUB=443 PORT_INT=443 :
# nzb: SABnzb
IP_PUB="$IP2" IP_INT=10.3.1.5 PORT_PUB=31645 PORT_INT=9090 :
# nzb: CouchPotato
IP_PUB="$IP2" IP_INT=10.3.1.5 PORT_PUB=31646 PORT_INT=5050 :
# nzb: Sickbeard
IP_PUB="$IP2" IP_INT=10.3.1.5 PORT_PUB=31647 PORT_INT=8081 :
# nzb: SSH
IP_PUB="$IP2" IP_INT=10.3.1.5 PORT_PUB=31648 PORT_INT=22 :
# syncthing
IP_PUB="$IP1" IP_INT=10.3.2.4 PORT_PUB=80 PORT_INT=80 : #export of some stuff in http (htaccess)
IP_PUB="$IP2" IP_INT=10.3.2.4 PORT_PUB=8080 PORT_INT=8080 : #syncthing https gui
IP_PUB="$IP2" IP_INT=10.3.2.4 PORT_PUB=22000 PORT_INT=22000 : #syncthing egress
IP_PUB="$IP2" IP_INT=10.3.2.4 PORT_PUB=11000 PORT_INT=8112 : #deluge
#s media munch.digtux.com
IP_PUB="$IP1" IP_INT=10.3.4.10 PORT_PUB=3200 PORT_INT=22 : #ssh
IP_PUB="$IP1" IP_INT=10.3.4.10 PORT_PUB=3201 PORT_INT=8001 : #sab
IP_PUB="$IP1" IP_INT=10.3.4.10 PORT_PUB=3202 PORT_INT=8002 : #sick
# notes: rainy/tomboy notes (ssl)
IP_PUB="$IP2" IP_INT=10.3.2.3 PORT_PUB=31641 PORT_INT=31641 :
# misc: SSH in for unison and rsnapshot backups
IP_PUB="$IP2" IP_INT=10.3.7.1 PORT_PUB=31422 PORT_INT=22 :
#gollum
# IP_PUB="$IP2" IP_INT=10.3.7.5 PORT_PUB=31351 PORT_INT=4000 :
#Flaskwallet nginx
IP_PUB="$IP2" IP_INT=10.3.2.2 PORT_PUB=7264 PORT_INT=7264 :
#minecraft SSH
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=22 PORT_INT=22 :
#toms minecraft Daemon
IP_PUB="$IP2" IP_INT=10.3.1.21 PORT_PUB=25565 PORT_INT=25565 : #legacy
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25565 PORT_INT=25565 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25566 PORT_INT=25566 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25567 PORT_INT=25567 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25568 PORT_INT=25568 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25569 PORT_INT=25569 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=25570 PORT_INT=25570 :
#mc1 mumble
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=64738 PORT_INT=64738 :
IP_PUB="$IP5" IP_INT=10.3.1.21 PORT_PUB=64738 PORT_INT=64738 :udp
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=22 PORT_INT=22 :
#alex minec6aft Daemon
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=25565 PORT_INT=25565 : #legacy
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=25565 PORT_INT=25565 :
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=25566 PORT_INT=25566 :
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=25567 PORT_INT=25567 :
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=25568 PORT_INT=25568 :
IP_PUB="$IP6" IP_INT=10.3.1.22 PORT_PUB=8123 PORT_INT=8123 :
#AKA: some server
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=22 PORT_INT=22 :
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=443 PORT_INT=443 :
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=25 PORT_INT=25 : #postfix
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=587 PORT_INT=587 : #postfix
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=993 PORT_INT=993 : #dovecot imaps
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=2703 PORT_INT=2703 : #Razor2
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=24441 PORT_INT=24441 : #pyzor
IP_PUB="$IP7" IP_INT=10.3.7.7 PORT_PUB=24441 PORT_INT=24441 :udp #pyzor
# Ringos dns
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=2028 PORT_INT=22 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=2028 PORT_INT=2222 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=3306 PORT_INT=3306 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=4444 PORT_INT=4444 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=4567 PORT_INT=4567 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=4568 PORT_INT=4568 :
IP_PUB="$IP2" IP_INT=10.3.5.1 PORT_PUB=53 PORT_INT=53 :udp
# Johns SSH
IP_PUB="$IP2" IP_INT=10.3.4.1 PORT_PUB=5122 PORT_INT=22 :
# Proxy
IP_PUB="$IP2" IP_INT=10.3.6.1 PORT_PUB=3128 PORT_INT=3128 :
# mx1
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=443 PORT_INT=443 :
#smtp, submission
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=25 PORT_INT=25 :
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=587 PORT_INT=587 :
#imaps
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=993 PORT_INT=993 :
#pyzor (anti spam)
IP_PUB="$IP2" IP_INT=10.3.1.3 PORT_PUB=24441 PORT_INT=24441 :
# IP3 -"FLEXI" IP (g3)
IP_PUB="$IP3" IP_INT=10.3.3.1 PORT_PUB=22 PORT_INT=22 :
IP_PUB="$IP3" IP_INT=10.3.3.1 PORT_PUB=80 PORT_INT=80 :
IP_PUB="$IP3" IP_INT=10.3.3.1 PORT_PUB=443 PORT_INT=443 :
service fail2ban restart
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
iptables-save
;;
restart)
stop
start
;;
list)
list
;;
*)
echo $"Usage: $0 {start|stop|restart|status|list}"
exit 1
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment