Got peer listing working
parent
1001f68ca6
commit
6d62db1acb
|
@ -1,69 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/api/dashboard/add
|
||||
# DESCRIPTION: Add a new peer
|
||||
# USAGE: add ip username querystring postdata
|
||||
|
||||
fail() {
|
||||
printf "Status: 500 Internal Server Error\nContent-Type: text/plain\n\n${1}\n"
|
||||
exit
|
||||
}
|
||||
[ "$#" == "3" ] || fail
|
||||
source ../../env/vars
|
||||
TOKENS_FILE='./tokens'
|
||||
|
||||
# Parse input
|
||||
hostname="$(printf ${3}\n | jq -r '.name' | xargs | tr -dc '[a-z0-9]' | head -c10)"
|
||||
[[ ${#hostname} -ge 3 ]] || fail "Hostname too short"
|
||||
|
||||
# Check token
|
||||
saved_token=$(grep "${1}" "${TOKENS_FILE}" | cut -f2)
|
||||
[ "${saved_token}" == "" ] && fail "Invalid token"
|
||||
printf "${2}" | grep "t=${saved_token}" || fail "Invalid token"
|
||||
|
||||
# Collect existing peer data
|
||||
peers="$(sudo ../../lib/wg/peer/list ${1} tsv)"
|
||||
hostnames="$(printf "${peers}" | awk '{print $0}')"
|
||||
ipv4s="$(printf "${peers}" | awk '{print $1}')"
|
||||
ipv6s="$(printf "${peers}" | awk '{print $2}')"
|
||||
usernumber="$(printf ${ipv4s} head -n1 | cut -d'.' -f3)"
|
||||
hostnumber=$(
|
||||
printf "$(printf "${ipv4s}" | awk -F'.' '{print $NF}')
|
||||
$(printf "${ipv6s}" | awk -F':' '{print $NF}')" \
|
||||
| sort | uniq | \
|
||||
awk -v RS='\\s+' '{ a[$1] } END { for(i = 1; i in a; ++i); print i }'
|
||||
|
||||
# Check if new peer already exists
|
||||
printf "${hostnames}" | grep "${hostname}" && \
|
||||
fail "Hostname ${hostname} already exists!"
|
||||
|
||||
# Create IP Addresses
|
||||
ipv4="${IPV4_NET%.*.*}.${usernumber}.${hostnumber}"
|
||||
ipv6="${IPV6_NET%:*:*}:${usernumber}:${hostnumber}"
|
||||
domain="${hostname}.${username}.${TLD}"
|
||||
|
||||
# Create wg config
|
||||
#TODO Check for /usr/bin/wg binary
|
||||
privkey="$(/usr/bin/wg genkey)"
|
||||
pubkey="$(echo $privkey | /usr/bin/wg pubkey)"
|
||||
address="${ipv4}/${IPV4_NET##*/},${ipv6}/${IPV6_NET##*/}"
|
||||
server_blocks=''
|
||||
while read server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_admin server_secret; do
|
||||
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
|
||||
then ../../lib/wg/user/add "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128"
|
||||
# Send new user config to federated server
|
||||
else ../../lib/fed/add "${server_admin}" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128" "${server_secret}"
|
||||
fi
|
||||
done <../../env/servers
|
||||
wg_config="[Interface] # ${hostname}.${username}.${TLD}\nPrivateKey=${privkey}\nAddress=${address}\n${WG_DNS}\n${server_blocks}"
|
||||
|
||||
# Respond to user
|
||||
printf "Status: 200 OK\nContent-Type: text/plain\n\n${wg_config}\n"
|
||||
|
||||
# Update nameserver
|
||||
../../lib/ns/update/add "${domain}" "${ipv4}" "${ipv6}"
|
||||
|
||||
# Create SSL cert
|
||||
sudo ../../lib/ssl/peer/add "${hostname}" "${username}" "IP:${ipv4},IP:${ipv6}"
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/api/dashboard/list
|
||||
# DESCRIPTION: List a user's peers, username, token from their IP
|
||||
# USAGE: list ip username
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
TOKENS_FILE='./tokens'
|
||||
source ../env/vars
|
||||
|
||||
# Get or set token
|
||||
token="$(grep ${1} ${TOKENS_FILE} | cut -f2)"
|
||||
if [ "${token}" == "" ]; then
|
||||
token="$(</dev/urandom tr -dc '[:alnum:]' | fold -w 64 | head -n 1)"
|
||||
printf "${1}\t${token}\n" >>"${TOKENS_FILE}"
|
||||
fi
|
||||
|
||||
# Get peers
|
||||
peers="[$(sudo ../../lib/wg/peer/list ${1} json)]"
|
||||
|
||||
# Send response
|
||||
printf "Content-Type: text/json\n\n{\"name\":\"${2}\",\"token\":\"${token}\",\"peers\":${peers}}\n"
|
|
@ -1,34 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/api/dashboard/serve
|
||||
# DESCRIPTION: Listen for user dashboard requests
|
||||
# USAGE: serve port
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
fail() {
|
||||
printf "Status: 500 Internal Server Error\nContent-Type: text/plain\n\n${1}\n"
|
||||
exit
|
||||
}
|
||||
TOKENS_FILE='tokens'
|
||||
source ../env/vars
|
||||
|
||||
## RUNTIME
|
||||
|
||||
# Get user
|
||||
username="$(../../lib/ns/lookup/user ${REMOTE_ADDR})"
|
||||
|
||||
case "${REQUEST_METHOD}" in
|
||||
|
||||
# List peers
|
||||
'GET') ./list "${REMOTE_ADDR}" "${username}";;
|
||||
|
||||
# Add peer
|
||||
'POST')
|
||||
[ "$CONTENT_LENGTH" -gt 0 ] && read -n $CONTENT_LENGTH POST_DATA <&0
|
||||
./add "${REMOTE_ADDR}" "${username}" "${QUERY_STRING}" "${POST_DATA}"
|
||||
;;
|
||||
|
||||
# Delete peer
|
||||
'DELETE') ./delete "${REMOTE_ADDR}" "${QUERY_STRING}";;
|
||||
|
||||
*) exit 1;;
|
||||
esac
|
|
@ -0,0 +1,15 @@
|
|||
version: '3'
|
||||
services:
|
||||
dashboard:
|
||||
build: srv/dashboard
|
||||
container_name: wgapi_dashboard
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
network_mode: host
|
||||
volumes:
|
||||
- './etc:/etc/wgapi:ro'
|
||||
- './lib:/usr/local/bin:ro'
|
||||
- './srv/dashboard/tokens:/var/local/wgapi_tokens'
|
||||
- './srv/dashboard:/var/www/cgi-bin:ro'
|
||||
# ports:
|
||||
# - '8080:80/tcp'
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
# FILE: /etc/wgapi/config
|
||||
# DESCRIPTION: Admin-editable configs
|
||||
|
||||
export TLD='gf4'
|
||||
export LOGFILE='/var/log/apache2/error.log'
|
||||
export LOCAL_SERVER='ksn'
|
||||
export IPV4_NET='10.4.0.0/16'
|
||||
export IPV6_NET='fd69:1337:0:420:f4:f4::/96'
|
||||
export WG_DNS='DNS=10.4.0.1,10.4.0.3,fd69:1337:0:420:f4:f4:0:1,fd69:1337:0:420:f4:f4:0:3'
|
||||
export LIB_DIR='/usr/local/bin'
|
||||
export TOKENS_FILE='/var/local/wgapi_tokens'
|
||||
export SERVERS_FILE='/etc/wgapi/servers'
|
||||
export SSL_CONFIG_DIR="/etc/ssl/private/${TLD}"
|
||||
export SSL_CA_CERT="${SSL_CONFIG_DIR}/_ca.crt"
|
||||
export SSL_CA_KEY="${SSL_CONFIG_DIR}/_ca.key"
|
||||
export SSL_ORG='My Org'
|
||||
export SSL_DAYS='3650'
|
||||
export SSL_CA_PASS='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
export DNS_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxw=='
|
||||
export DNS_MASTER='10.4.0.1'
|
||||
export DNS_TTL='86400'
|
|
@ -0,0 +1,3 @@
|
|||
# host ipv4 ipv6 pubkey wg-endpoint admin-endpoint secret
|
||||
ksn 10.4.0.1 fd69:1337:0:420:f4:f4:0:1 /LrbvvmXLk2ZmU94JZua+eliqySuJ4QMHApthjvhO3s= 172.93.54.60:52348 https://wgapi-admin.ksn.gf4 Mipto0ncZ2KFglNHshfKCrYxyLtAfakfkt4q9SoHxr1lW
|
||||
krow 10.4.0.3 fd69:1337:0:420:f4:f4:0:3 6VA79LOmlUaJSD1AiLEMCtnjMRZ7rwRrdbtNSCDtO2k= 85.17.214.157:56333 https://wgapi-admin.krow.gf4 x32JMJmET3ehGUJ1meGjqdkd9HBI3LhqxFMYzrVsw
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/http/res
|
||||
# DESCRIPTION: Formats an http response from arguments
|
||||
# USAGE: [printf "message" |] res [200] [text/plain]
|
||||
|
||||
# Parse status
|
||||
status=''
|
||||
case "${1}" in
|
||||
''|'0'|'200') status='Status: 200 OK\n';;
|
||||
'400') status='Status: 400 Bad Request\n';;
|
||||
'500') status='Status: 500 Internal Server Error\n';;
|
||||
*) exit 3;;
|
||||
esac
|
||||
|
||||
# Parse inputs
|
||||
body="$(cat)"
|
||||
content_type=''
|
||||
if [ "${2}" == '' ] && [ "${body}" == '' ]
|
||||
then content_type=''
|
||||
elif [ "${2}" == '' ]
|
||||
then content_type='Content-type: text/plain\n'
|
||||
else content_type="Content-type: ${2}\n"
|
||||
fi
|
||||
|
||||
# Send response
|
||||
printf "${status}${content_type}\n${body}\n"
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/lookup/host
|
||||
# DESCRIPTION: Get a hostname from an IP address
|
||||
# USAGE: host ip
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
./send "${1}" | cut -d'=' -f2 | cut -d'.' -f1 | xargs
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/lookup/send
|
||||
# DESCRIPTION: Send nslookup command to DNS master server
|
||||
# USAGE: send cmd
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
source ../../../env/vars
|
||||
# TODO: Check that nslookup is installed
|
||||
/usr/bin/nslookup "${1}" "${DNS_MASTER}"
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/lookup/user
|
||||
# DESCRIPTION: Get a username from an IP address
|
||||
# USAGE: user ip
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
./send "${1}" | cut -d'=' -f2 | cut -d'.' -f1 | xargs
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/update/add
|
||||
# DESCRIPTION: Add a new peer's domain to nameserver
|
||||
# USAGE: add domain ipv4 ipv6
|
||||
|
||||
source ../../../../env/vars
|
||||
# Keep these updates seperate because the zones are different
|
||||
./send "update add ${1}. ${DNS_TTL} A ${2}\nupdate add ${1}. ${DNS_TTL} AAAA ${3}\nupdate add *.${1}. ${DNS_TTL} CNAME ${1}."
|
||||
./send "update add $(./rev_ipv4 $2) ${DNS_TTL} PTR ${1}."
|
||||
./send "update add $(./rev_ipv6 $3) ${DNS_TTL} PTR ${1}."
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/lookup/rdns
|
||||
# DESCRIPTION: Get a domain from an IP address
|
||||
# USAGE: rdns ip
|
||||
# OUTPUT: The domain for that IP
|
||||
# ERRORS:
|
||||
# 3: bad usage
|
||||
# 4: not found
|
||||
# 5: server down
|
||||
# 6: nslookup not found
|
||||
# 7: config not found
|
||||
|
||||
# Accept exactly one argument
|
||||
[ ${#} -eq 1 ] || exit 3
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || exit 7
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
domain="$(${LIB_DIR}/ns_lookup_send ${1})"
|
||||
case $? in
|
||||
0) printf "${domain%.}" | cut -d'=' -f2 | xargs -0; exit 0;;
|
||||
4) printf "Address not found: ${1}\n" >>"${LOGFILE}"; exit 4;;
|
||||
5) printf "Nameserver not available: ${DNS_MASTER}\n" >>"${LOGFILE}"; exit 5;;
|
||||
6) printf 'nslookup not installed!\n' >>"${LOGFILE}"; exit 6;;
|
||||
*) printf "Bad usage: ${0} ${@}\n" >>"${LOGFILE}"; exit 3;;
|
||||
esac
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/lookup/send
|
||||
# DESCRIPTION: Send nslookup command to DNS master server
|
||||
# USAGE: send cmd
|
||||
# ERRORS:
|
||||
# 3: bad usage
|
||||
# 4: not found
|
||||
# 5: server down
|
||||
# 6: nslookup not found
|
||||
# 7: config file not found
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || exit 7
|
||||
[ "$#" == "1" ] || exit 3
|
||||
[ -x /usr/bin/nslookup ] || exit 6
|
||||
source "${CONFIG_FILE}"
|
||||
res="$(/usr/bin/nslookup ${1} ${DNS_MASTER})"
|
||||
#printf "${1} ${res}" >>"${LOGFILE}"
|
||||
if printf "${res}" | grep ';; connection timed out'
|
||||
then exit 5
|
||||
elif printf "${res}" | grep "** server can't find "
|
||||
then exit 4
|
||||
else
|
||||
printf "${res}"
|
||||
fi
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/ns/update/add
|
||||
# DESCRIPTION: Add a new peer's domain to nameserver
|
||||
# USAGE: add domain ipv4 ipv6
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: config file not found
|
||||
# 5: nsupdate failed
|
||||
|
||||
[ ${#} -eq 3 ] || exit 3
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || exit 4
|
||||
source "${CONFIG_FILE}"
|
||||
# Keep these updates seperate because the zones are different
|
||||
( ./send "update add ${1}. ${DNS_TTL} A ${2}\nupdate add ${1}. ${DNS_TTL} AAAA ${3}\nupdate add *.${1}. ${DNS_TTL} CNAME ${1}." \
|
||||
&& ./send "update add $(./rev_ipv4 $2) ${DNS_TTL} PTR ${1}." \
|
||||
&& ./send "update add $(./rev_ipv6 $3) ${DNS_TTL} PTR ${1}." ) || exit 5
|
|
@ -2,8 +2,14 @@
|
|||
# FILE: wgapi:back/lib/ns/update/del
|
||||
# DESCRIPTION: Use nsupdate to delete host RRs
|
||||
# USAGE: del domain ipv4 ipv6
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: Config not found
|
||||
|
||||
source ../../../../env/vars
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ ${#} -eq 3 ] || exit 3
|
||||
[ -f "${CONFIG_FILE}" ] || exit 5
|
||||
source "${CONFIG_FILE}"
|
||||
# Keep these updates seperate because the zones are different
|
||||
./send "update delete ${1}. A\nupdate delete ${1}. AAAA\n update delete *.${1}. CNAME"
|
||||
./send "update delete $(./rev_ipv4 $2) PTR"
|
|
@ -2,7 +2,12 @@
|
|||
# FILE: wgapi:back/lib/ns/update/send
|
||||
# DESCRIPTION: Send stuff to the nsupdate server
|
||||
# USAGE: send cmd
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: Missing config file
|
||||
|
||||
source ../../../env/vars
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || exit 4
|
||||
source "${CONFIG_FILE}"
|
||||
printf "server ${DNS_MASTER}\n${1}\nsend\n" \
|
||||
| nsupdate -y "${DNS_KEY}"
|
|
@ -2,37 +2,48 @@
|
|||
# FILE: wgapi:back/lib/ssl/peer/add
|
||||
# DESCRIPTION: Create SSL certs for a new host
|
||||
# USAGE: add hostname username ipstring
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: config file not found
|
||||
# 5: openssl or config not found
|
||||
# 6: not root
|
||||
# 7: openssl failed
|
||||
|
||||
[ "$#" == "" ] || exit
|
||||
source ../../../env/vars
|
||||
#TODO Check for root
|
||||
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ ${#} -eq 0 ] || exit 3
|
||||
(( ${EUID} == 0 )) || exit 6
|
||||
[ -f "${CONFIG_FILE}" ] || exit 4
|
||||
[ -x '/usr/bin/openssl' ] || exit 5
|
||||
[ -f '/etc/ssl/openssl.cnf' ] || exit 5
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
# Generate key
|
||||
openssl genrsa -out "${SSL_CONFIG_DIR}/${username}/${hostname}/server.key" >/dev/null 2>&1
|
||||
/usr/bin/openssl genrsa -out "${SSL_CONFIG_DIR}/${username}/${hostname}/server.key" >/dev/null 2>&1 || exit 7
|
||||
chmod 400 "${SSL_CONFIG_DIR}/${username}/${hostname}/server.key"
|
||||
|
||||
# Generate config
|
||||
#TODO Make sure /etc/ssl/openssl.cnf exists
|
||||
cat '/etc/ssl/openssl.cnf' \
|
||||
<(printf "\n[SAN]\nsubjectAltNames=DNS:${hostname}.${username}.${TLD},DNS:*.${hostname}.${username}.${TLD},${3}") \
|
||||
> "${SSL_CONFIG_DIR}/${username}/${hostname}.cnf"
|
||||
|
||||
# Generate CSR
|
||||
openssl req -new -sha256 -reqexts SAN \
|
||||
/usr/bin/openssl req -new -sha256 -reqexts SAN \
|
||||
-key "${SSL_CONFIG_DIR}/${username}/${hostname}/server.key" \
|
||||
-out "${SSL_CONFIG_DIR}/${username}/${hostname}.csr"
|
||||
-config "${SSL_CONFIG_DIR}/${username}/${hostname}.cnf" \
|
||||
-subj "/O=${SSL_ORG}/OU=${username}/CN=${hostname}.${username}.${TLD}" \
|
||||
>/dev/null 2>&1
|
||||
>/dev/null 2>&1 || exit 7
|
||||
|
||||
# Generate cert
|
||||
openssl x509 -req -sha256 -extensions SAN -CAcreateserial \
|
||||
/usr/bin/openssl x509 -req -sha256 -extensions SAN -CAcreateserial \
|
||||
-extfile "${SSL_CONFIG_DIR}/${username}/${hostname}.cnf" \
|
||||
-in "${SSL_CONFIG_DIR}/${username}/${hostname}.csr" \
|
||||
-CA "${SSL_CA_CERT}" -CAkey "${SSL_CA_KEY}" \
|
||||
-passin "pass:${SSL_CA_PASS}" \
|
||||
-out "${SSL_CONFIG_DIR}/${username}/${hostname}/server.crt"
|
||||
-days "${SSL_DAYS}" >/dev/null 2>&1
|
||||
-days "${SSL_DAYS}" >/dev/null 2>&1 || exit 7
|
||||
chmod 644 "${SSL_CONFIG_DIR}/${username}/${hostname}/server.crt"
|
||||
|
||||
# Remove old files
|
|
@ -2,8 +2,11 @@
|
|||
# FILE: wgapi:back/lib/ssl/peer/del
|
||||
# DESCRIPTION: Delete SSL cert for a removed device
|
||||
# USAGE: del hostname username
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: Not root
|
||||
|
||||
[ "$#" == "2" ] || exit
|
||||
#TODO Check for root
|
||||
[ "$#" == "2" ] || exit 3
|
||||
(( ${EUID} == 0 )) || exit 4
|
||||
rm -rf "${SSL_CONFIG_DIR}/${username}/${hostname}/" 2>/dev/null
|
||||
rm -rf "${SSL_CONFIG_DIR}/${username}/${hostname}.*" 2>/dev/null
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/wg/peer/add
|
||||
# DESCRIPTION: Add a new peer to a wireguard interface
|
||||
# USAGE: add pubkey psk allowedips
|
||||
|
||||
[ "$#" == "3" ] || exit
|
||||
source ../../../env/vars
|
||||
/usr/bin/wg set "${TLD}" peer "${1}" preshared-key <(printf "${2}") allowed-ips "${3}"
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/wg/peer/del
|
||||
# DESCRIPTION: Delete a peer from a wireguard interface
|
||||
# USAGE: del pubkey
|
||||
|
||||
[ "$#" == "3" ] || exit
|
||||
source ../../../env/vars
|
||||
/usr/bin/wg set "${TLD}" peer "${1}" remove
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/wg/peer/list
|
||||
# DESCRIPTION: Get peers in the same subnet as an ip
|
||||
# USAGE: list ip json|tsv
|
||||
|
||||
[ "$#" == "2" ] || exit
|
||||
source ../../../env/vars
|
||||
/usr/bin/wg show "${TLD}" allowed-ips | grep "${1[.:]*}" \
|
||||
| while read pubkey ipv4 ipv6; do
|
||||
ipv4="${ipv4%%/*}"
|
||||
ipv6="${ipv6%%/*}"
|
||||
hostname="$(../../ns/lookup/host ${ipv4})"
|
||||
if [ "${2}" == 'json' ]; then
|
||||
#TODO Remove keys with empty ("") values
|
||||
printf "{\"hostname\":\"${hostname}\",\"ipv4\":\"${ipv4}\",\"ipv6\":\"${ipv6}\",\"pubkey\":\"${pubkey}\"},"
|
||||
elif [ "${2}" == 'tsv' ]; then
|
||||
printf "${hostname}\t${ipv4}\t${ipv6}\t${pubkey}\n"
|
||||
fi
|
||||
done | sed 's/,$//' # Remove trailing comma from json
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/wg/peer/add
|
||||
# DESCRIPTION: Add a new peer to a wireguard interface
|
||||
# USAGE: add pubkey psk allowedips
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: wg binary not found
|
||||
# 5: vars not found
|
||||
# 6: wg command failed
|
||||
# 7: Not root
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ "$#" == "3" ] || exit 3
|
||||
[ -x /usr/bin/wg ] || exit 4
|
||||
(( ${EUID} == 0 )) || exit 7
|
||||
[ -f "${CONFIG_FILE}" ] || exit 5
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
/usr/bin/wg set "${TLD}" peer "${1}" preshared-key <(printf "${2}") allowed-ips "${3}" || exit 6
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/lib/wg/peer/del
|
||||
# DESCRIPTION: Delete a peer from a wireguard interface
|
||||
# USAGE: del pubkey
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: wg binary not found
|
||||
# 5: config not found
|
||||
# 6: wg command failed
|
||||
# 7: Not root
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ "$#" == "3" ] || exit 3
|
||||
[ -x /usr/bin/wg ] || exit 4
|
||||
(( ${EUID} == 0 )) || exit 7
|
||||
[ -f "${CONFIG_FILE}" ] || exit 5
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
/usr/bin/wg set "${TLD}" peer "${1}" remove || exit 6
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
# FILE: wg_peer_list
|
||||
# DESCRIPTION: Get peers in the same subnet as an ip
|
||||
# USAGE: list ip json|tsv
|
||||
# ERRORS:
|
||||
# 3: bad usage
|
||||
# 4: nslookup failed
|
||||
# 5: wg failed
|
||||
# 6: Config file not found
|
||||
# 7: wg not found
|
||||
# 8: wg found no peers
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || ( printf "ERROR! ${0} Config file not found" >&2; exit 6 )
|
||||
[ ${#} -eq 2 ] || ( printf "ERROR! Bad usage: $0 $@" >&2; exit 3 )
|
||||
[ -x /usr/bin/wg ] || ( printf "ERROR! ${0} /usr/bin/wg not found" >&2; exit 5 )
|
||||
|
||||
source "${CONFIG_FILE}"
|
||||
wg_output="$(/usr/bin/wg show ${TLD} allowed-ips)"
|
||||
[ ${?} -ne 0 ] && (
|
||||
printf "ERROR! Wireguard failed!\n" >>${LOGFILE}
|
||||
exit 5
|
||||
)
|
||||
user_peers="$(grep ${1%[.:]*} <<<${wg_output} 2>/dev/null)"
|
||||
[ "${user_peers}" == "" ] && (
|
||||
printf "ERROR! ${1} accessed the dashboard but isn't on the network!\n" >>${LOGFILE}
|
||||
exit 8
|
||||
)
|
||||
while IFS= read -r line; do # TODO: Do these dns lookups in parallel
|
||||
pubkey="$(<<<${line} cut -d ' ' -f1)"
|
||||
ips="$(<<<${line} cut -d ' ' -f2)"
|
||||
ipv4="$(<<<${ips} cut -d ' ' -f1)"
|
||||
ipv6="$(<<<${ips} cut -d ' ' -f2)"
|
||||
ipv4="${ipv4%%/*}"
|
||||
ipv6="${ipv6%%/*}"
|
||||
domain="$(${LIB_DIR}/ns_lookup_rdns ${ipv4} | xargs)"
|
||||
[ ${?} -ne 0 ] && exit 4 # Check if nslookup failed
|
||||
case "${2}" in
|
||||
'json') printf "{\"domain\":\"${domain}\",\"ipv4\":\"${ipv4}\",\"ipv6\":\"${ipv6}\",\"pubkey\":\"${pubkey}\"},";;
|
||||
'tsv') printf "${domain}\t${ipv4}\t${ipv6}\t${pubkey}\n";;
|
||||
esac
|
||||
done <<<"${user_peers}" | sed 's/\n//g' | sed 's/,$//' # Remove trailing comma and newline
|
|
@ -2,18 +2,28 @@
|
|||
# FILE: wgapi:back/lib/wg/user/list
|
||||
# DESCRIPTION: List all devices from all users
|
||||
# USAGE: list json|tsv
|
||||
# ERRORS:
|
||||
# 3: bad usage
|
||||
# 4: nslookup failed
|
||||
# 5: Config not found
|
||||
# 6: wg failed
|
||||
|
||||
[ "$#" == "1" ] || exit
|
||||
source ../../../env/vars
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ ${#} -eq 1 ] || exit 3
|
||||
[ -f "${CONFIG_FILE}" ] || exit 5
|
||||
source "${CONFIG_FILE}"
|
||||
#/usr/bin/wg show ${TLD} allowed-ips
|
||||
|
||||
/usr/bin/wg show "${TLD}" allowed-ips \
|
||||
| while read pubkey ipv4 ipv6; do
|
||||
ipv4="${ipv4%%/*}"
|
||||
ipv6="${ipv6%%/*}"
|
||||
#TODO Combine these next two into one nslookup
|
||||
username="$(../../ns/lookup/user ${ipv4})"
|
||||
hostname="$(../../ns/lookup/host ${ipv4})"
|
||||
domain="$(../../ns/lookup/rdns ${ipv4})"
|
||||
if [ ${?} -ne 0 ]
|
||||
then exit 4
|
||||
fi
|
||||
username="$(printf ${domain} | cut -d'.' -f2)"
|
||||
hostname="$(printf ${domain} | cut -d'.' -f1)"
|
||||
if [ "${2}" == 'json' ]; then
|
||||
#TODO Remove keys with empty ("") values
|
||||
printf "{\"hostname\":\"${hostname}.${username}.${TLD}\",\"ipv4\":\"${ipv4}\",\"ipv6\":\"${ipv6}\",\"pubkey\":\"${pubkey}\"},"
|
|
@ -1,26 +0,0 @@
|
|||
server {
|
||||
server_name localhost;
|
||||
listen 8080;
|
||||
gzip off;
|
||||
autoindex on;
|
||||
location / {
|
||||
fastcgi_pass unix:/var/run/fcgiwrap.socket;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /etc/nginx/fastcgi.conf;
|
||||
root /home/ki9/src/wgapi/srv;
|
||||
fastcgi_index client;
|
||||
}
|
||||
}
|
||||
server {
|
||||
server_name localhost;
|
||||
listen 8081;
|
||||
gzip off;
|
||||
autoindex on;
|
||||
location / {
|
||||
fastcgi_pass unix:/var/run/fcgiwrap.socket;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /etc/nginx/fastcgi.conf;
|
||||
root /home/ki9/src/wgapi/srv;
|
||||
fastcgi_index fed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
FROM debian:latest
|
||||
RUN apt-get update && apt-get upgrade --yes
|
||||
RUN apt-get install --yes sudo apache2 openssl wireguard-tools dnsutils
|
||||
COPY apache2.conf /etc/apache2/sites-available/000-default.conf
|
||||
RUN a2enmod cgi rewrite
|
||||
RUN echo "www-data ALL=(ALL:ALL) NOPASSWD: ALL" | sudo EDITOR='tee -a' visudo
|
||||
EXPOSE 80
|
||||
CMD ["apachectl", "-D", "FOREGROUND"]
|
|
@ -0,0 +1,100 @@
|
|||
#!/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
|
||||
# 11: Failed to create new IPs
|
||||
# 12: Servers file doesn't exist
|
||||
# 15: Failed to add user to local wireguard
|
||||
# 16: Failed to add user to federated server
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
SERVERS_FILE='/etc/wgapi/servers'
|
||||
[ ${#} -eq 2 ] || exit 3
|
||||
[ -f "${CONFIG_FILE}" ] || exit 4
|
||||
[ -f "${TOKENS_FILE}" ] || exit 9
|
||||
[ -f "${SERVERS_FILE}" ] || exit 12
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
# Check hostname
|
||||
hostname="$(printf ${2}\n | jq -r '.name' | xargs | tr -dc '[a-z0-9]' | head -c10)"
|
||||
[[ ${#hostname} -ge 3 ]] || (
|
||||
printf 'Hostname too short\n' | res 400
|
||||
exit 7
|
||||
)
|
||||
|
||||
username="$(${LIB_DIR}/ns_lookup_rdns ${REMOTE_ADDR} | cut -d'.' -f2)"
|
||||
[ $? -ne 0 ] && (
|
||||
printf 'User not found' | "${LIB)DIR}/http_res" 403
|
||||
exit 403
|
||||
) ||
|
||||
|
||||
# Check token
|
||||
token_fail(){ printf 'Invalid token\n' | res 403; exit 8; }
|
||||
saved_token=$(grep "${1}" "${TOKENS_FILE}" | cut -f2)
|
||||
[ "${saved_token}" == "" ] && token_fail
|
||||
printf "${username}" | grep "t=${saved_token}" || token_fail
|
||||
|
||||
# Check if new peer already exists
|
||||
printf "${hostnames}" | grep "${hostname}" && (
|
||||
printf "Hostname ${hostname} already exists!\n" | res 40
|
||||
exit 6
|
||||
)
|
||||
|
||||
# Collect/parse existing peer data
|
||||
# Create new IPs and domain
|
||||
peers="$(sudo ${LIB_DIR}/wg_peer_list ${1} tsv)"
|
||||
[ ${?} -ne 0 ] && exit 10
|
||||
hostnames="$(printf "${peers}" | awk '{print $0}' | cut -d'.' -f1)"
|
||||
ipv4s="$(printf "${peers}" | awk '{print $1}')"
|
||||
ipv6s="$(printf "${peers}" | awk '{print $2}')"
|
||||
usernumber="$(printf ${ipv4s} head -n1 | cut -d'.' -f3)"
|
||||
used_ips="$(printf ${ipv4s} | cut -d'.' -f3)\n$(printf ${ipv6s} | cut -d'.' -f3)"
|
||||
used_hostnumbers="$(printf ${used_ipvs} | sort | uniq)"
|
||||
hostnumber=1
|
||||
while printf "${used_hostnumbers}" | grep "${hostnumber}"
|
||||
do hostnumber++
|
||||
done
|
||||
ipv4="${IPV4_NET%.*.*}.${usernumber}.${hostnumber}"
|
||||
ipv6="${IPV6_NET%:*:*}:${usernumber}:${hostnumber}"
|
||||
domain="${hostname}.${username}.${TLD}"
|
||||
# TODO: Check it or exit 11
|
||||
|
||||
# Create wg config
|
||||
#TODO Check for /usr/bin/wg binary
|
||||
privkey="$(/usr/bin/wg genkey)"
|
||||
pubkey="$(echo $privkey | /usr/bin/wg pubkey)"
|
||||
address="${ipv4}/${IPV4_NET##*/},${ipv6}/${IPV6_NET##*/}"
|
||||
server_blocks=''
|
||||
while read server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_admin server_secret; do
|
||||
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
|
||||
then "${LIB_DIR}/wg_peer_add" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128"
|
||||
[ ${?} -ne 0 ] && printf 'Failed to add new peer ${ipv4} to local server!' >&2 # TODO: clear existing progress and exit 15
|
||||
# Send new user config to federated server
|
||||
else "${LIB_DIR}/fed_add" "${server_admin}" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128" "${server_secret}"
|
||||
[ ${?} -ne 0 ] && printf 'Failed to add new peer ${ipv4} to federated server ${server_hostname}!' >&2 # TODO: clear existing progress and exit 16
|
||||
fi
|
||||
done <${SERVERS_FILE}
|
||||
wg_config="[Interface] # ${hostname}.${username}.${TLD}\nPrivateKey=${privkey}\nAddress=${address}\n${WG_DNS}\n${server_blocks}"
|
||||
|
||||
# Respond to user
|
||||
printf "${wg_config}" | "${LIB_DIR}/http_res"
|
||||
|
||||
# Update nameserver
|
||||
"${LIB_DIR}/ns_update_add" "${domain}" "${ipv4}" "${ipv6}"
|
||||
[ ${?} -ne 0 ] && printf "Failed to add ${domain} ${ipv4} ${ipv6} to DNS server!" >&2
|
||||
|
||||
# Create SSL cert
|
||||
sudo "${LIB_DIR}/ssl_peer_add" "${hostname}" "${username}" "IP:${ipv4},IP:${ipv6}"
|
||||
[ ${?} -ne 0 ] && printf "Failed to add ${domain} ${ipv4} ${ipv6} to DNS server!" >&2
|
|
@ -0,0 +1,15 @@
|
|||
<VirtualHost *:80>
|
||||
ServerName localhost
|
||||
#ServerAdmin webmaster@localhost
|
||||
DocumentRoot /var/www/cgi-bin
|
||||
LogLevel info
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
ScriptAlias "/" "/var/www/cgi-bin/"
|
||||
<Directory /var/www/cgi-bin/>
|
||||
AllowOverride None
|
||||
#Options +ExecCGI
|
||||
#SetHandler cgi-script
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
|
@ -8,8 +8,8 @@ fail() {
|
|||
exit
|
||||
}
|
||||
[ "$#" == "2" ] || fail
|
||||
source ../../env/vars
|
||||
TOKENS_FILE='./tokens'
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
# Check token
|
||||
saved_token=$(grep "${1}" "${TOKENS_FILE}" | cut -f2)
|
||||
|
@ -24,13 +24,13 @@ printf "Status: 202 Accepted\nContent-Type: text/plain\n\nDeleted\n"
|
|||
|
||||
while read server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_admin server_secret; do
|
||||
if [ "${server_hostname}" == "${LOCAL_SERVER}" ]
|
||||
then ../../lib/wg/user/del "${pubkey}"
|
||||
else ../../lib/fed/del "${server_admin}" "${pubkey}" "${server_secret}"
|
||||
then "${LIB_DIR}/wg_user_del" "${pubkey}"
|
||||
else "${LIB_DIR}/fed_del" "${server_admin}" "${pubkey}" "${server_secret}"
|
||||
fi
|
||||
done <../../env/servers
|
||||
done <${SERVERS_FILE}
|
||||
|
||||
# Update nameserver
|
||||
../../lib/ns/update/del "${domain}" "${ipv4}" "${ipv6}"
|
||||
"${LIB_DIR}/ns_update_del" "${domain}" "${ipv4}" "${ipv6}"
|
||||
|
||||
# Delete SSL certs
|
||||
sudo ../../lib/ssl/peer/del "${hostname}" "${username}"
|
||||
sudo "${LIB_DIR}/ssl_peer_del" "${hostname}" "${username}"
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
# FILE: wgapi:back/api/dashboard/index.cgi
|
||||
# DESCRIPTION: Recieves incoming dashboard API requests
|
||||
# USAGE: serve
|
||||
# ERRORS:
|
||||
# 3: Bad usage
|
||||
# 4: Missing vars vile
|
||||
|
||||
CONFIG_FILE='/etc/wgapi/config'
|
||||
[ -f "${CONFIG_FILE}" ] || exit 4
|
||||
source "${CONFIG_FILE}"
|
||||
|
||||
case "${REQUEST_METHOD}" in
|
||||
|
||||
# List peers
|
||||
'GET')
|
||||
token="$(grep ${REMOTE_ADDR} ${TOKENS_FILE} | cut -f2)"
|
||||
if [ "${token}" == "" ]; then
|
||||
token="$(</dev/urandom tr -dc '[:alnum:]' | fold -w 64 | head -n 1)"
|
||||
printf "${REMOTE_ADDR}\t${token}\n" >>"${TOKENS_FILE}"
|
||||
fi
|
||||
peers="[$(sudo ${LIB_DIR}/wg_peer_list ${REMOTE_ADDR} json)]"
|
||||
case ${?} in
|
||||
0) printf "${peers}" | "${LIB_DIR}/http_res" 200 'application/json';;
|
||||
*) printf 'Failed to lookup user' | "${LIB_DIR}/http_res" 500;;
|
||||
esac
|
||||
;;
|
||||
|
||||
# Add peer
|
||||
'POST') ./add "${REMOTE_ADDR}" "${username}" "${QUERY_STRING}" "${POST_DATA}";;
|
||||
|
||||
# Delete peer
|
||||
'DELETE') ./delete "${REMOTE_ADDR}" "${QUERY_STRING}";;
|
||||
|
||||
# Bad request
|
||||
*) printf 'Invalid HTTP verb' | "${LIB_DIR}/http_res" 400;;
|
||||
|
||||
esac && exit 0
|
|
@ -0,0 +1,23 @@
|
|||
172.27.0.1 xxaErrLvw1iSKmI2bIvAUbZwg9qEzWgz1gUsySon59KHCkhQ3CYjPY0jm4CjNVWC
|
||||
172.28.0.1 oIAPZJzFzYV9SVXJnxrE0orLfu1PH388OOXT1tSN8AqGUQKZIDBT2bNy3gPzgfwl
|
||||
172.29.0.1 t5jLNjw4KF1iYQGZfTOgydhWIM6rXWrSqqFvF5hRTOhQ0X7EWeQO2a9hzpHGP5yq
|
||||
172.31.0.1 ZvVtj9YuoB8lNYByZZcjwZMBNkhTKqZw5A7udSgS445fyR0T0L1SDDNQM3fMKFCE
|
||||
192.168.16.1 JjZBNHWQ0WR93yX997rPBCZrofxPffbZvxnNYp0ckwX1m3okiaf3PHVNhHnCBTNu
|
||||
192.168.32.1 ukFhLudFQ0afzbycnJRumyegl9wJzoVFZGkO7gy5imsgPUA3nJQ49CHD2fHcFDCP
|
||||
192.168.48.1 ZFeZLxVxZA51FtS28hk7ZGfSEA860EjYWz1ekyHXjMPeTrZyZBfR0QspxTBWaUdQ
|
||||
192.168.64.1 xcL8TzG8JfqAwcE40FbPefYvxElAvRevpLjrsMuRyqxT2dyKUNm4fdvXRHMixtF2
|
||||
192.168.80.1 NK0msKu08pzQ1v6emm6XoU80oNLjCc87fGtZky483KvX7n7V68omWA2p3yd4CFXV
|
||||
192.168.96.1 QEOihdwGeCyQy9xrXdXRmBhcgkEs2f7lj7L9uR4REr1ASZAQaMA0eP4I5LdwQfBR
|
||||
192.168.128.1 iQhMunQyzDYcEZSg5A2Hu8fkcG0w9dzZeL5YQBwxxuuKw3ZtnNkLomXXQvTPe1r0
|
||||
192.168.144.1 QupcdsyxDruhoQbTZsmQ0iUzH5WAjecqCnKZQCmZhEd7qtQm958mkPi12WYOQXXT
|
||||
192.168.160.1 Jc5ScdryW9fZFIyxjO4eWm1Xyh5LnUB32mSliIbGiWqW8rhQcUJpDZjMSl94ch6A
|
||||
192.168.176.1 hikGzZrtocvVFO3gbAU0vyjXnaAzOu8vvAUuZ68pWMJY8LtZLwyTnbCfVZQU4W3K
|
||||
192.168.192.1 OyXJ6yq3GJiZsumY9wqq5XSfaC7F8oZ3A18PcjYr1AOzHOuxGdYwVpzAOwIXv0iB
|
||||
192.168.208.1 JUaD2QPNTrLlrRANS0TeC57pf3c5KTV4hlDJHfrbEpYx2OtmII4rWYkebAIGcz2S
|
||||
192.168.224.1 qRItfROyQPaZXLo6FnDN6A0cI6umDpW53se0wiqsuCtyUkhs8DncJd5Yroj8coAg
|
||||
192.168.240.1 LqwVxAabepe3brXKwLvjNdNAz6yafipzEQ0p8gXdZBzXQlf4Rxjxbl9XHjY0fTev
|
||||
172.19.0.1 2jMFQMMtSrAnT8pVxcYbL7jumL4kgFXFeGNDdvy7dtQwyPBi5GMlm12UjtIHKx9Y
|
||||
172.20.0.1 QIIK8Sl6S8cE2H9xKpvwBkXZNfd2UKVJU0hnKAeEJXdxEkUHtKEGv7PQ1DbDqv0i
|
||||
10.4.1.2 OYTgelpqTuHuhw9WVTXyddvqSHInQGa7zIA73JD10mKDW2eerSIQHmyjgHigXdCt
|
||||
127.0.0.1 jr8a6xGb2e9c8uQUH8sWBnumg8yySGFDttOkDIKMyJ46PAuhZIJHZ4njly3pHj6P
|
||||
10.4.1.10 sJmL4hnD8FvmaBI4szGDY6Y8VMYCZsNo0jHoXg8R2xesQle1ElU7WgqTxLQsXLvn
|
Loading…
Reference in New Issue