Code cleanup

master
wgapi Cloud9 2021-10-21 22:21:59 -06:00
parent 0a6c042b11
commit 37fa81eda4
6 changed files with 194 additions and 170 deletions

View File

@ -12,16 +12,23 @@ const local_secret = env.SERVERS.filter(
)[0].secret )[0].secret
module.exports = async (req, res) => { module.exports = async (req, res) => {
// Check secret auth
if (req.query['secret']!==local_secret) { if (req.query['secret']!==local_secret) {
console.log(`Peer sent from ${req.requester} without correct secret querystring!`) console.log(`Peer sent from ${req.requester} without correct secret querystring!`)
return res.sendStatus(403) return res.sendStatus(403)
} else try { }
// Add request body to wg config
try {
await fs.appendFile(env.WG_CONFIG_FILE, req.body) await fs.appendFile(env.WG_CONFIG_FILE, req.body)
} catch (err) { } catch (err) {
console.error(`Failed to save new peer config from ${req.requester} to ${env.WG_CONFIG_FILE}`,err) console.error(`Failed to save new peer config from ${req.requester} to ${env.WG_CONFIG_FILE}`,err)
return res.sendStatus(500) return res.sendStatus(500)
} finally {
console.log(`Saved new peer from ${req.requester}`)
return res.sendStatus(200)
} }
console.log(`Saved new peer from ${req.requester}`)
// Respond
return res.sendStatus(200)
} }

View File

@ -19,41 +19,38 @@ module.exports = async (req, res) => {
if (req.query['secret']!==local_secret) { if (req.query['secret']!==local_secret) {
console.log(`Peer sent from ${req.requester} without correct secret querystring!`) console.log(`Peer sent from ${req.requester} without correct secret querystring!`)
return res.sendStatus(403) return res.sendStatus(403)
}
// Read config file // Read config file
} else try { else try {
const config_file = await fs.readFile(env.WG_CONFIG_FILE) const config_file = await fs.readFile(env.WG_CONFIG_FILE)
config = config_file.toString() config = config_file.toString()
} catch (err) { }
catch (err) {
console.error(`Failed to load config from ${env.WG_CONFIG_FILE}:\n`,err) console.error(`Failed to load config from ${env.WG_CONFIG_FILE}:\n`,err)
res.sendStatus(500) res.sendStatus(500)
} finally {
// Find peer in config
const peer = config.split('\n\n')
.filter( (paragraph) => {
return paragraph.includes('[Peer]')
}).filter( (peer) => {
return peer.includes(`PublicKey = ${req.body}`)
})
// Delete peer
try {
await fs.writeFile(env.WG_CONFIG_FILE,
config.replace(`\n\n${peer}`,'')
.replace('\n\n\n','\n\n')
)
} catch (err) {
console.error(`Failed to delete peer config from ${env.WG_CONFIG_FILE}:\n`,err)
return res.sendStatus(500)
} finally {
// Success
console.log(`Saved new peer from ${req.requester}`)
return res.sendStatus(200)
}
} }
// Find peer in config
const peer = config.split('\n\n')
.filter( (paragraph) => {
return paragraph.includes('[Peer]')
}).filter( (peer) => {
return peer.includes(`PublicKey = ${req.body}`)
})
// Delete peer
try { await fs.writeFile(env.WG_CONFIG_FILE,
config.replace(`\n\n${peer}`,'')
.replace('\n\n\n','\n\n')
) }
catch (err) {
console.error(`Failed to delete peer config from ${env.WG_CONFIG_FILE}:\n`,err)
return res.sendStatus(500)
}
// Success
console.log(`Deleted peer by requested from ${req.requester}`)
return res.sendStatus(200)
} }

View File

@ -1,5 +1,5 @@
'use strict' 'use strict'
/* add.js /* app/add.js
* route for a client to add a peer * route for a client to add a peer
*/ */
@ -34,7 +34,7 @@ module.exports = async (req, res) => {
return res.sendStatus(err) return res.sendStatus(err)
} console.log(`${req.requester} must be ${user.name}`) } console.log(`${req.requester} must be ${user.name}`)
// Check user token // Check token
if (req.query['token']!==helper.getToken(req.requester)) { if (req.query['token']!==helper.getToken(req.requester)) {
console.log(`Invalid token from ${req.requester}: ${req.query['token']}`) console.log(`Invalid token from ${req.requester}: ${req.query['token']}`)
return res.sendStatus(403) return res.sendStatus(403)
@ -129,7 +129,7 @@ update add *.${domain} ${env.DNS_TTL} CNAME ${domain}`)
console.error(`Failed to add ns record:\n${err}`) console.error(`Failed to add ns record:\n${err}`)
return res.sendStatus(500) return res.sendStatus(500)
} }
finally { console.log(`Updated nameserver to add ${domain}.`) } console.log(`Updated nameserver to add ${domain}.`)
// Generate user config // Generate user config
const listen_port = Math.floor(50000 + Math.random() * 10000) const listen_port = Math.floor(50000 + Math.random() * 10000)

View File

@ -1,5 +1,5 @@
'use strict' 'use strict'
/* del.js /* app/del.js
* route to let clients delete a peer * route to let clients delete a peer
*/ */
@ -28,127 +28,120 @@ module.exports = async (req, res) => {
catch (err) { catch (err) {
console.error(`Failed to get user from ${req.requester}`) console.error(`Failed to get user from ${req.requester}`)
return res.sendStatus(err) return res.sendStatus(err)
} finally { }
console.log(`${req.requester} must be ${user.name}`) console.log(`${req.requester} must be ${user.name}`)
// Check user token
if (req.query['token']!==helper.getToken(req.requester)) {
console.log(`Invalid token from ${req.requester}: ${req.query['token']}`)
return res.sendStatus(403)
}
// Load wg.conf // Check token
let config_file if (req.query['token']!==helper.getToken(req.requester)) {
try { config_file = await fs.readFile(env.WG_CONFIG_FILE) } console.log(`Invalid token from ${req.requester}: ${req.query['token']}`)
catch (err) { console.error(err); return res.sendStatus(500) } return res.sendStatus(403)
finally { }
// Search for peer // Load wg.conf
let peer_pubkey let config_file
const config = config_file.toString() try { config_file = await fs.readFile(env.WG_CONFIG_FILE) }
const peer = config.split('\n\n') catch (err) { console.error(err); return res.sendStatus(500) }
.filter( (paragraph) => {
return paragraph.includes('[Peer]') // Search for peer
}).filter( (peer) => { let peer_pubkey
if (req.query['name']) { const config = config_file.toString()
return peer.includes(`[Peer] # ${req.query['name']}.`) const peer = config.split('\n\n')
} else if (req.query['pubkey']) { .filter( (paragraph) => {
peer_pubkey = req.query['pubkey'] return paragraph.includes('[Peer]')
return peer.includes(`PublicKey = ${req.query['pubkey']}`) }).filter( (peer) => {
} else if (req.query['psk']) { if (req.query['name']) {
return peer.includes(`PresharedKey = ${req.query['psk']}`) return peer.includes(`[Peer] # ${req.query['name']}.`)
} else if (req.query['ip']) { } else if (req.query['pubkey']) {
return peer.split('\n').some( (line) => ( peer_pubkey = req.query['pubkey']
line.includes('AllowedIPs') && return peer.includes(`PublicKey = ${req.query['pubkey']}`)
line.includes(` ${req.query['ip']}/`) } else if (req.query['psk']) {
) ) return peer.includes(`PresharedKey = ${req.query['psk']}`)
} else if (req.query['privkey']) { } else if (req.query['ip']) {
// .filter() doesn't support async so use then/catch in this block return peer.split('\n').some( (line) => (
wg.getPubkeyFromPrivkey(req.query['privkey']) line.includes('AllowedIPs') &&
.then((pubkey) => { line.includes(` ${req.query['ip']}/`)
peer_pubkey = pubkey ) )
return peer.includes(`PublicKey = ${pubkey}`) } else if (req.query['privkey']) {
}) // .filter() doesn't support async so use then/catch in this block
.catch((err) => { wg.getPubkeyFromPrivkey(req.query['privkey'])
console.error(`Failed to generate public key from private key during delete request\n`,err) .then((pubkey) => {
return res.sendStatus(500) peer_pubkey = pubkey
}) return peer.includes(`PublicKey = ${pubkey}`)
} else { })
console.error(`${req.requester} sent delete request without specifying a peer`) .catch((err) => {
return res.sendStatus(400) console.error(`Failed to generate public key from private key during delete request\n`,err)
} return res.sendStatus(500)
})[0] })
if (peer===undefined) { } else {
console.log(`No peer found for delete request from ${req.requester}`) console.error(`${req.requester} sent delete request without specifying a peer`)
return res.sendStatus(404) return res.sendStatus(400)
} }
})[0]
// Parse peer if (peer===undefined) {
const peer_lines = peer.split('\n') console.log(`No peer found for delete request from ${req.requester}`)
const peer_name = peer_lines return res.sendStatus(404)
.filter( (line) => line.includes('[Peer] # ') )[0] }
.split(' # ')[1]
const peer_ips = peer_lines // Parse peer
.filter( (line) => line.includes('AllowedIPs = '))[0] const peer_lines = peer.split('\n')
.split(' = ')[1] const peer_name = peer_lines
if (peer_pubkey===undefined) { .filter( (line) => line.includes('[Peer] # ') )[0]
peer_pubkey = peer_lines .split(' # ')[1]
.filter( (line) => line.includes('PublicKey = ') )[0] const peer_ips = peer_lines
.split(' = ')[1] .filter( (line) => line.includes('AllowedIPs = '))[0]
} .split(' = ')[1]
if (peer_pubkey===undefined) {
// Make sure requester can't delete self peer_pubkey = peer_lines
if (peer_ips.includes(req.requester)) { .filter( (line) => line.includes('PublicKey = ') )[0]
console.log(`Refused to let ${req.requester} delete self: ${peer_name}`) .split(' = ')[1]
return res.sendStatus(409) // "Conflict" }
}
// Make sure requester can't delete self
// Delete from local wg config if (peer_ips.includes(req.requester)) {
console.log(`Deleting ${peer_name}`); try { console.log(`Refused to let ${req.requester} delete self: ${peer_name}`)
await fs.writeFile(env.WG_CONFIG_FILE, return res.sendStatus(409) // "Conflict"
config.replace(`\n\n${peer}`,'') }
.replace('\n\n\n','\n\n')
) // Delete from local wg config
console.log(`Deleting ${peer_name}`); try {
await fs.writeFile(env.WG_CONFIG_FILE,
config.replace(`\n\n${peer}`,'')
.replace('\n\n\n','\n\n')
)
} catch (err) {
console.error(`Failed to delete ${peer_name}:\n`,err)
return res.sendStatus(500)
}
// Inform other servers
for (const server of env.SERVERS) {
if (server.host!==env.LOCAL_SERVER) {
try {
console.log(`Informing ${server.host} to delete ${peer_name}`)
await axios.post(`${server.admin_endpoint}/del?secret=${server.secret}`, peer_pubkey, {
headers: {'Content-Type': 'text/plain'},
})
} catch (err) { } catch (err) {
console.error(`Failed to delete ${peer_name}:\n`,err) console.error(`Failed to inform ${server.host} to delete ${peer_name}:\n\n`,err)
return res.sendStatus(500) return res.sendStatus(500)
} finally { }
}
// Inform other servers }
for (const server of env.SERVERS) {
if (server.host!==env.LOCAL_SERVER) { // Delete domains from nameserver
try { try {
console.log(`Informing ${server.host} to delete ${peer_name}`) await helper.nsUpdate(dns_key, env.DNS_MASTER,
await axios.post(`${server.admin_endpoint}/del?secret=${server.secret}`, peer_pubkey, {
headers: {'Content-Type': 'text/plain'},
})
} catch (err) {
console.error(`Failed to inform ${server.host} to delete ${peer_name}:\n\n`,err)
return res.sendStatus(500)
}
}
}
// Delete domains from nameserver
try {
await helper.nsUpdate(dns_key, env.DNS_MASTER,
`update delete ${peer_name}. A `update delete ${peer_name}. A
update delete ${peer_name}. AAAA update delete ${peer_name}. AAAA
update delete *.${peer_name}. CNAME`) update delete *.${peer_name}. CNAME`)
}
catch (err) {
console.error(`Failed to delete ns record:\n${err}`)
return res.sendStatus(500)
}
finally { console.log(`Updated nameserver to delete ${peer_name}.`) }
// Inform user that delete was successful
res.sendStatus(200)
}
}
} }
catch (err) {
console.error(`Failed to delete ns record`)
if (err) console.error(err)
return res.sendStatus(500)
}
console.log(`Updated nameserver to delete ${peer_name}.`)
return res.sendStatus(200)
} }

View File

@ -15,23 +15,17 @@ 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.sendStatus(err) return res.sendStatus(err)
} }
finally { console.log(`${req.requester} must be ${user.name}`)
console.log(`${req.requester} must be ${user.name}`)
// Get or generate token
// Get or generate token try { user.token = helper.getToken(req.requester) || await helper.setToken(req.requester) }
try { user.token = helper.getToken(req.requester) || await helper.setToken(req.requester) } catch (err) {
catch (err) { console.error(`Failed to set token for ${req.requester}`)
console.error(`Failed to set token for ${req.requester}`) return res.sendStatus(err)
return res.sendStatus(err)
}
finally {
// Send user
res.setHeader('content-type', 'text/json')
res.send(user)
}
} }
// Send user
res.setHeader('content-type', 'text/json')
res.send(user)
} }

View File

@ -25,7 +25,7 @@ module.exports = {
}).filter( (peer) => { }).filter( (peer) => {
return peer.includes(`${env.IPV4_NET}.${subnet}`) || peer.includes(`${env.IPV6_NET}:${subnet}`) return peer.includes(`${env.IPV4_NET}.${subnet}`) || peer.includes(`${env.IPV6_NET}:${subnet}`)
}) })
} catch (err) { console.log(err) } } catch (err) { console.log(err); reject(500) }
let found_usernames = [] let found_usernames = []
let found_hosts = [] let found_hosts = []
for (const userpeer of userpeers) { for (const userpeer of userpeers) {
@ -73,6 +73,39 @@ module.exports = {
} }
}), }),
getAllUsers: () =>
new Promise( async (resolve, reject) => {
let users = {}
let peers; try {
peers = (await fs.readFile(env.WG_CONFIG_FILE)).toString()
.split('\n\n').filter( (paragraph) => {
return paragraph.includes('[Peer]')
})
} catch (err) { console.log(err) }
for (const peer of peers) {
let peer_obj = {}
let peer_username
for (const line of peer.split('\n')) {
if (line.includes('[Peer] # ')) {
const domain = line.split(' # ')[1].split('.')
peer_obj.name = domain[0]
peer_username = domain[1]
}
else if (line.includes('AllowedIPs = ')) {
const ips = line.split('=')[1].split(', ')
peer_obj.ipv4 = ips.filter( (ip) => ip.includes(env.IPV4_NET) )[0].trim()
peer_obj.ipv6 = ips.filter( (ip) => ip.includes(env.IPV6_NET) )[0].trim()
}
}
if (!users[peer_username]) users[peer_username] = {
name: peer_username,
peers: [],
}
users[peer_username].peers.push(peer_obj)
}
resolve(users)
}),
getToken: (ip) => tokens[ip], getToken: (ip) => tokens[ip],
setToken: (ip) => setToken: (ip) =>
new Promise ( async (resolve, reject) => { new Promise ( async (resolve, reject) => {