Skip to content

Instantly share code, notes, and snippets.

@MicroDroid
Created February 6, 2020 22:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MicroDroid/e8dda8a28e4e7ff481f422b66eadd045 to your computer and use it in GitHub Desktop.
Save MicroDroid/e8dda8a28e4e7ff481f422b66eadd045 to your computer and use it in GitHub Desktop.
Generate WireGuard peer config
#!/bin/bash
umask 077
# version of https://stackoverflow.com/a/43196141/2164304
generate_ip() {
LAST_IP=`grep -F "AllowedIPs" $LOCAL_PEER_CONFIG | cut -d '=' '-f2-' | cut -d '/' -f1 | xargs -n1 | sort -nrt . -k 3,3 -k 4,4 | head -n1`
IP_HEX=$(printf '%.2X%.2X%.2X%.2X\n' `echo $LAST_IP | sed -e 's/\./ /g'`)
NEXT_IP_HEX=$(printf %.8X `echo $(( 0x$IP_HEX + 1 ))`)
NEXT_IP=$(printf '%d.%d.%d.%d\n' `echo $NEXT_IP_HEX | sed -r 's/(..)/0x\1 /g'`)
echo "$NEXT_IP"
}
HELP="Usage:
mkwg [args] client-name
-h / --help: Show this thing
-c / --config [/etc/wireguard/wg0.conf]: Specify local peer configuration
-p / --publickey [read from /etc/wireguard/publickey]: Specify local peer public key
-o / --output [./<client-name>]: Specify directory to output config
-w / --write [false]: Write to local peer config
"
# CLI args
REMOTE_PEER_NAME=""
OUTPUT_DIR=""
LOCAL_PEER_CONFIG="/etc/wireguard/wg0.conf"
WRITE_LOCAL_PEER_CONFIG=0
# Things to figure out
LOCAL_PEER_PUBLIC_IP=""
LOCAL_PEER_PUBLIC_KEY=""
LOCAL_PEER_PORT=""
REMOTE_PEER_WIREGUARD_IP=""
# Parse CLI args
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-c|--config)
LOCAL_PEER_CONFIG="$2"
shift # past argument
shift # past value
;;
-h|--help)
echo "$HELP"
exit
;;
-p|--publickey)
LOCAL_PEER_PUBLIC_KEY="$2"
shift # past argument
shift # past value
;;
-o|--output)
OUTPUT_DIR="$2"
shift # past argument
shift # past value
;;
-w|--write)
WRITE_LOCAL_PEER_CONFIG=1
shift # past argument
shift # past value
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
REMOTE_PEER_NAME="$POSITIONAL"
# Verify input & skim down some data
if [ -z "$REMOTE_PEER_NAME" ]; then
>&2 echo "$HELP"
exit 1
fi
if [ -z "$OUTPUT_DIR" ]; then
OUTPUT_DIR="./$REMOTE_PEER_NAME"
fi
if [ ! -r "$LOCAL_PEER_CONFIG" ]; then
>&2 echo "Local peer's configuration cannot be read at '$LOCAL_PEER_CONFIG'"
exit 1
fi
LOCAL_PEER_PUBLIC_IP=`curl -s https://ipinfo.io/ip`
if [ -z "$LOCAL_PEER_PUBLIC_IP" ]; then
>&2 echo "Local peer's public IP could not be fetched"
exit 1
fi
LOCAL_PEER_PORT=`grep -m1 -F "ListenPort" "$LOCAL_PEER_CONFIG" | cut -d '=' '-f2-' | xargs`
if [ -z "$LOCAL_PEER_PUBLIC_KEY" ]; then
if [ ! -r "/etc/wireguard/publickey" ]; then
>&2 echo "Local peer public key could not be read at /etc/wireguard/publickey"
exit 1
fi
LOCAL_PEER_PUBLIC_KEY=`cat /etc/wireguard/publickey`
# Just makin' sure
if [ -z "$LOCAL_PEER_PUBLIC_KEY" ]; then
>&2 echo "Local peer public key could not be found at /etc/wireguard/publickey"
exit 1
fi
fi
if [[ "$WRITE_LOCAL_PEER_CONFIG" -eq "1" && ! -w "$LOCAL_PEER_CONFIG" ]]; then
>&2 echo "Local peer configuration is not writable"
exit 1
fi
REMOTE_PEER_WIREGUARD_IP=`generate_ip`
# Actual work heheheheh
if [ -d "$OUTPUT_DIR" ]; then
>&2 echo "Directory '$OUTPUT_DIR' exists."
exit 1
fi
# Create a directory for the client
mkdir "$OUTPUT_DIR"
# Generate pub/priv keys, and a preshared key
wg genkey | tee "$OUTPUT_DIR/privatekey" | wg pubkey > "$OUTPUT_DIR/publickey"
wg genkey > "$OUTPUT_DIR/preshared"
# Write configuration
cat <<EOT >> "$OUTPUT_DIR/config.conf"
[Interface]
Address = $REMOTE_PEER_WIREGUARD_IP/32
DNS = 1.1.1.1,1.0.0.1
MTU=1280
PrivateKey = `cat "$OUTPUT_DIR/privatekey"`
[Peer]
PublicKey = $LOCAL_PEER_PUBLIC_KEY
PresharedKey = `cat "$OUTPUT_DIR/preshared"`
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = $LOCAL_PEER_PUBLIC_IP:$LOCAL_PEER_PORT
EOT
# Set permissions
chmod 700 "$OUTPUT_DIR"
chmod 600 "$OUTPUT_DIR/privatekey"
chmod 600 "$OUTPUT_DIR/publickey"
chmod 600 "$OUTPUT_DIR/preshared"
REMOTE_PEER_CONFIG="
[Peer]
PublicKey = `cat "$OUTPUT_DIR/publickey"`
PresharedKey = `cat "$OUTPUT_DIR/preshared"`
AllowedIPs = $REMOTE_PEER_WIREGUARD_IP/32
"
if [ "$WRITE_LOCAL_PEER_CONFIG" -eq "1" ]; then
echo -e "\n\n$REMOTE_PEER_CONFIG" >> $LOCAL_PEER_CONFIG
else
echo -e "Copy the following configuration to local peer's config (like /etc/wireguard/wg0.conf):\n"
echo "$REMOTE_PEER_CONFIG"
fi
if [ -x "$(command -v qrencode)" ]; then
echo -e "QR code of new peer's config:\n"
qrencode -t ansi "$REMOTE_PEER_CONFIG"
echo -e "\nRemote peer's configuration is also available at $OUTPUT_DIR/config.conf"
else
echo -e "QR code could not be generated because 'qrencode' is not installed."
echo -e "Copy remote peer's configuration from $OUTPUT_DIR/config.conf"
fi
echo ">> Configuration finished. Make sure to restart WireGuard."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment