2022-09-06 20:57:41 -06:00
|
|
|
#!/bin/bash
|
|
|
|
# FILE: wgapi:back/api/dashboard/add
|
|
|
|
# DESCRIPTION: Add a new peer
|
|
|
|
# USAGE: add ip querystring
|
|
|
|
# ERRORS:
|
|
|
|
# 3: bad args/usage
|
|
|
|
# 4: vars file not found
|
|
|
|
# 5: Wireguard not installed
|
|
|
|
# 6: Hostname in use
|
|
|
|
# 7: Hostname too short
|
|
|
|
# 8: Invalid token
|
|
|
|
# 9: Token file not found
|
|
|
|
# 10: Failed to get peer data from wg
|
2022-09-08 14:39:59 -06:00
|
|
|
# 11: Failed to generate new IPs
|
2022-09-06 20:57:41 -06:00
|
|
|
# 12: Servers file doesn't exist
|
|
|
|
# 15: Failed to add user to local wireguard
|
|
|
|
# 16: Failed to add user to federated server
|
2022-09-08 21:15:30 -06:00
|
|
|
# 17: User not found
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
CONFIG_FILE='/etc/wgapi/config'
|
|
|
|
SERVERS_FILE='/etc/wgapi/servers'
|
|
|
|
[ ${#} -eq 2 ] || exit 3
|
2022-09-08 21:44:46 -06:00
|
|
|
[ -x '/usr/bin/wg' ] || exit 5
|
2022-09-06 20:57:41 -06:00
|
|
|
[ -f "${CONFIG_FILE}" ] || exit 4
|
|
|
|
[ -f "${SERVERS_FILE}" ] || exit 12
|
|
|
|
source "${CONFIG_FILE}"
|
2022-09-08 14:44:55 -06:00
|
|
|
[ -f "${TOKENS_FILE}" ] || exit 9
|
2022-09-08 14:04:01 -06:00
|
|
|
ip="${1}"
|
2022-09-08 21:15:30 -06:00
|
|
|
qs="$(<<<"${2}" tr '&' '\n' | sed 's/?//')"
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
# Check hostname
|
2022-09-09 21:56:25 -06:00
|
|
|
hostname="$(<<<"${qs}" grep -oP 'name=(.*)' | sed 's/^name//' | xargs | tr -dc 'a-z0-9' | head -c10)"
|
2022-09-08 21:15:30 -06:00
|
|
|
printf '%s requested new peer with hostname %s\n' "${ip}" "${hostname}" >>"${LOGFILE}"
|
2022-09-06 20:57:41 -06:00
|
|
|
[[ ${#hostname} -ge 3 ]] || (
|
2022-09-08 21:15:30 -06:00
|
|
|
printf 'Rejecting hostname %s because it is too short.\n' "${hostname}" >>"${LOGFILE}"
|
2022-09-08 14:04:01 -06:00
|
|
|
printf 'Hostname too short\n' | "${LIB_DIR}/http_res" 400
|
2022-09-06 20:57:41 -06:00
|
|
|
exit 7
|
|
|
|
)
|
|
|
|
|
2022-09-08 14:04:01 -06:00
|
|
|
# Check token
|
|
|
|
token_fail(){
|
2022-09-08 21:15:30 -06:00
|
|
|
printf 'Rejecting %s request for new peer due to %s token\n' "${ip}" "${1}" >>"${LOGFILE}"
|
2022-09-08 14:04:01 -06:00
|
|
|
printf 'Invalid token\n' | "${LIB_DIR}/http_res" 403
|
|
|
|
exit 8
|
|
|
|
}
|
2022-09-08 21:15:30 -06:00
|
|
|
saved_token="$(grep "${ip}" "${TOKENS_FILE}" | cut -f2)"
|
2022-09-08 14:04:01 -06:00
|
|
|
[ "${saved_token}" == "" ] && token_fail 'missing'
|
2022-09-08 21:15:30 -06:00
|
|
|
<<<"${qs}" grep -x "t=${saved_token}" || token_fail 'mismatched'
|
2022-09-09 22:19:57 -06:00
|
|
|
printf '%s token was valid\n' "${ip}" >>"${LOGFILE}"
|
2022-09-08 14:04:01 -06:00
|
|
|
|
|
|
|
# Check user
|
2022-09-09 20:04:53 -06:00
|
|
|
username="$("${LIB_DIR}/ns_lookup_rdns" "${REMOTE_ADDR}" | cut -d'.' -f2)" || (
|
|
|
|
printf 'User not found for %s\n' "${REMOTE_ADDR}" >>"${LOGFILE}"
|
2022-09-09 21:56:25 -06:00
|
|
|
printf 'User not found' | "${LIB_DIR}/http_res" 403
|
2022-09-09 20:04:53 -06:00
|
|
|
exit 17
|
|
|
|
)
|
2022-09-09 22:12:35 -06:00
|
|
|
printf '%s identified as %s\n' "${ip}" "${username}" >>"${LOGFILE}"
|
2022-09-08 14:04:01 -06:00
|
|
|
domain="${hostname}.${username}.${TLD}"
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
# Check if new peer already exists
|
2022-09-09 20:04:53 -06:00
|
|
|
printf '%s' "${hostnames}" | grep -o "${hostname}" && (
|
2022-09-08 21:15:30 -06:00
|
|
|
printf '%s.%s.%s already exists!\n' "${hostname}" "${username}" "${TLD}" >>"${LOGFILE}"
|
|
|
|
printf 'Hostname %s already exists!\n' "${hostname}" | "${LIB_DIR}/http_res" 409
|
2022-09-06 20:57:41 -06:00
|
|
|
exit 6
|
|
|
|
)
|
2022-09-09 22:19:57 -06:00
|
|
|
domain="${hostname:?}.${username:?}.${TLD:?}"
|
|
|
|
printf 'New domain will be %s' "${domain}" >>"${LOGFILE}"
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
# Collect/parse existing peer data
|
2022-09-08 14:04:01 -06:00
|
|
|
# Create new IPs
|
2022-09-08 21:15:30 -06:00
|
|
|
peers="$(sudo "${LIB_DIR}/wg_peer_list" "${1}" tsv)" || exit 10
|
2022-09-09 21:56:25 -06:00
|
|
|
hostnames="$(<<<"${peers}" awk '{print $1}' | cut -d'.' -f1)"
|
|
|
|
ipv4s="$(<<<"${peers}" awk '{print $2}')"
|
|
|
|
ipv6s="$(<<<"${peers}" awk '{print $3}')"
|
2022-09-08 21:15:30 -06:00
|
|
|
usernumber="$(<<<"${ipv4s}" head -n1 | cut -d'.' -f3)"
|
2022-09-09 22:06:48 -06:00
|
|
|
# Increment hostnumber from 1 until an unused one is found
|
|
|
|
used_hostnumbers="$(<<<"${ipv4s}" cut -d'.' -f4 | sort | uniq)"
|
2022-09-09 22:19:57 -06:00
|
|
|
hostnumber=1; while <<<"${used_hostnumbers}" grep "${hostnumber}"
|
2022-09-09 21:29:59 -06:00
|
|
|
do ((hostnumber++))
|
2022-09-06 20:57:41 -06:00
|
|
|
done
|
|
|
|
ipv4="${IPV4_NET%.*.*}.${usernumber}.${hostnumber}"
|
|
|
|
ipv6="${IPV6_NET%:*:*}:${usernumber}:${hostnumber}"
|
2022-09-09 21:56:25 -06:00
|
|
|
printf 'IP addresses for %s created: %s %s\n' "${domain}" "${ipv4}" "${ipv6}" >>"${LOGFILE}"
|
2022-09-06 20:57:41 -06:00
|
|
|
# TODO: Check it or exit 11
|
|
|
|
|
|
|
|
# Create wg config
|
|
|
|
privkey="$(/usr/bin/wg genkey)"
|
2022-09-08 21:15:30 -06:00
|
|
|
pubkey="$(echo "${privkey}" | /usr/bin/wg pubkey)"
|
2022-09-06 20:57:41 -06:00
|
|
|
address="${ipv4}/${IPV4_NET##*/},${ipv6}/${IPV6_NET##*/}"
|
|
|
|
server_blocks=''
|
2022-09-08 21:44:46 -06:00
|
|
|
while IFS=$'\t' read -r server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_admin server_secret; do
|
2022-09-09 21:56:25 -06:00
|
|
|
[[ ${server_hostname:0:1} = \# ]] && continue # Ignore comments
|
2022-09-06 20:57:41 -06:00
|
|
|
server_psk="$(/usr/bin/wg genpsk)"
|
|
|
|
server_blocks="${server_blocks}\n[Peer] # ${server_hostname}.${TLD}\nPublicKey=${server_pubkey}\nPresharedKey=${server_psk}\nAllowedIPs=${server_ipv4}/32,${server_ipv6}/128\nEndpoint=${server_endpoint}\n"
|
|
|
|
if [ "${server_hostname}" == "${LOCAL_SERVER}" ]
|
|
|
|
# Add new user to local server
|
2022-09-08 21:15:30 -06:00
|
|
|
then printf 'Adding %s to local server...' "${domain}" >>"${LOGFILE}"
|
|
|
|
"${LIB_DIR}/wg_peer_add" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128" || (
|
|
|
|
printf 'Failed to add new peer %s to local server!' "${ipv4}" >>"${LOGFILE}"
|
2022-09-08 14:04:01 -06:00
|
|
|
# TODO: clear existing progress and exit 15
|
|
|
|
)
|
2022-09-06 20:57:41 -06:00
|
|
|
# Send new user config to federated server
|
2022-09-08 21:15:30 -06:00
|
|
|
else printf 'Sending %s to remote server %s...' "${domain}" "${server_hostname}" >>"${LOGFILE}"
|
2022-09-09 22:10:19 -06:00
|
|
|
#"${LIB_DIR}/fed_add" "${server_admin}" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128" "${server_secret}" || (
|
|
|
|
# printf 'Failed to add new peer %s to federated server %s!' "${ipv4}" "${server_hostname}" >>"${LOGFILE}"
|
|
|
|
# # TODO: clear existing progress and exit 16
|
|
|
|
#)
|
2022-09-06 20:57:41 -06:00
|
|
|
fi
|
2022-09-09 21:56:25 -06:00
|
|
|
done <"${SERVERS_FILE}"
|
2022-09-06 20:57:41 -06:00
|
|
|
wg_config="[Interface] # ${hostname}.${username}.${TLD}\nPrivateKey=${privkey}\nAddress=${address}\n${WG_DNS}\n${server_blocks}"
|
|
|
|
|
|
|
|
# Respond to user
|
2022-09-08 14:04:01 -06:00
|
|
|
# Do it before updating nameserver and certs because
|
|
|
|
# if wireguard worked, there's no going back. The admin
|
|
|
|
# can clean up missing records and certs after checking the logs
|
2022-09-08 21:15:30 -06:00
|
|
|
printf '%s' "${wg_config}" | "${LIB_DIR}/http_res"
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
# Update nameserver
|
2022-09-08 21:15:30 -06:00
|
|
|
"${LIB_DIR}/ns_update_add" "${domain}" "${ipv4}" "${ipv6}" || (
|
|
|
|
printf 'Failed to add %s %s %s to DNS server!' "${domain}" "${ipv4}" "${ipv6}" >>"${LOGFILE}"
|
|
|
|
)
|
2022-09-06 20:57:41 -06:00
|
|
|
|
|
|
|
# Create SSL cert
|
2022-09-08 21:15:30 -06:00
|
|
|
sudo "${LIB_DIR}/ssl_peer_add" "${hostname}" "${username}" "IP:${ipv4},IP:${ipv6}" || (
|
|
|
|
printf 'Failed to create certs for %s with IPS: %s %s!' "${domain}" "${ipv4}" "${ipv6}" >>"${LOGFILE}"
|
|
|
|
)
|