Skip to content

Instantly share code, notes, and snippets.

@RedDocMD
Created May 19, 2024 04:27
Show Gist options
  • Save RedDocMD/0cec7ae6f7970a2b03abcf033d771097 to your computer and use it in GitHub Desktop.
Save RedDocMD/0cec7ae6f7970a2b03abcf033d771097 to your computer and use it in GitHub Desktop.
OpenBSD Wireguard VPN setup script
#!/usr/bin/env bash
set -e
# Script to setup Wireguard and make this a VPN server
# Additionally, create client configurations and remove them
function setup() {
pushd "/etc/wireguard"
# Make key
umask 077
wg genkey | tee private.key | wg pubkey > public.key
PRIVATE_KEY=$(cat private.key)
# Make conf file
touch ${WGDEV}.conf
echo "[Interface]
PrivateKey = ${PRIVATE_KEY}
ListenPort = ${PUBLIC_PORT}
" > ${WGDEV}.conf
cp ${WGDEV}.conf ${WGDEV}.conf.part
popd
umask 133
# Add forwarding
sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
cp /etc/sysctl.conf /etc/sysctl.conf.old
echo "net.inet.ip.forwarding=1" >> /etc/sysctl.conf
echo "net.inet6.ip6.forwarding=1" >> /etc/sysctl.conf
# Setup packet filtering
cp /etc/pf.conf /etc/pf.conf.old
echo "pass in on ${WGDEV}
pass in inet proto udp from any to any port ${PUBLIC_PORT}
pass out on egress inet from (${WGDEV}:network) nat-to (${INTERFACE}:0)" >> /etc/pf.conf
pfctl -f /etc/pf.conf
# Setup networking
echo "inet 10.0.0.1 255.255.255.0 NONE
up
!/usr/local/bin/wg setconf ${WGDEV} /etc/wireguard/${WGDEV}.conf" > /etc/hostname.${WGDEV}
chmod 640 /etc/hostname.${WGDEV}
sh /etc/netstart ${WGDEV}
# Set status
echo "setup 0 ${PUBLIC_IP} ${PUBLIC_PORT}" > ${STATUS_FILE}
}
function teardown() {
sysctl net.inet.ip.forwarding=0
sysctl net.inet6.ip6.forwarding=0
mv /etc/sysctl.conf.old /etc/sysctl.conf
mv /etc/pf.conf.old /etc/pf.conf
pfctl -f /etc/pf.conf
ifconfig wg0 down
rm /etc/hostname.${WGDEV}
echo "nothing" > ${STATUS_FILE}
}
function joinConf() {
CONF=$1
NEW_CLIENT=$2
CLIENTS=$(tail -n +2 ${STATUS_FILE} | tr "\n" " ")
echo $CLIENTS
cp ${WGDEV}.conf.part ${CONF}
for OLD_CLIENT in ${CLIENTS}; do
if [[ "${OLD_CLIENT}" == "" ]]; then
continue
fi
cat ${OLD_CLIENT}.conf.part >> ${CONF}
done
}
function clientExists() {
NEW_CLIENT=$2
CLIENTS=$(tail -n +2 ${STATUS_FILE})
for OLD_CLIENT in "${CLIENTS}"; do
if [[ ${OLD_CLIENT} == ${NEW_CLIENT} ]]; then
return 1
fi
done
return 0
}
function addClient() {
local ret=clientExists "$CLIENT"
if [[ $ret -eq 1 ]]; then
echo "client ${CLIENT} already exists"
exit 1
fi
pushd /etc/wireguard
umask 077
wg genkey | tee ${CLIENT}_private.key | wg pubkey > ${CLIENT}_public.key
CLIENT_PRIVATE_KEY=$(cat ${CLIENT}_private.key)
CLIENT_PUBLIC_KEY=$(cat ${CLIENT}_public.key)
PUBLIC_KEY=$(cat public.key)
CLIENT_IP="10.0.0.$((${CLIENT_CNT} + 2))"
umask 133
echo "[Peer]
PublicKey = ${CLIENT_PUBLIC_KEY}
AllowedIPs = ${CLIENT_IP}/32
PersistentKeepalive = 25" > ${CLIENT}.conf.part
NEW_CLIENT_CNT=$((${CLIENT_CNT} + 1))
OLD_CLIENTS=$(tail -n +2 ${STATUS_FILE})
echo "setup ${NEW_CLIENT_CNT} ${PUBLIC_IP} ${PUBLIC_PORT}" > ${STATUS_FILE}
for OLD_CLIENT in "${OLD_CLIENTS}"; do
if [[ ${OLD_CLIENT} == "" ]]; then
continue
fi
echo ${OLD_CLIENT} >> ${STATUS_FILE}
done
echo ${CLIENT} >> ${STATUS_FILE}
TMP_CONF=$(mktemp -t ${WGDEV}.conf.XXXXXX)
joinConf ${TMP_CONF} ${CLIENT}
mv ${TMP_CONF} ${WGDEV}.conf
popd
sh /etc/netstart ${WGDEV}
echo "[Interface]
PrivateKey = ${CLIENT_PRIVATE_KEY}
Address = ${CLIENT_IP}/24
[Peer]
PublicKey = ${PUBLIC_KEY}
Endpoint = ${PUBLIC_IP}:${PUBLIC_PORT}
AllowedIPs = 0.0.0.0/0, ::/0" > ${CLIENT}-wg.conf
echo "Created ${CLIENT}-wg.conf"
}
function delClient() {
local ret=clientExists $CLIENT
if [[ $ret -ne 1 ]]; then
echo "client ${CLIENT} doesn't exist"
exit 1
fi
pushd /etc/wireguard
rm ${CLIENT}_private.key
rm ${CLIENT}_public.key
rm ${CLIENT}.conf.part
NEW_CLIENT_CNT=$((${CLIENT_CNT} - 1))
OLD_CLIENTS=$(tail -n +2 ${STATUS_FILE})
echo "setup ${NEW_CLIENT_CNT} ${PUBLIC_IP} ${PUBLIC_PORT}" > ${STATUS_FILE}
for OLD_CLIENT in "${OLD_CLIENTS}"; do
if [[ ${OLD_CLIENT} == "" || ${OLD_CLIENT} == ${CLIENT} ]]; then
continue
fi
echo ${OLD_CLIENT} >> ${STATUS_FILE}
done
TMP_CONF=$(mktemp -t ${WGDEV}.conf.XXXXXX)
joinConf ${TMP_CONF} ${CLIENT}
mv ${TMP_CONF} ${WGDEV}.conf
sh /etc/netstart ${WGDEV}
popd
}
if [[ ${EUID} -ne 0 ]]; then
echo "Run as root"
exit 1
fi
STATUS_FILE="/root/wg-status"
if [[ ! -f ${STATUS_FILE} ]]; then
echo "nothing" > ${STATUS_FILE}
fi
STATUS=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 1)
if [[ ! -d "/etc/wireguard" ]]; then
mkdir /etc/wireguard
echo "Created /etc/wireguard"
fi
command -v wg &>/dev/null
if [[ ! $? ]]; then
pkg_add wireguard-tools
echo "Installed Wireguard"
fi
WGDEV=wg0
if [[ $# -lt 1 ]]; then
echo "Expected: $0 <cmd>"
exit 1
fi
CMD=$1
case "${CMD}" in
"setup")
if [[ ${STATUS} != "nothing" ]]; then
echo "Already setup"
exit 1
fi
if [[ $# != 4 ]]; then
echo "Expected: $0 setup <interface> <public-ip> <port>"
exit 1
fi
INTERFACE="$2"
PUBLIC_IP="$3"
PUBLIC_PORT="$4"
setup
;;
"teardown")
teardown
;;
"add")
if [[ ${STATUS} != "setup" ]]; then
echo "First run \"setup\""
exit 1
fi
if [[ $# != 2 ]]; then
echo "Expected: $0 add <client>"
exit 1
fi
CLIENT="$2"
CLIENT_CNT=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 2)
PUBLIC_IP=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 3)
PUBLIC_PORT=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 4)
addClient
;;
"del")
if [[ ${STATUS} != "setup" ]]; then
echo "First run \"setup\""
exit 1
fi
CLIENT="$2"
CLIENT_CNT=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 2)
PUBLIC_IP=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 3)
PUBLIC_PORT=$(head -n 1 ${STATUS_FILE} | cut -d ' ' -f 4)
delClient
;;
*)
echo "Invalid cmd"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment