vpn: refactor key handling code

Move JS code for listing, creating and deleting WG keys into a
separate file and improve it somewhat. Also the related Python code.
This commit is contained in:
Timotej Lazar 2024-07-27 13:40:02 +02:00
parent 8c9829b726
commit 1b26f0738a
3 changed files with 154 additions and 149 deletions

View file

@ -2,10 +2,7 @@
{% block content %}
<p>
Za VPN oziroma oddeljano povezavo v omrežje FRI uporabljamo <a href="https://wireguard.com">WireGuard</a>. Več informacij o uporabi in nastavitvah VPN najdete v <a href="https://doku.fri.uni-lj.si/vpn">dokumentaciji</a>.
<p>
Za priklop v omrežje spodaj ustvarite nov ključ in prenesite izpisano datoteko. Nato sledite napotkom za posamezni sistem.
Za VPN oziroma oddeljano povezavo v omrežje FRI uporabljamo <a href="https://wireguard.com">WireGuard</a>. Za priklop v omrežje ustvarite nov ključ in prenesite izpisano datoteko. Nato sledite napotkom za posamezni sistem.
<details>
<summary>Windows / Mac</summary>
@ -43,14 +40,14 @@ Na vsaki napravi, ki jo želite povezati v omrežje FRI, ustvarite nov ključ. P
<input id="name" name="name" pattern="[-._A-Za-z0-9 ]*" maxlength="16" placeholder="A-Z a-z 0-9 . _ - " />
<button id="submit" type="submit">Ustvari ključ</button>
<p>
<input type="checkbox" id="add_default" name="add_default" />
<label for="add_default">Uporabi VPN za ves promet</label>
<input type="checkbox" id="add-default" name="add-default" />
<label for="add-default">Uporabi VPN za ves promet</label>
<br>
<input type="checkbox" id="use_dns" name="use_dns" checked />
<label for="use_dns">Uporabi imenske strežnike FRI</label>
<input type="checkbox" id="use-dns" name="use-dns" checked />
<label for="use-dns">Uporabi imenske strežnike FRI</label>
<p>
Če vklopite prvo opcijo, bo vaš računalnik čez VPN usmerjal ves promet. Če izklopite drugo opcijo, bodo nekateri strežniki dostopni le prek naslova IP. Če ste v dvomih, pustite privzete nastavitve.
Če vklopite prvo opcijo, bo vaš računalnik čez VPN usmerjal ves promet. Če izklopite drugo opcijo, bodo nekateri strežniki dostopni le prek naslova IP. Če ste v dvomih, pustite privzete nastavitve. Več informacij o uporabi in nastavitvah VPN <a href="https://doku.fri.uni-lj.si/vpn">najdemo v dokumentaciji</a>.
</form>
<section id="settings" style="display: none;">
@ -73,125 +70,10 @@ V nastavitvah lahko dodate ali odstranite vnose <code>AllowedIPs</code>. Ti dolo
Če ključa ne uporabljamo, smo ga izgubili ali so nam ga ukradli, ga tukaj odstranimo. Trenutno so registrirani ključi:
<ul class="keys" style="list-style: none;"></ul>
<p class="keys" id="active-key-warning" style="margin-top: 0;">
<font color="red"><sup></sup></font> Ta ključ uporablja trenutna povezava. Če ga odstranite, bo prekinjena.
</section>
<script type="text/javascript" src="{{ url_for('static', filename='qrcode.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='wireguard.js') }}"></script>
<script type="text/javascript">
function del_key(key) {
fetch('del', {
credentials: 'include',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ pubkey: key })
})
.then(response => {
if (!response.ok)
throw new Error('deleting key failed');
return response.text();
})
.then(data => {
// reload key list
window.dispatchEvent(new Event('load'));
})
.catch(error => console.error(error));
}
function fetch_keys() {
fetch('list', {
credentials: 'include'
})
.then(response => {
if (!response.ok)
throw new Error('fetching keys failed');
return response.json();
})
.then(data => {
const keys = document.querySelector('ul.keys');
keys.innerHTML = '';
const warning = document.getElementById('active-key-warning');
warning.innerHTML = '';
for (let key of Object.values(data)) {
var a = document.createElement('a');
a.innerText = '✖';
a.href = '';
a.addEventListener('click', event => {
del_key(key.key);
event.preventDefault();
});
var li = document.createElement('li');
li.innerHTML = ' ' + (new Date(key.time*1000).toISOString().split('T')[0]) +
' <code>' + key.key + '</code> ' + key.name +
(key.active ? '<font color="red"><sup></sup></font> ' : '');
li.prepend(a);
keys.appendChild(li);
if (key.active)
warning.innerHTML = '<font color="red"><sup></sup></font> Ta ključ uporablja trenutna povezava. Če ga odstranite, bo prekinjena.';
}
document.querySelector('section.keys').style.display = (Object.keys(data).length ? 'unset' : 'none');
})
.catch(error => console.error(error));
}
window.addEventListener('load', fetch_keys);
const request = document.getElementById('request');
request.addEventListener('submit', event => {
event.preventDefault();
const name = document.getElementById('name');
const key = wireguard.generateKeypair();
const settings = document.getElementById('settings');
const submit = document.getElementById('submit');
const use_dns = document.getElementById('use_dns');
const add_default = document.getElementById('add_default');
submit.innerHTML = 'Obdelovanje…';
submit.disabled = true;
fetch('new', {
credentials: 'include',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
pubkey: key.publicKey,
name: name.value,
use_dns: use_dns.checked,
add_default: add_default.checked,
})
})
.then(response => {
if (!response.ok) {
response.text().then(text => {
settings.innerHTML = response.status + ' ' + response.statusText + ': ' + text;
});
} else {
return response.text();
}
})
.then(text => {
var complete = text.replace(/PrivateKey = .*/, "PrivateKey = "+key.privateKey).trim();
document.getElementById("config").innerHTML = complete;
var blob = new Blob([complete], { type: 'text/plain;charset=utf-8' });
const link = document.getElementById('download');
link.download = 'wg-fri.conf';
link.href = window.URL.createObjectURL(blob);
var qr = qrcode(0, 'L');
qr.addData(complete.replace(/#.*\n/g, ''));
qr.make();
document.getElementById('qr').innerHTML = qr.createSvgTag(3);
// reload key list
fetch_keys();
})
.catch(error => {
settings.innerHTML = error;
})
.finally(() => {
request.style.display = 'none';
settings.style.display = 'unset';
});
});
</script>
<script type="text/javascript" src="{{ url_for('static', filename='vpn.js') }}"></script>
{% endblock %}