Skip to content

Instantly share code, notes, and snippets.

@lucyllewy
Created May 6, 2014 20:34
Show Gist options
  • Save lucyllewy/af1e70513ae295d1ae16 to your computer and use it in GitHub Desktop.
Save lucyllewy/af1e70513ae295d1ae16 to your computer and use it in GitHub Desktop.
executes on libvirt domains starting up and shutting down to add and remove port forwards. useful for systems that only have a single public ip. plonk into /etc/libvirt/hooks, create a directory /etc/libvirt/iptables.d with a file for each domain you wish to forward ports to.
#!/bin/bash
# Copyright 2014 Daniel Llewellyn
# Released under GPLv3
# syntax for config file
# --
#PUBLIC_IP="1.2.3.4" # optional - the public ip address to listen on, will default to first public ip in `ip addr list` if unspecified or empty.
#PRIVATE_IP="192.168.122.x" # mandatory - the ip of the domain's natted network.
#PORTSPEC="80/tcp" # partially mandatory - public-side - can be just "80" in which case tcp is assumed, alternative to tcp, udp can be specified.
#DESTPORT="80" # optional - private-side - just the port number only
#BRIDGE="virbr0" # mandatory - the bridge that the domain's virtual network is connected to - virbr0 is usually correct
CONFIGDIR=/etc/libvirt/iptables.d
[ -z "$1" ] && exit 1
[ -f "$CONFIGDIR/$1" ] && source "$CONFIGDIR/$1" || exit 0
if [ -z "$PUBLIC_IP" ]; then
PUBLIC_IP="$( \
ip addr list | \
grep -e 'inet ' | grep -ve 127\. \
-e 192.168\. \
-e 10\. \
-e 172\.1[6-9]\. \
-e 172\.2[0-9]\. \
-e 172\.3[0-1]\. | \
awk '{ print $2 }' | cut -d/ -f1 \
)"
fi
[ -z "$PRIVATE_IP" ] && exit 3
[ -z "$PORTSPEC" ] && exit 4
[ -z "$BRIDGE" ] && exit 5
PROTOCOL="$(echo "$PORTSPEC" | cut -d/ -f2)"
ORIGPORT="$(echo "$PORTSPEC" | cut -d/ -f1)"
[ -z "$PROTOCOL" ] && PROTOCOL=tcp
[ -z "$DESTPORT" ] && DESTPORT="$ORIGPORT"
IPT_COMMAND="iptables"
IPT_NETSPEC="-p $PROTOCOL -d $PUBLIC_IP --dport"
IPT_NAT="PREROUTING -p $PROTOCOL -d $PUBLIC_IP --dport $ORIGPORT -j DNAT --to $PRIVATE_IP:$DESTPORT"
IPT_FORWARD="FORWARD -p $PROTOCOL --dport $DESTPORT -o $BRIDGE -j ACCEPT"
apply() {
$IPT_COMMAND -t nat -I $IPT_NAT
$IPT_COMMAND -I $IPT_FORWARD
}
remove() {
$IPT_COMMAND -t nat -D $IPT_NAT
$IPT_COMMAND -D $IPT_FORWARD
}
case $2 in
start)
apply
;;
stopped)
remove
;;
reconnect)
remove
apply
;;
*)
exit 255
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment