Added better logging

master
Keith Irwin 2021-12-11 09:37:32 -07:00
parent 7f25fe3abb
commit 80e1bc75b3
Signed by: ki9
GPG Key ID: DF773B3F4A88DA86
3 changed files with 50 additions and 41 deletions

View File

@ -19,7 +19,6 @@ let axios; (async()=>{
} catch (err) { console.error(err) } } catch (err) { console.error(err) }
})() })()
const dns_key = `hmac-sha512:wgapi-${env.LOCAL_SERVER}:${env.DNS_KEY}` const dns_key = `hmac-sha512:wgapi-${env.LOCAL_SERVER}:${env.DNS_KEY}`
let config_queue = []
module.exports = async (req, res) => { module.exports = async (req, res) => {
@ -41,7 +40,7 @@ module.exports = async (req, res) => {
console.error(`Failed to get user from ${req.requester}`) console.error(`Failed to get user from ${req.requester}`)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(403).send('User not found!') .status(403).send('User not found!')
} console.log(`${req.requester} must be ${user.name}`) } console.log(`${req.requester} identified as ${user.name}`)
// Check token // Check token
if (req.query['token']!==helper.getToken(req.requester)) { if (req.query['token']!==helper.getToken(req.requester)) {
@ -59,8 +58,8 @@ module.exports = async (req, res) => {
.status(409).send(`You already have a peer named ${new_hostname}`) .status(409).send(`You already have a peer named ${new_hostname}`)
} }
// Create IP Addresses and keys
// Find next available host part console.log(`Generating new IP addresses and keys...`)
const used_ipv4_hosts = user.peers const used_ipv4_hosts = user.peers
.map((host) => host.ipv4).map((found_ipv4) => .map((host) => host.ipv4).map((found_ipv4) =>
found_ipv4.toString().split('.')[3]) found_ipv4.toString().split('.')[3])
@ -70,22 +69,22 @@ module.exports = async (req, res) => {
let host = 1 let host = 1
while ([...used_ipv4_hosts,...used_ipv6_hosts].includes(host.toString())) host++ while ([...used_ipv4_hosts,...used_ipv6_hosts].includes(host.toString())) host++
if (host>9999) { if (host>9999) {
console.error(`New host part for ${user.name} is higher than 9999: ${host}`) console.error(`ERROR! New host part for ${user.name} is higher than 9999: ${host}`)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(507).send('No more numeric IPv6 addresses available. Try deleting an old peer first. ') .status(507).send('No more numeric IPv6 addresses available. Try deleting an old peer first. ')
} }
// Create IP Addresses and keys
let ipv4_addr; if (host<254) let ipv4_addr; if (host<254)
ipv4_addr = `${env.IPV4_NET}.${user.subnet}.${host}` ipv4_addr = `${env.IPV4_NET}.${user.subnet}.${host}`
const ipv6_addr = `${env.IPV6_NET}:${user.subnet}:${host}` const ipv6_addr = `${env.IPV6_NET}:${user.subnet}:${host}`
let keypair; try { let keypair; try {
keypair = await wg.generateKeypair() keypair = await wg.generateKeypair()
} catch (err) { } catch (err) {
console.error(`Unable to generateKeypair:\n${err}`) console.error(`ERROR! Unable to generateKeypair.`)
if (err) console.error(err)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(500).send('Server failed to generate a keypair. Something is broken so your peer was not created.') .status(500).send('Server failed to generate a keypair. Something is broken so your peer was not created.')
} }
console.log(`Generated IP addresses and keys.`)
// Peer with each server // Peer with each server
let client_peers = [] let client_peers = []
@ -122,28 +121,33 @@ AllowedIPs = ${allowed_ips}
// Add server_config to local wg0.conf // Add server_config to local wg0.conf
if (server.host===env.LOCAL_SERVER) { if (server.host===env.LOCAL_SERVER) {
console.log(`Adding config to local wg.conf at ${env.WG_CONFIG_FILE}...`)
try { await fs.appendFile(env.WG_CONFIG_FILE, server_config) } try { await fs.appendFile(env.WG_CONFIG_FILE, server_config) }
catch (err) { return console.error(err) } catch (err) {
console.error(`ERROR! Failed to write to config file!`)
if (err) console.error(err)
}
console.log(`Added new peer to local wg.conf file.`)
// Remote server: send config // Remote server: send config
} else { } else {
console.log(`Sending config to ${server.host}.gf4`) console.log(`Sending config to ${server.host}.${env.TLD}...`)
try { try {
await axios.post(`${server.admin_endpoint}/add?secret=${server.secret}`, server_config, { await axios.post(`${server.admin_endpoint}/add?secret=${server.secret}`, server_config, {
headers: {'Content-Type': 'text/plain'}, headers: {'Content-Type': 'text/plain'},
}) })
} catch (err) { } catch (err) {
if (err.message==='Request failed with status code 403') console.error(`ERROR! Failed to add peer to ${server.host}:\n${server_config} but the peer was created locally.`)
console.error(`Received 403 from ${server.admin_endpoint}/add`)
console.error(`Failed to add peer to ${server.host}:\n${server_config}
But the peer was created locally.`)
if (err) console.error(err.message) if (err) console.error(err.message)
} }
console.log(`Config sent to ${server.host}.${env.TLD}.`)
} }
} }
// Update nameserver // Update nameserver
if (env.ENV==='prod') { if (env.ENV!=='prod') console.log(`Skipping nameserver updates because env.ENV != 'prod'`)
else {
console.log(`Sending nsupdate to ${env.DNS_MASTER}...`)
try { try {
await helper.nsUpdate(dns_key, env.DNS_MASTER, await helper.nsUpdate(dns_key, env.DNS_MASTER,
`update add ${domain}. ${env.DNS_TTL} A ${ipv4_addr} `update add ${domain}. ${env.DNS_TTL} A ${ipv4_addr}
@ -151,25 +155,23 @@ update add ${domain}. ${env.DNS_TTL} AAAA ${ipv6_addr}
update add *.${domain}. ${env.DNS_TTL} CNAME ${domain}.`) update add *.${domain}. ${env.DNS_TTL} CNAME ${domain}.`)
} }
catch (err) { catch (err) {
console.error(`Failed to add ns record.`) console.error(`ERROR! Failed to add ns record.`)
if (err) console.error(err) if (err) console.error(err)
} }
console.log(`Updated nameserver to add ${domain}.`) console.log(`Added ${domain} to nameserver.`)
} }
// Generate user config // Generate user config and send it back to the user
console.log(`Sending config back to user...`)
const config_address = ipv4_addr const config_address = ipv4_addr
? `${ipv4_addr}/${env.IPV4_CIDR}, ${ipv6_addr}/${env.IPV6_CIDR}` ? `${ipv4_addr}/${env.IPV4_CIDR}, ${ipv6_addr}/${env.IPV6_CIDR}`
: `${ipv6_addr}/${env.IPV6_CIDR}` : `${ipv6_addr}/${env.IPV6_CIDR}`
const config = `[Interface] # ${domain} return res.setHeader('content-type', 'text/plain')
.status(201).send(`[Interface] # ${domain}
PrivateKey = ${keypair[1]} PrivateKey = ${keypair[1]}
Address = ${config_address} Address = ${config_address}
DNS = ${res.locals.DNS_SERVERS_STRING} DNS = ${res.locals.DNS_SERVERS_STRING}
PostUp = resolvectl domain ${env.TLD} ${env.TLD} PostUp = resolvectl domain ${env.TLD} ${env.TLD}
${client_peers.join('\n')}` ${client_peers.join('\n')}`)
// Send config to user
return res.setHeader('content-type', 'text/plain')
.status(201).send(config)
} }

View File

@ -35,7 +35,7 @@ module.exports = async (req, res) => {
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(404).send(`User for ${req.requester} not found`) .status(404).send(`User for ${req.requester} not found`)
} }
console.log(`${req.requester} must be ${user.name}`) console.log(`${req.requester} identified as ${user.name}`)
// Check token // Check token
if (req.query['token']!==helper.getToken(req.requester)) { if (req.query['token']!==helper.getToken(req.requester)) {
@ -57,6 +57,7 @@ module.exports = async (req, res) => {
// Search for peer // Search for peer
let peer_pubkey let peer_pubkey
const config = config_file.toString() const config = config_file.toString()
console.log(`Checking ${env.WG_CONFIG_FILE} for peer to be deleted...`)
const peer = config.split('\n\n') const peer = config.split('\n\n')
.filter( (paragraph) => { .filter( (paragraph) => {
return paragraph.includes('[Peer]') return paragraph.includes('[Peer]')
@ -81,15 +82,15 @@ module.exports = async (req, res) => {
return peer.includes(`PublicKey = ${pubkey}`) return peer.includes(`PublicKey = ${pubkey}`)
}) })
.catch((err) => { .catch((err) => {
console.error(`Failed to generate public key from private key during delete request`) console.error(`ERROR! Failed to generate public key from private key during delete request`)
if (err) console.error(err) if (err) console.error(err)
return res.setHeader('content-type', 'text/plain') res.setHeader('content-type', 'text/plain')
.status(500).send('Server error. Something is broken!') .status(500).send('Failed to generate public key to delete host. Something is broken!')
}) })
} else { } else {
console.error(`${req.requester} sent delete request without specifying a peer`) console.error(`ERROR! ${req.requester} sent delete request without specifying a peer`)
res.setHeader('content-type', 'text/plain') res.setHeader('content-type', 'text/plain')
.status(400).send('Peer not specified.') .status(400).send('Peer not specified!')
} }
})[0] })[0]
if (peer===undefined) { if (peer===undefined) {
@ -101,6 +102,7 @@ module.exports = async (req, res) => {
// Parse peer // Parse peer
const peer_lines = peer.split('\n') const peer_lines = peer.split('\n')
const peer_name = peer_lines const peer_name = peer_lines
console.log(`Found peer: ${peer_name}.`)
.filter( (line) => line.includes('[Peer] # ') )[0] .filter( (line) => line.includes('[Peer] # ') )[0]
.split(' # ')[1] .split(' # ')[1]
const peer_ips = peer_lines const peer_ips = peer_lines
@ -120,37 +122,41 @@ module.exports = async (req, res) => {
} }
// Delete from local wg config // Delete from local wg config
console.log(`Deleting ${peer_name}`); try { console.log(`Deleting ${peer_name} from ${env.WG_CONFIG_FILE}...`); try {
await fs.writeFile(env.WG_CONFIG_FILE, await fs.writeFile(env.WG_CONFIG_FILE,
config.replace(`\n${peer}`,'') config.replace(`\n${peer}`,'')
.replace('\n\n\n','\n\n') .replace('\n\n\n','\n\n')
) )
} catch (err) { } catch (err) {
console.error(`Failed to delete ${peer_name}`) console.error(`ERROR! Failed to delete ${peer_name}`)
if (err) console.error(err) if (err) console.error(err)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(500).send('Failed to delete! Try again?') .status(500).send('Failed to delete! Try again?')
} }
console.log(`${peer_name} deleted. `)
// Inform other servers // Inform other servers
for (const server of env.SERVERS) { for (const server of env.SERVERS) {
if (server.host!==env.LOCAL_SERVER) { if (server.host!==env.LOCAL_SERVER) {
try { try {
console.log(`Informing ${server.host} to delete ${peer_name}`) console.log(`Informing ${server.host} to delete ${peer_name}...`)
await axios.post(`${server.admin_endpoint}/del?secret=${server.secret}`, peer_pubkey, { await axios.post(`${server.admin_endpoint}/del?secret=${server.secret}`, peer_pubkey, {
headers: {'Content-Type': 'text/plain'}, headers: {'Content-Type': 'text/plain'},
}) })
} catch (err) { } catch (err) {
console.error(`ERROR! Failed to inform ${server.host} to delete ${peer_name}!`)
if (err) console.error(err) if (err) console.error(err)
console.error(`Failed to inform ${server.host} to delete ${peer_name}!`)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(500).send('Peer was added but did not propogate to the other server') .status(500).send('Peer was added but did not propogate to the other server')
} }
console.log(`Informed ${server.host} to delete ${peer_name}.`)
} }
} }
// Delete domains from nameserver // Delete domains from nameserver
if (env.ENV==='prod') { if (env.ENV!=='prod') console.log(`Skipping nameserver updates because env.ENV != 'prod'`)
else {
console.log(`Sending nsupdate to ${env.DNS_MASTER}...`)
try { try {
await helper.nsUpdate(dns_key, env.DNS_MASTER, await helper.nsUpdate(dns_key, env.DNS_MASTER,
`update delete ${peer_name}. A `update delete ${peer_name}. A
@ -158,7 +164,7 @@ update delete ${peer_name}. AAAA
update delete *.${peer_name}. CNAME`) update delete *.${peer_name}. CNAME`)
} }
catch (err) { catch (err) {
console.error(`Failed to delete ns record`) console.error(`ERROR! Failed to delete ns record`)
if (err) console.error(err) if (err) console.error(err)
return res.setHeader('content-type', 'text/plain') return res.setHeader('content-type', 'text/plain')
.status(500).send('Peer was added to all servers, but nameservers were not updated. You can use your peer but need to set its domain name by hand.') .status(500).send('Peer was added to all servers, but nameservers were not updated. You can use your peer but need to set its domain name by hand.')
@ -167,5 +173,4 @@ update delete *.${peer_name}. CNAME`)
} }
return res.sendStatus(200) return res.sendStatus(200)
} }

View File

@ -102,19 +102,21 @@ module.exports = {
// Handle exit // Handle exit
nsupdate.on('error', (err) => { nsupdate.on('error', (err) => {
console.error(`nsupdate threw an error`) console.error(`ERROR! nsupdate threw an error.`)
if (err) console.error(err) if (err) console.error(err)
reject(err) reject(err)
}) })
nsupdate.on('exit', (status) => { nsupdate.on('exit', (status) => {
console.log(`nsupdate exited with status: ${status}`) if (status!==0) {
if (status!==0) reject(errors) console.error(`ERROR! nsupdate threw a nonzero exit code.`)
reject(errors)
}
else resolve() else resolve()
}) })
// Something went wrong with the spawn? // Something went wrong with the spawn?
} catch (err) { } catch (err) {
console.error('nsupdate failed to spawn or something') console.error('ERROR! nsupdate failed to spawn or something.')
if (err) console.error(err) if (err) console.error(err)
reject(err) reject(err)
} }