Skip to content

Instantly share code, notes, and snippets.

@mrdima
Last active September 24, 2020 09:39
Show Gist options
  • Save mrdima/e0098308f2351e90132c7cf0e4fa460c to your computer and use it in GitHub Desktop.
Save mrdima/e0098308f2351e90132c7cf0e4fa460c to your computer and use it in GitHub Desktop.
Retain source IP for weave overlay network in Kubernetes
#!/bin/bash
# Inserts or removes iptables rules to prevent snat to the hosts local weave ip ranges
# This way the source ip will be retained for traffic not coming from weave
# Requires weave to be running, the script does wait for weave report to respond
echo running $0 $1
action="${1:-start}"
echo action: ${action}
#functions taken from: https://stackoverflow.com/questions/10768160/ip-address-converter
dec2ip () {
local ip dec=$@
for e in {3..0}
do
((octet = dec / (256 ** e) ))
((dec -= octet * 256 ** e))
ip+=$delim$octet
delim=.
done
printf '%s\n' "$ip"
}
ip2dec () {
local a b c d ip=$@
IFS=. read -r a b c d <<< "$ip"
printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"
}
weaverange=$(/opt/bin/weave report | jq -rM '.IPAM.Range')
echo weave range is: ${weaverange}
/opt/bin/weave report | jq -M '.IPAM.Entries' > /tmp/weave-ipam.json
hostname=$(hostname -s)
# Lowercase the hostname
hostname="${hostname,,}"
# Get the Tokens (IP Ranges) for the specific host
ipranges=$(cat /tmp/weave-ipam.json | jq -r ".[] | select(.Nickname == \"${hostname}\") .Token")
echo local weave ip networks for host ${hostname} is/are: ${ipranges}
# Get the Sizes (IP Ranges) for the specific host
sizes=$(cat /tmp/weave-ipam.json | jq -r ".[] | select(.Nickname == \"${hostname}\") .Size")
echo number of hosts \(size\) in those networks are: ${sizes}
from_ips_array=( ${ipranges} )
sizesa=( ${sizes} )
# if the number of elements in ipranges and sizes aren't equal there's something wrong (shoudln't happen)
if [ ${#sizesa[@]} -ne ${#from_ips_array[@]} ]
then
echo number of ipranges and sizes not equal
exit 1
fi
end_ips=""
i=0
for size in $sizes
do
from_ip=${from_ips_array[$i]}
from_ip_dec=$(ip2dec "$from_ip")
let end_ip=$from_ip_dec+${sizesa[$i]}-1
end_ips="${end_ips} $(dec2ip $end_ip)"
let i++
done
#Remove leading whitespace
end_ips="$(echo -e "${end_ips}" | sed -e 's/^[[:space:]]*//')"
echo "end_ips: ${end_ips}"
end_ips_array=( ${end_ips} )
# Check if weave MASQUERADE rule already exists
/usr/sbin/iptables -n -L WEAVE -t nat > /tmp/weave-iptables.txt
if grep -qe "MASQUERADE.*all.*[ !]${weaverange}.*[ !]${weaverange}" /tmp/weave-iptables.txt; then
echo weave snat rules exist, inserting or removing workaround rules in nat table, chain WEAVE at line 2
i=0
for iprange in $ipranges
do
if grep -qe "RETURN.*all.*!${weaverange}.*0.0.0.0/0.*$iprange-${end_ips_array[$i]}" /tmp/weave-iptables.txt; then
if [ ${action} == "stop" ]; then
echo "removing (iptables -t nat -D WEAVE \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN)"
/usr/sbin/iptables -t nat -D WEAVE \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN
else
echo "exists, not re-inserting (iptables -t nat -I WEAVE 2 \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN)"
fi
else
if [ ${action} == "stop" ]; then
echo "not found so no need to remove (iptables -t nat -D WEAVE \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN)"
else
echo "inserting (iptables -t nat -I WEAVE 2 \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN)"
/usr/sbin/iptables -t nat -I WEAVE 2 \! -s ${weaverange} -m iprange --dst-range $iprange-${end_ips_array[$i]} -j RETURN
fi
fi
i=$((i+1))
done
else
echo weave snat rules not found, weave not exposed yet or not running
fi
# Cleanup temporary files
rm /tmp/weave-ipam.json /tmp/weave-iptables.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment