Skip to content

Instantly share code, notes, and snippets.

@colemar
Last active April 20, 2024 20:55
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save colemar/030fe6eef8f01858052dc6c29c8cc022 to your computer and use it in GitHub Desktop.
Save colemar/030fe6eef8f01858052dc6c29c8cc022 to your computer and use it in GitHub Desktop.
Manage Wireguard peers (IPv4 only)

Manage Wireguard peers (IPv4 only)

List, add or delete Wireguard peers. Also show client configuration for already added peers.

wg-peer [add|show <peer>|del <peer>|list]

where:

  • a[dd] add a new peer
  • s[how] show peer configuration
  • d[el] delete peer
  • l[ist] list peers

<peer> is the peer public key as shown by list command

Configuration files for clients are saved in /etc/wireguard/clients. If there are multiple Wireguard interfaces, wg-peer chooses the first one listed by wg show interfaces (most likely wg0).

Examples

  • list peers: wg-peer l
  • add a new peer: wg-peer a
  • show client configuration for peer: wg-peer s kTU5yhp1qPBHsKhKs4aSgPKRotU4bGPhl3y8dHD1Ki4=
  • delete peer: wg-peer d kTU5yhp1qPBHsKhKs4aSgPKRotU4bGPhl3y8dHD1Ki4=

Screenshots

Screenshot Screenshot Screenshot Screenshot

Based on new-wireguard-peer.sh by robinlandstrom.

#!/bin/bash
readonly CFOLDER=/etc/wireguard/clients
readonly THISFILE=$(basename $0)
# =================================================
main () {
# Check for root privileges
[[ $USER == root ]] || { echo "Root privileges required. Try: sudo $THISFILE"; return 1; }
# Find Wireguard interface
if=$(wg show interfaces)
[[ $if =~ $'\n' ]] && { echo "WARNING: multiple Wireguard interfaces detected"; }
read -r INTERFACE <<<$if; readonly INTERFACE
echo "Using interface $INTERFACE"
case $1 in
a*)
add_new_peer
;;
s*)
show_peer_conf $2
;;
d*)
delete_peer $2
;;
l*)
list_peers
;;
*)
usage
;;
esac
}
# =================================================
usage () {
cat <<USAGE
$THISFILE [add|show <peer>|del <peer>|list]
a[dd] : add a new peer
s[how] : show peer configuration
d[el] : delete peer
l[ist] : list peers
<peer> is peer public key as shown by list command
USAGE
}
build_peer_list () {
PEERLIST=':'$(wg show $INTERFACE peers | awk '{printf $1":"}')
}
check_peer_exists () {
local pk=$1
build_peer_list
[[ $PEERLIST =~ ":${pk}:" ]] || { echo "Cannot find peer $pk"; return 1; }
}
show_peer_conf () {
local pk=$1
check_peer_exists $pk || return 1
local clientfile=$CFOLDER/$(md5sum <<<${pk}); clientfile=${clientfile%% *}
[[ -r $clientfile ]] || { echo "Cannot read $clientfile"; return 1; }
qrencode -t ANSIUTF8 < $clientfile
cat $clientfile
echo -e "---------\n"
wg show $INTERFACE | awk '$0=="peer: '${pk}'"{f=1; print; next} /^peer:/{f=0} f'
}
delete_peer () {
local pk=$1
check_peer_exists $pk || return 1
wg set $INTERFACE peer $pk remove && {
wg-quick save ${INTERFACE}
clientfile=$CFOLDER/$(md5sum <<<${pk}); clientfile=${clientfile%% *}
rm -f $clientfile
echo "Removed peer $pk"
} || { echo "Cannot remove peer $pk"; return 1; }
}
list_peers () {
wg show $INTERFACE |\
awk '/^peer:/{
f=1
print "# '$THISFILE' show '\''"$2"'\''"
print "# '$THISFILE' del '\''"$2"'\''"
print
next
}
f'
}
add_new_peer () {
# Generate peer keys
PRIVATE_KEY=$(wg genkey)
PUBLIC_KEY=$(echo ${PRIVATE_KEY} | wg pubkey)
PRESHARED_KEY=$(wg genpsk)
# Read server key from interface
SERVER_PUBLIC_KEY=$(wg show ${INTERFACE} public-key)
# Get next free peer IP (This will break after x.x.x.255)
PEER_ADDRESS=$(wg show ${INTERFACE} allowed-ips |\
cut -f 2 |\
awk -F'[./]' '{print $1"."$2"."$3"."1+$4"/"$5}' |\
sort -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -n | tail -n1)
# Try to guess nameserver
NAMESERVER=$(ip -j addr show $INTERFACE | jq -r '.[0].addr_info[0].local')
nslookup google.com $NAMESERVER > /dev/null || {
NAMESERVER=$(nslookup bogusname | awk '/^Server:/{print $2}')
[[ ! $NAMESERVER =~ ^127 ]] && nslookup google.com $NAMESERVER > /dev/null || NAMESERVER="8.8.8.8, 1.1.1.1"
}
echo "Guessed nameserver: $NAMESERVER"
LISTENPORT=$(wg show ${INTERFACE} listen-port)
ENDPOINT=$(curl -s ipinfo.io | jq -r '.ip')
# Add peer
wg set ${INTERFACE} peer ${PUBLIC_KEY} preshared-key <(echo ${PRESHARED_KEY}) allowed-ips ${PEER_ADDRESS} || {
echo "Cannot add peer ${PEER_ADDRESS} with public key ${PUBLIC_KEY}"
return 1
}
wg-quick save ${INTERFACE}
# Generate peer config
read -r -d$'\x04' CONFIG << END_OF_CONFIG
[Interface]
Address = ${PEER_ADDRESS}
PrivateKey = ${PRIVATE_KEY}
DNS = ${NAMESERVER}
[Peer]
PublicKey = ${SERVER_PUBLIC_KEY}
PresharedKey = ${PRESHARED_KEY}
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1
Endpoint = ${ENDPOINT}:${LISTENPORT}
END_OF_CONFIG
# Save added peer config
clientfile=$CFOLDER/$(md5sum <<<${PUBLIC_KEY}); clientfile=${clientfile%% *}
mkdir -p $CFOLDER
touch $clientfile
chmod go-rwx $clientfile
echo "$CONFIG" >${clientfile}
# Show added peer config
show_peer_conf ${PUBLIC_KEY}
}
# =================================================
main "$@"
@marios88
Copy link

really good, maybe add the following to check if jq and curl exists first

# Check if "jq" command exists
if ! command -v jq &> /dev/null; then
    echo "jq is not installed. Please install it and try again."
    exit 1
fi

# Check if "curl" command exists
if ! command -v curl &> /dev/null; then
    echo "curl is not installed. Please install it and try again."
    exit 1
fi

@luke-meshii
Copy link

Hi, i am getting an "unable to parse IP address: 'public' when running this on my Ubuntu Wireguard server, any ideas?

image

@colemar
Copy link
Author

colemar commented Nov 3, 2023

Hi, i am getting an "unable to parse IP address: 'public' when running this on my Ubuntu Wireguard server, any ideas?

Try: bash -x ./wg-peer add

Then attach the output here.

@4li-ra
Copy link

4li-ra commented Feb 6, 2024

in first time if you did not created any peer before allowed-ips will be empty and got error, i think you should consider this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment