Last active
January 8, 2020 00:02
-
-
Save nhibberd/b53df2f952e534115b658ded11c413f9 to your computer and use it in GitHub Desktop.
Wireguard update script
This file contains 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/sh -eu | |
TEMPLATE_DIR=${TEMPLATE_DIR:-/tmp} | |
: ${ROOT:=/etc/config} | |
: ${ENV:=$(cat /etc/config/env)} | |
: ${REGION:=$(cat /etc/config/region)} | |
: ${SUBNET:=$(cat /etc/config/subnet)} | |
: ${PREFIX:?"s3 location"} | |
if [ -z "${ENV}" ]; then | |
echo "ENV is not defined" | |
exit 1 | |
elif [ -z "${REGION}" ]; then | |
echo "REGION is not defined" | |
exit 1 | |
elif [ -z "${SUBNET}" ]; then | |
echo "SUBNET is not defined" | |
exit 1 | |
fi | |
if [ ! "$(whoami)" == "root" ]; then | |
echo "Run as root" | |
exit 1 | |
fi | |
## Pull private key secret | |
PRIVATE_KEY=$(aws secretsmanager get-secret-value --secret-id "${ENV}/vpn-private-key" --region ${REGION} | jq .SecretString -r) | |
PUBLIC_KEY=$(echo $PRIVATE_KEY | wg pubkey) | |
SERVER_ADDRESS=$(${ROOT}/wg-ip --subnet ${SUBNET} gen ${PUBLIC_KEY}) | |
mkdir -p /etc/wireguard | |
# Forcibly rewrite MSS to 1360 to prevent TCP fragmentation. Based on | |
# https://www.zeitgeist.se/2013/11/26/mtu-woes-in-ipsec-tunnels-how-to-fix/ | |
# TODO: This can probably be 1380, as wg headers are 20b smaller than IPsec | |
# Find latest payload | |
PAYLOAD=$(aws s3 ls "${PREFIX}/" --recursive | awk -F'/' '{ print $3 }' | sort -nr | head -n 1) | |
RAW_PAYLOAD=$(aws s3 cp ${PREFIX}/${PAYLOAD} -) | |
KEYS=$(echo ${RAW_PAYLOAD} | jq -r '.employees | map (.vpn."'${ENV}'") | map (select(. != null)) | map(join("\n")) | join ("\n")') | |
CURRENT=$(mktemp) | |
CONFIG=$(mktemp) | |
CREATE=$(mktemp) | |
cleanup () { | |
rm -f ${CURRENT} | |
rm -f ${CONFIG} | |
rm -f ${CREATE} | |
} | |
trap cleanup EXIT 1 | |
ADDING="" | |
REMOVING="" | |
if [ ! -f /etc/wireguard/wg0.conf ]; then | |
echo "No existing config, loading - ${PAYLOAD}" | |
cat > ${CREATE} << _CONFIG | |
[Interface] | |
Address = ${SERVER_ADDRESS} | |
ListenPort = 51820 | |
PostUp = /usr/sbin/iptables -A FORWARD -i wg0 -j ACCEPT; /usr/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; /usr/sbin/iptables -t mangle -A FORWARD -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360 | |
PostDown = /usr/sbin/iptables -D FORWARD -i wg0 -j ACCEPT; /usr/sbin/iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; /usr/sbin/iptables -t mangle -D FORWARD -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360 | |
PrivateKey = ${PRIVATE_KEY} | |
SaveConfig = true | |
_CONFIG | |
for KEY in ${KEYS}; do | |
ADDR=$(${ROOT}/wg-ip --subnet "${SUBNET}" gen "${KEY}") | |
echo "[Peer] | |
PublicKey = ${KEY} | |
AllowedIps = ${ADDR} | |
" >> ${CREATE} | |
done | |
cp ${CREATE} /etc/wireguard/wg0.conf | |
${ROOT}/wg-quick up wg0 | |
wg show | |
else | |
echo "Checking VPN config - ${PAYLOAD}" | |
wg show wg0 peers | sort > ${CURRENT} | |
echo $KEYS | tr -d '\n' | xargs -d ' ' -L 1 echo | sort > ${CONFIG} | |
for NEW in $(comm -13 ${CURRENT} ${CONFIG}); do | |
echo "Adding peer: $NEW" | |
ADDING+="${NEW}\n" | |
ADDR=$(${ROOT}/wg-ip --subnet "${SUBNET}" gen "${NEW}") | |
echo "[Peer] | |
PublicKey = ${NEW} | |
AllowedIps = ${ADDR} | |
" > ${CREATE} | |
wg addconf wg0 ${CREATE} | |
/usr/sbin/ip route add ${ADDR} dev wg0 | |
done | |
for REMOVE in $(comm -23 ${CURRENT} ${CONFIG}); do | |
echo "Removing peer: $REMOVE" | |
REMOVING+="${REMOVE}\n" | |
ADDR=$(${ROOT}/wg-ip --subnet "${SUBNET}" gen "${REMOVE}") | |
wg set wg0 peer ${REMOVE} remove | |
/usr/sbin/ip route del ${ADDR} | |
done | |
fi | |
### Slack notifications | |
RAW_SLACK_VALUE=$(aws secretsmanager get-secret-value --secret-id "${ENV}/vpn-slack" --region ${REGION} || echo "") | |
if [ ! "${RAW_SLACK_VALUE}" == "" ]; then | |
SLACK_URL=$(echo $RAW_SLACK_VALUE | jq .SecretString -r) | |
PAYLOAD="" | |
if [ ! "${ADDING}" == "" ]; then | |
NAME=$(echo $RAW_PAYLOAD | jq -r '.employees | map(select(.vpn."'${ENV}'") | select(.vpn."'${ENV}'"[] | contains("'${ADDING}'"))) | map (.name) | join("")') | |
PAYLOAD+="{ | |
\"title\": \"Adding peers\", | |
\"value\": \"${ADDING} - $NAME\" | |
}" | |
fi | |
if [ ! "${REMOVING}" == "" ]; then | |
if [ ! "${PAYLOAD}" == "" ]; then | |
PAYLOAD+=", | |
" | |
fi | |
PAYLOAD+="{ | |
\"title\": \"Removing peers\", | |
\"value\": \"${REMOVING}\" | |
}" | |
fi | |
if [ ! "${PAYLOAD}" == "" ]; then | |
echo "Sending slack notification" | |
curl -X POST -H "Content-type: application/json" $SLACK_URL --silent -d "{ | |
\"icon_emoji\": \":shield:\", | |
\"attachments\": [ | |
{ | |
\"text\": \"VPN Config updates for \`${ENV}\` environment.\", | |
\"color\": \"good\", | |
\"fields\": [ | |
${PAYLOAD} | |
] | |
} | |
] | |
}" | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment