Code cleanup
parent
0a6c042b11
commit
37fa81eda4
15
admin/add.js
15
admin/add.js
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
55
admin/del.js
55
admin/del.js
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
|
225
app/del.js
225
app/del.js
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
28
app/list.js
28
app/list.js
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in New Issue