Moved routes to own files
parent
addc2754f3
commit
c6ab3893fb
|
@ -0,0 +1,130 @@
|
|||
'use strict'
|
||||
const fs = require('fs').promises
|
||||
const wg = require('./wireguard')
|
||||
const env = require('./env.json')
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
const hostname = req.query['name']
|
||||
if (!hostname) {
|
||||
console.log(`New peer request from ${req.requester} didn't provide a hostname`)
|
||||
res.sendStatus(500); return
|
||||
}
|
||||
console.log(`New peer request from ${req.requester} for ${hostname}`)
|
||||
|
||||
// Determine user subnet
|
||||
let subnet
|
||||
if (req.requester.includes(env.IPV4_NET)) subnet = req.requester.split('.').slice(-2,-1)[0]
|
||||
else if (req.requester.includes(env.IPV6_NET)) subnet = req.requester.split(':').slice(-2,-1)[0]
|
||||
else console.log(`Received add request from ${req.requester}, which does not appear to be from the network.`)
|
||||
|
||||
// Read wg.conf file for this user's other devices
|
||||
const userpeers = (await fs.readFile(env.WG_CONFIG_FILE)).toString()
|
||||
.split('\n\n').filter( (paragraph) => {
|
||||
return paragraph.includes('[Peer]')
|
||||
}).filter( (peer) => {
|
||||
return peer.includes(`${env.IPV4_NET}.${subnet}`) || peer.includes(`${env.IPV6_NET}:${subnet}`)
|
||||
})
|
||||
let found_usernames = []
|
||||
let found_ipv6s = []
|
||||
let found_ipv4s = []
|
||||
for (const userpeer of userpeers) {
|
||||
for (const line of userpeer.split('\n')) {
|
||||
if (line.includes('[Peer]')) {
|
||||
// Check if host exists
|
||||
if (line.includes(`# ${hostname}.`)) {
|
||||
console.log(`Host already exists for ${hostname}`)
|
||||
res.sendStatus(500); return
|
||||
}
|
||||
found_usernames.push(line.split('.').slice(-2,-1)[0])
|
||||
}
|
||||
else if (line.includes('AllowedIPs')) {
|
||||
const ips = line.split('=')[1].split(',')
|
||||
found_ipv4s.push(ips.filter( (ip) => ip.includes(env.IPV4_NET) )[0].trim())
|
||||
found_ipv6s.push(ips.filter( (ip) => ip.includes(env.IPV6_NET) )[0].trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check that all IP addresses are in correct subnet or error out
|
||||
if (!found_ipv4s.every((found_ipv4) =>
|
||||
found_ipv4.toString().includes(`${env.IPV4_NET}.${subnet}.`))) {
|
||||
console.log(`Found unmatching IPv4 address subnets for ${req.requester}: ${found_ipv4s}`)
|
||||
res.sendStatus(500); return
|
||||
} else if (!found_ipv6s.every((found_ipv6) =>
|
||||
found_ipv6.toString().includes(`${env.IPV6_NET}:${subnet}:`))) {
|
||||
console.log(`Found unmatching IPv6 address subnets for ${req.requester}: ${found_ipv6s}`)
|
||||
res.sendStatus(500); return
|
||||
|
||||
// Check that the req.requester is "on the list"
|
||||
// Should never get here because this req.requester can't access this IP!
|
||||
} else if (found_usernames.length ===0) {
|
||||
console.log(`Received request from ${req.requester} not in wg.conf!`)
|
||||
res.sendStatus(500); return
|
||||
// Check that all usernames are correct or error out
|
||||
// https://stackoverflow.com/a/35568895
|
||||
} else if (!found_usernames.every( (v,i,r) => v === r[0] )) {
|
||||
console.log(`Found unmatching usernames for ${req.requester}: ${found_usernames.toString()}`)
|
||||
res.sendStatus(500); return
|
||||
|
||||
// Everything looks good! Proceed
|
||||
} else {
|
||||
const username = found_usernames[0]
|
||||
console.log(`${req.requester} must be ${username}`)
|
||||
|
||||
// Find next available host part in config
|
||||
const used_ipv4_hosts = found_ipv4s.map((found_ipv4) =>
|
||||
found_ipv4.toString().split('.')[3].split('/')[0])
|
||||
const used_ipv6_hosts = found_ipv6s.map((found_ipv6) =>
|
||||
found_ipv6.toString().split(':')[3].split('/')[0])
|
||||
let host = 1
|
||||
while ([...used_ipv4_hosts,...used_ipv6_hosts].includes(host.toString())) host++
|
||||
|
||||
// Create IP Addresses and keys
|
||||
const ipv4_addr = `${env.IPV4_NET}.${subnet}.${host}`
|
||||
const ipv6_addr = `${env.IPV6_NET}:${subnet}:${host}`
|
||||
const keypair = await wg.generateKeypair()
|
||||
const pubkey = keypair[0]
|
||||
const privkey = keypair[1]
|
||||
|
||||
// Create [Peer] sections for each env.SERVERS
|
||||
let client_peers = []
|
||||
for (const server of env.SERVERS) {
|
||||
const psk = await wg.generatePSK()
|
||||
client_peers.push(`
|
||||
[Peer] # ${server.host}.${env.TLD}
|
||||
PublicKey = ${server.pubkey}
|
||||
PresharedKey = ${psk}
|
||||
AllowedIPs = ${server.ipv4}/32, ${server.ipv6}/128
|
||||
Endpoint = ${server.endpoint}
|
||||
PersistentKeepAlive = 25`)
|
||||
const server_config = `\n
|
||||
[Peer] # ${hostname}.${username}.${env.TLD}
|
||||
PublicKey = ${pubkey}
|
||||
PresharedKey = ${psk}
|
||||
AllowedIPs = ${ipv4_addr}/32, ${ipv6_addr}/128`
|
||||
if (server.host===env.LOCAL_SERVER) {
|
||||
// Add server_config to wg0.conf
|
||||
fs.appendFile(env.WG_CONFIG_FILE,server_config)
|
||||
} else {
|
||||
//TODO: Send server_config to `${server.host}.gf4`
|
||||
console.log(`Sending config to ${server.host}.gf4`)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Nameserver config
|
||||
|
||||
// Generate config
|
||||
const listen_port = Math.floor(50000 + Math.random() * 10000)
|
||||
const config = `[Interface]
|
||||
PrivateKey = ${privkey}
|
||||
Address = ${ipv4_addr}/${env.IPV4_CIDR}, ${ipv6_addr}/${env.IPV6_CIDR}
|
||||
DNS = ${req.DNS_SERVERS_STRING}
|
||||
ListenPort = ${listen_port}
|
||||
PostUp = resolvectl domain ${env.TLD} ${env.TLD}
|
||||
${client_peers.join('\n')}`
|
||||
|
||||
// Send config to user
|
||||
res.setHeader('content-type', 'text/plain')
|
||||
res.send(config)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
'use strict'
|
||||
const fs = require('fs').promises
|
||||
const env = require('./env.json')
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
const privkey = req.query['del']
|
||||
|
||||
console.log(`Received request from ${req.requester} to delete ${privkey}`)
|
||||
res.setHeader('content-type', 'text/plain')
|
||||
res.send(`Delete ${privkey}`)
|
||||
|
||||
}
|
159
index.js
159
index.js
|
@ -1,7 +1,4 @@
|
|||
'use strict'
|
||||
const fs = require('fs').promises
|
||||
const app = require('express')()
|
||||
const wg = require('./wireguard')
|
||||
const env = require('./env.json')
|
||||
|
||||
// Determine DNS servers string from environment file
|
||||
|
@ -11,145 +8,21 @@ for (const server of env.SERVERS.filter((server) => server.dns) ){
|
|||
if (server.ipv6) DNS_SERVERS.push(server.ipv6)
|
||||
}
|
||||
const DNS_SERVERS_STRING = DNS_SERVERS.join(', ')
|
||||
const getDnsServers = (req, res, next) => {
|
||||
req.DNS_SERVERS_STRING = DNS_SERVERS_STRING
|
||||
next()
|
||||
}
|
||||
|
||||
// API
|
||||
app.get('/', async (req,res) => {
|
||||
// Determine request IP
|
||||
const getRequester = (req, res, next) => {
|
||||
req.requester = (env.ENV==='prod')
|
||||
?req.ip.replace('::ffff:','')
|
||||
:'10.4.1.1'
|
||||
next()
|
||||
}
|
||||
|
||||
const privkey = req.query['del']
|
||||
const hostname = req.query['add']
|
||||
const requester = (env.ENV==='prod')
|
||||
?req.ip.replace('::ffff:','')
|
||||
:'10.4.1.1'
|
||||
|
||||
|
||||
// Delete a peer
|
||||
if (privkey) {
|
||||
console.log(`Received request from ${requester} to delete ${privkey}`)
|
||||
res.setHeader('content-type', 'text/plain')
|
||||
res.send(`Delete ${privkey}`)
|
||||
}
|
||||
|
||||
// Add a peer
|
||||
else if (hostname) {
|
||||
console.log(`New peer request from ${requester}`)
|
||||
|
||||
// Determine user subnet
|
||||
let subnet
|
||||
if (requester.includes(env.IPV4_NET)) subnet = requester.split('.').slice(-2,-1)[0]
|
||||
else if (requester.includes(env.IPV6_NET)) subnet = requester.split(':').slice(-2,-1)[0]
|
||||
else console.log(`Received add request from ${requester}, which does not appear to be from the network.`)
|
||||
|
||||
// Read wg.conf file for this user's other devices
|
||||
const userpeers = (await fs.readFile(env.WG_CONFIG_FILE)).toString()
|
||||
.split('\n\n').filter( (paragraph) => {
|
||||
return paragraph.includes('[Peer]')
|
||||
}).filter( (peer) => {
|
||||
return peer.includes(`${env.IPV4_NET}.${subnet}`) || peer.includes(`${env.IPV6_NET}:${subnet}`)
|
||||
})
|
||||
let found_usernames = []
|
||||
let found_ipv6s = []
|
||||
let found_ipv4s = []
|
||||
for (const userpeer of userpeers) {
|
||||
for (const line of userpeer.split('\n')) {
|
||||
if (line.includes('[Peer]')) {
|
||||
// Check if host exists
|
||||
if (line.includes(`# ${hostname}.`)) {
|
||||
console.log(`Host already exists for ${hostname}`)
|
||||
res.sendStatus(500); return
|
||||
}
|
||||
found_usernames.push(line.split('.').slice(-2,-1)[0])
|
||||
}
|
||||
else if (line.includes('AllowedIPs')) {
|
||||
const ips = line.split('=')[1].split(',')
|
||||
found_ipv4s.push(ips.filter( (ip) => ip.includes(env.IPV4_NET) )[0].trim())
|
||||
found_ipv6s.push(ips.filter( (ip) => ip.includes(env.IPV6_NET) )[0].trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check that all IP addresses are in correct subnet or error out
|
||||
if (!found_ipv4s.every((found_ipv4) =>
|
||||
found_ipv4.toString().includes(`${env.IPV4_NET}.${subnet}.`))) {
|
||||
console.log(`Found unmatching IPv4 address subnets for ${requester}: ${found_ipv4s}`)
|
||||
res.sendStatus(500); return
|
||||
} else if (!found_ipv6s.every((found_ipv6) =>
|
||||
found_ipv6.toString().includes(`${env.IPV6_NET}:${subnet}:`))) {
|
||||
console.log(`Found unmatching IPv6 address subnets for ${requester}: ${found_ipv6s}`)
|
||||
res.sendStatus(500); return
|
||||
|
||||
// Check that the requester is "on the list"
|
||||
// Should never get here because this requester can't access this IP!
|
||||
} else if (found_usernames.length ===0) {
|
||||
console.log(`Received request from ${requester} not in wg.conf!`)
|
||||
res.sendStatus(500); return
|
||||
// Check that all usernames are correct or error out
|
||||
// https://stackoverflow.com/a/35568895
|
||||
} else if (!found_usernames.every( (v,i,r) => v === r[0] )) {
|
||||
console.log(`Found unmatching usernames for ${requester}: ${found_usernames.toString()}`)
|
||||
res.sendStatus(500); return
|
||||
|
||||
// Everything looks good! Proceed
|
||||
} else {
|
||||
const username = found_usernames[0]
|
||||
console.log(`${requester} must be ${username}`)
|
||||
|
||||
// Find next available host part in config
|
||||
const used_ipv4_hosts = found_ipv4s.map((found_ipv4) =>
|
||||
found_ipv4.toString().split('.')[3].split('/')[0])
|
||||
const used_ipv6_hosts = found_ipv6s.map((found_ipv6) =>
|
||||
found_ipv6.toString().split(':')[3].split('/')[0])
|
||||
let host = 1
|
||||
while ([...used_ipv4_hosts,...used_ipv6_hosts].includes(host.toString())) host++
|
||||
|
||||
// Create IP Addresses and keys
|
||||
const ipv4_addr = `${env.IPV4_NET}.${subnet}.${host}`
|
||||
const ipv6_addr = `${env.IPV6_NET}:${subnet}:${host}`
|
||||
const keypair = await wg.generateKeypair()
|
||||
const pubkey = keypair[0]
|
||||
const privkey = keypair[1]
|
||||
|
||||
// Create [Peer] sections for each env.SERVERS
|
||||
let client_peers = []
|
||||
for (const server of env.SERVERS) {
|
||||
const psk = await wg.generatePSK()
|
||||
client_peers.push(`
|
||||
[Peer] # ${server.host}.${env.TLD}
|
||||
PublicKey = ${server.pubkey}
|
||||
PresharedKey = ${psk}
|
||||
AllowedIPs = ${server.ipv4}/32, ${server.ipv6}/128
|
||||
Endpoint = ${server.endpoint}
|
||||
PersistentKeepAlive = 25`)
|
||||
const server_config = `\n
|
||||
[Peer] # ${hostname}.${username}.${env.TLD}
|
||||
PublicKey = ${pubkey}
|
||||
PresharedKey = ${psk}
|
||||
AllowedIPs = ${ipv4_addr}/32, ${ipv6_addr}/128`
|
||||
if (server.host===env.LOCAL_SERVER) {
|
||||
// Add server_config to wg0.conf
|
||||
fs.appendFile(env.WG_CONFIG_FILE,server_config)
|
||||
} else {
|
||||
//TODO: Send server_config to `${server.host}.gf4`
|
||||
console.log(`Sending config to ${server.host}.gf4`)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Nameserver config
|
||||
|
||||
// Generate config
|
||||
const listen_port = Math.floor(50000 + Math.random() * 10000)
|
||||
const config = `[Interface]
|
||||
PrivateKey = ${privkey}
|
||||
Address = ${ipv4_addr}/${env.IPV4_CIDR}, ${ipv6_addr}/${env.IPV6_CIDR}
|
||||
DNS = ${DNS_SERVERS_STRING}
|
||||
ListenPort = ${listen_port}
|
||||
PostUp = resolvectl domain ${env.TLD} ${env.TLD}
|
||||
${client_peers.join('\n')}`
|
||||
|
||||
// Send config to user
|
||||
res.setHeader('content-type', 'text/plain')
|
||||
res.send(config)
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid querystring
|
||||
else { console.log(`Invalid querystring: ${req.query}`) }
|
||||
}).listen(env.PORT)
|
||||
// Main
|
||||
require('express')()
|
||||
.get('/add', getRequester, getDnsServers, require('./add.js'))
|
||||
.get('/del', getRequester, require('./del.js'))
|
||||
.listen(env.PORT)
|
||||
|
|
Loading…
Reference in New Issue