Compare commits

...

19 Commits

Author SHA1 Message Date
donaldzou
f361e178f1 Added the function to remove peers 2020-12-26 23:42:41 -05:00
donaldzou
edc77be8ef Merge branch 'main' of https://github.com/donaldzou/Wireguard-Dashboard into main 2020-12-26 00:17:43 -05:00
donaldzou
55ba5801af Added connected peers 2020-12-26 00:17:42 -05:00
Donald Zou
6d9c35f7cc Update README.md 2020-10-28 10:12:39 -04:00
Donald Zou
320b82dc18 Update README.md 2020-10-23 17:51:11 -04:00
donaldzou
d22d695312 Merge branch 'main' of https://github.com/donaldzou/Wireguard-Dashboard into main 2020-10-23 01:51:03 -04:00
donaldzou
ba5eeeba07 Commit 2020-10-23 01:50:52 -04:00
Donald Zou
0b5b2b6243 Delete sftp.json 2020-10-23 01:50:04 -04:00
donaldzou
0efef135d6 Merge branch 'main' of https://github.com/donaldzou/Wireguard-Dashboard into main 2020-10-23 01:31:15 -04:00
donaldzou
ea52529e06 Able to add peer 2020-10-23 01:31:10 -04:00
Donald Zou
259bd325af Update README.md 2020-10-21 20:30:16 -04:00
Donald Zou
faf05bad6a Delete .DS_Store 2020-10-20 10:47:02 -04:00
Donald Zou
0576906907 Delete .DS_Store 2020-10-20 10:46:53 -04:00
donaldzou
8c88440c3e commit 2020-10-20 10:45:29 -04:00
donaldzou
2f327ed49a File arrangement 2020-10-20 10:44:41 -04:00
donaldzou
96af266c38 Update configuration.html 2020-10-19 11:48:08 -04:00
Donald Zou
397e448899 Update README.md 2020-10-18 20:20:02 -04:00
donaldzou
cabb6df477 Update configuration.html 2020-10-18 20:19:41 -04:00
donaldzou
032ea1d967 On/Off Switch 2020-10-18 12:23:38 -04:00
13 changed files with 417 additions and 164 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
.vscode/sftp.json .vscode/sftp.json
src/.vscode/sftp.json
.DS_Store

View File

@@ -1,8 +1,9 @@
# Wireguard-Dashboard # Wireguard Dashboard
## Intro ## Intro
Monitoring Wireguard is not convinient, need to login into server and type wg show. That's why this platform is being created, to view all configurations in a more straight forward way. Monitoring Wireguard is not convinient, need to login into server and type wg show. That's why this platform is being created, to view all configurations in a more straight forward way.
## Installation ## Installation
**Requirement:** **Requirement:**
- Ubuntu 18.04.1 LTS, other OS might work, but haven't test yet.
- Wireguard - Wireguard
- Configuration files under **/etc/wireguard** - Configuration files under **/etc/wireguard**
- Python 3.7 - Python 3.7
@@ -10,10 +11,10 @@ Monitoring Wireguard is not convinient, need to login into server and type wg sh
**Install:** **Install:**
1. `git clone https://github.com/donaldzou/Wireguard-Dashboard.git` 1. `git clone https://github.com/donaldzou/Wireguard-Dashboard.git`
2. `cd Wireguard-Dashboard` 2. `cd Wireguard-Dashboard\src`
3. `python3 dashboard.py` 3. `python3 dashboard.py`
4. Access your server! e.g (http://your_server_ip:10086) 4. Access your server! e.g (http://your_server_ip:10086)
## Example ## Example
![Index Image](https://github.com/donaldzou/Wireguard-Dashboard/raw/main/static/index.png) ![Index Image](https://github.com/donaldzou/Wireguard-Dashboard/raw/main/src/static/index.png)
![Conf Image](https://github.com/donaldzou/Wireguard-Dashboard/raw/main/static/configuration.png) ![Conf Image](https://github.com/donaldzou/Wireguard-Dashboard/raw/main/src/static/configuration.png)

View File

@@ -1,14 +1,44 @@
import os import os
from flask import Flask, request, render_template from flask import Flask, request, render_template, redirect, url_for
from tinydb import TinyDB, Query
import subprocess import subprocess
from datetime import datetime, date, time, timedelta from datetime import datetime, date, time, timedelta
from tinydb import TinyDB, Query
import time
import requests
conf_location = "/etc/wireguard" conf_location = "/etc/wireguard"
app = Flask("Wireguard Dashboard") app = Flask("Wireguard Dashboard")
app.config['TEMPLATES_AUTO_RELOAD'] = True app.config['TEMPLATES_AUTO_RELOAD'] = True
css = "" css = ""
conf_data = {}
def get_conf_peer_key(config_name):
keys = []
try: peer_key = subprocess.check_output("wg show "+config_name+" peers", shell=True)
except Exception: return "stopped"
peer_key = peer_key.decode("UTF-8").split()
for i in peer_key: keys.append(i)
return keys
def get_conf_running_peer_number(config_name):
running = 0
#Get latest handshakes
try: data_usage = subprocess.check_output("wg show "+config_name+" latest-handshakes", shell=True)
except Exception: return "stopped"
data_usage = data_usage.decode("UTF-8").split()
count = 0
now = datetime.now()
b = timedelta(minutes=2)
for i in range(int(len(data_usage)/2)):
minus = now - datetime.fromtimestamp(int(data_usage[count+1]))
if minus < b:
running += 1
count += 2
return running
def get_conf_peers_data(config_name): def get_conf_peers_data(config_name):
peer_data = {} peer_data = {}
@@ -50,7 +80,6 @@ def get_conf_peers_data(config_name):
b = timedelta(minutes=2) b = timedelta(minutes=2)
for i in range(int(len(data_usage)/2)): for i in range(int(len(data_usage)/2)):
minus = now - datetime.fromtimestamp(int(data_usage[count+1])) minus = now - datetime.fromtimestamp(int(data_usage[count+1]))
if minus < b: if minus < b:
peer_data[data_usage[count]]['status'] = "running" peer_data[data_usage[count]]['status'] = "running"
else: else:
@@ -96,9 +125,9 @@ def get_conf_total_data(config_name):
download_total += int(data_usage[count+2]) download_total += int(data_usage[count+2])
count += 3 count += 3
total = round(((((upload_total+download_total)/1024)/1024)/1024),3) total = round(((((upload_total+download_total)/1024)/1024)/1024),4)
upload_total = round(((((upload_total)/1024)/1024)/1024),3) upload_total = round(((((upload_total)/1024)/1024)/1024),4)
download_total = round(((((download_total)/1024)/1024)/1024),3) download_total = round(((((download_total)/1024)/1024)/1024),4)
return [total, upload_total, download_total] return [total, upload_total, download_total]
@@ -115,6 +144,9 @@ def get_conf_list():
if ".conf" in i: if ".conf" in i:
i = i.replace('.conf','') i = i.replace('.conf','')
temp = {"conf":i, "status":get_conf_status(i), "public_key": get_conf_pub_key(i)} temp = {"conf":i, "status":get_conf_status(i), "public_key": get_conf_pub_key(i)}
if temp['status'] == "running":
temp['checked'] = 'checked'
else: temp['checked'] = ""
conf.append(temp) conf.append(temp)
return conf return conf
@@ -125,15 +157,68 @@ def index():
@app.route('/configuration/<config_name>', methods=['GET']) @app.route('/configuration/<config_name>', methods=['GET'])
def conf(config_name): def conf(config_name):
conf_data = { conf_data = {
"name": config_name, "name": config_name,
"status": get_conf_status(config_name), "status": get_conf_status(config_name),
"total_data_usage": get_conf_total_data(config_name), "total_data_usage": get_conf_total_data(config_name),
"public_key": get_conf_pub_key(config_name), "public_key": get_conf_pub_key(config_name),
"listen_port": get_conf_listen_port(config_name), "listen_port": get_conf_listen_port(config_name),
"peer_data":get_conf_peers_data(config_name) "peer_data":get_conf_peers_data(config_name),
"running_peer": get_conf_running_peer_number(config_name),
"checked": ""
} }
if conf_data['status'] == "stopped":
print(conf_data)
return redirect('/')
else:
conf_data['checked'] = "checked"
return render_template('configuration.html', conf=get_conf_list(), conf_data=conf_data) return render_template('configuration.html', conf=get_conf_list(), conf_data=conf_data)
@app.route('/switch/<config_name>', methods=['GET'])
def switch(config_name):
status = get_conf_status(config_name)
if status == "running":
try: status = subprocess.check_output("wg-quick down "+config_name, shell=True)
except Exception: return redirect('/')
elif status == "stopped":
try: status = subprocess.check_output("wg-quick up "+config_name, shell=True)
except Exception: return redirect('/')
return redirect('/')
@app.route('/add_peer/<config_name>', methods=['POST'])
def add_peer(config_name):
data = request.get_json()
public_key = data['public_key']
allowed_ips = data['allowed_ips']
keys = get_conf_peer_key(config_name)
if public_key in keys:
return "Key already exist."
else:
status = ""
try:
status = subprocess.check_output("wg set "+config_name+" peer "+public_key+" allowed-ips "+allowed_ips, shell=True, stderr=subprocess.STDOUT)
status = subprocess.check_output("wg-quick save "+config_name, shell=True, stderr=subprocess.STDOUT)
return "true"
except subprocess.CalledProcessError as exc:
return exc.output.strip()
# return redirect('/configuration/'+config_name)
@app.route('/remove_peer/<config_name>', methods=['POST'])
def remove_peer(config_name):
data = request.get_json()
delete_key = data['peer_id']
keys = get_conf_peer_key(config_name)
if delete_key not in keys:
return "This key does not exist"
else:
try:
status = subprocess.check_output("wg set "+config_name+" peer "+delete_key+" remove", shell=True, stderr=subprocess.STDOUT)
status = subprocess.check_output("wg-quick save "+config_name, shell=True, stderr=subprocess.STDOUT)
return "true"
except subprocess.CalledProcessError as exc:
return exc.output.strip()
app.run(host='0.0.0.0',debug=False, port=10086) app.run(host='0.0.0.0',debug=False, port=10086)

0
src/json/conf.json Normal file
View File

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 455 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -0,0 +1,282 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Wireguard Dashboard</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='dashboard.css') }}">
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">Wireguard Dashboard</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse"
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
<div class="container-fluid">
<div class="row">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Configurations</span>
</h6>
<ul class="nav flex-column">
{% for i in conf%}
<li class="nav-item"><a class="nav-link" href="/configuration/{{i['conf']}}">{{i['conf']}}</a></li>
{%endfor%}
</ul>
</div>
</nav>
</div>
</div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4">
<div class="info mt-4">
<div class="row">
<div class="col-sm">
<small class="text-muted"><strong>CONFIGURATION</strong></small>
<h1 class="mb-3">{{conf_data['name']}}</h1>
</div>
<div class="col-sm">
<small class="text-muted"><strong>ACTION</strong></small><br>
<input class="mt-2 switch" id="{{conf_data['name']}}" type="checkbox" data-toggle="toggle" {{conf_data['checked']}} data-size="sm">
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>STATUS</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['status']}}<span class="dot dot-{{conf_data['status']}}"></span></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>CONNECTED PEERS</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['running_peer']}}</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][0]}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL RECIEVED</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][1]}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL SENT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][2]}} GB</h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>PUBLIC KEY</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{conf_data['public_key']}}</samp></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>LISTEN PORT</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{conf_data['listen_port']}}</samp></h6>
</div>
</div>
<hr>
<div class="button-div" style="text-align: right;">
<button type="button" class="btn btn-outline-primary btn-sm mb-3" data-toggle="modal" data-target="#add_modal">
<strong>ADD PEER</strong>
</button>
</div>
</div>
{% for i in conf_data['peer_data']%}
<div class="card mb-3">
<div class="card-body">
<div class="row">
<div class="col-sm">
<small class="text-muted"><strong>STATUS</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['status']}}<span class="dot dot-{{conf_data['peer_data'][i]['status']}}"></span></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>PEER</strong></small>
<h6><samp>{{i}}</samp></h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>ALLOWED IP</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['allowed_ip']}}</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>LATEST HANDSHAKE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['latest_handshake']}}</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>END POINT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['endpoint']}}</h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_data']}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL RECIEVED</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_recive']}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL SENT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_sent']}} GB</h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<!-- <small class="text-muted"><strong>ACTION</strong></small> -->
<div class="button-group">
<button type="button" class="btn btn-outline-danger btn-sm btn-delete-peer" id="{{i}}" data-toggle="modal" data-target="#delete_modal"><span class="material-icons">delete_forever</span></button>
</div>
</div>
</div>
</div>
</div>
{%endfor%}
</main>
</div>
<div class="modal fade" id="add_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add a new peer</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div id="add_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form>
<div class="form-group">
<label for="public_key">Public Key</label>
<input type="text" class="form-control" id="public_key" aria-describedby="public_key">
</div>
<div class="form-group">
<label for="allowed_ips">Allowed IPs</label>
<input type="text" class="form-control" id="allowed_ips">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="save_peer" conf_id={{conf_data['name']}}>Save</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="delete_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Are you sure to delete this peer?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<h6>This action is not reversible.</h6>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}} peer_id="">Yes</button>
</div>
</div>
</div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script>
$('.switch').change(function() {
if ($(this).prop('checked') == false){
if (confirm('Are you sure you want to turn off this connection?')){
location.replace("/switch/"+$(this).attr('id'));
}
}
else{
location.replace("/switch/"+$(this).attr('id'));
}
});
$("#save_peer").click(function(){
if ($("#allowed_ips") != "" && $("#public_key") != ""){
var conf = $(this).attr('conf_id')
$.ajax({
method: "POST",
url: "/add_peer/"+conf,
headers:{
"Content-Type": "application/json"
},
data: JSON.stringify({"public_key":$("#public_key").val(), "allowed_ips": $("#allowed_ips").val()}),
success: function (response){
if(response != "true"){
$("#add_peer_alert").html(response+$("#add_peer_alert").html());
$("#add_peer_alert").removeClass("d-none");
}
else{
location.reload();
}
}
})
}
})
$(".btn-delete-peer").click(function(){
var peer_id = $(this).attr("id");
$("#delete_peer").attr("peer_id", peer_id);
});
$("#delete_peer").click(function(){
var peer_id = $(this).attr("peer_id");
var config = $(this).attr("conf_id");
$.ajax({
method: "POST",
url: "/remove_peer/"+config,
headers:{
"Content-Type": "application/json"
},
data: JSON.stringify({"action": "delete", "peer_id": peer_id}),
success: function (response){
if(response != "true"){
$("#remove_peer_alert").html(response+$("#add_peer_alert").html());
$("#remove_peer_alert").removeClass("d-none");
}
else{
location.reload();
}
}
})
});
// setInterval(function(){
// location.reload();
// }, 10000)
</script>
</html>

View File

@@ -6,6 +6,7 @@
<title>Wireguard Dashboard</title> <title>Wireguard Dashboard</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='dashboard.css') }}"> <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='dashboard.css') }}">
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
</head> </head>
<body> <body>
@@ -40,10 +41,19 @@
{% for i in conf%} {% for i in conf%}
<div class="card mt-3"> <div class="card mt-3">
<div class="card-body"> <div class="card-body">
<div class="row">
<div class="col">
<small class="text-muted"><strong>CONFIGURATION</strong></small>
<a href="/configuration/{{i['conf']}}"> <a href="/configuration/{{i['conf']}}">
<h5 class="card-title">{{i['conf']}}</h5> <h5 class="card-title">{{i['conf']}}</h5>
</a> </a>
<div class="row"> </div>
<div class="col">
<input class="mt-2 switch" id="{{i['conf']}}" type="checkbox" data-toggle="toggle" {{i['checked']}} data-size="sm">
</div>
<div class="w-100"></div>
<div class="col-sm"> <div class="col-sm">
<small class="text-muted"><strong>STATUS</strong></small> <small class="text-muted"><strong>STATUS</strong></small>
<h6 style="text-transform: uppercase;">{{i['status']}}<span class="dot dot-{{i['status']}}"></span></h6> <h6 style="text-transform: uppercase;">{{i['status']}}<span class="dot dot-{{i['status']}}"></span></h6>
@@ -52,6 +62,8 @@
<small class="text-muted"><strong>PUBLIC KEY</strong></small> <small class="text-muted"><strong>PUBLIC KEY</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{i['public_key']}}</samp></h6> <h6 style="text-transform: uppercase;"><samp>{{i['public_key']}}</samp></h6>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@@ -67,12 +79,17 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js" <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
crossorigin="anonymous"></script> crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script> <script>
// $.get("/get_conf", function(data, status){ $('.switch').change(function() {
// for (var i = 0; i < data['data'].length; i++){ if ($(this).prop('checked') == false){
// $(".nav").append('<li class="nav-item"><a class="nav-link" href="/conf/'+data['data'][i]['conf']+'">'+data['data'][i]['conf']+'</a></li>'); if (confirm('Are you sure you want to turn off this connection?')){
// $("main").append('<div class="card mt-3"><div class="card-body"><a href="/conf/'+data['data'][i]['conf']+'"><h5 class="card-title">'+data['data'][i]['conf']+'</h5></a><h6 class="card-subtitle mb-2 text-muted">Status: '+data['data'][i]['status']+'<span class="dot dot-'+data['data'][i]['status']+'"></span></h6></div></div>') location.replace("/switch/"+$(this).attr('id'))
// } }
// }); }
else{
location.replace("/switch/"+$(this).attr('id'))
}
});
</script> </script>
</html> </html>

4
src/test.py Normal file
View File

@@ -0,0 +1,4 @@
from tinydb import TinyDB, Query
conf_db = TinyDB("json/conf.json")
print(conf_db.all())

View File

@@ -1,133 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Wireguard Dashboard</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='dashboard.css') }}">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">Wireguard Dashboard</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse"
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
<div class="container-fluid">
<div class="row">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Configurations</span>
</h6>
<ul class="nav flex-column">
{% for i in conf%}
<li class="nav-item"><a class="nav-link" href="/configuration/{{i['conf']}}">{{i['conf']}}</a></li>
{%endfor%}
</ul>
</div>
</nav>
</div>
</div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4">
<div class="info mt-4">
<small class="text-muted"><strong>CONFIGURATION</strong></small>
<h1 class="mb-3">{{conf_data['name']}}</h1>
<div class="row">
<div class="col-sm">
<small class="text-muted"><strong>STATUS</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['status']}}<span class="dot dot-{{conf_data['status']}}"></span></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][0]}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL RECIEVED</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][1]}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL SENT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][2]}} GB</h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>PUBLIC KEY</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{conf_data['public_key']}}</samp></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>LISTEN PORT</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{conf_data['listen_port']}}</samp></h6>
</div>
</div>
<hr>
</div>
{% for i in conf_data['peer_data']%}
<div class="card mb-3">
<div class="card-body">
<div class="row">
<div class="col-sm">
<small class="text-muted"><strong>STATUS</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['status']}}<span class="dot dot-{{conf_data['peer_data'][i]['status']}}"></span></h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>PEER</strong></small>
<h6 style="text-transform: uppercase;"><samp>{{i}}</samp></h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>ALLOWED IP</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['allowed_ip']}}</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>LATEST HANDSHAKE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['latest_handshake']}}</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>END POINT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['endpoint']}}</h6>
</div>
<div class="w-100"></div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_data']}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL RECIEVED</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_recive']}} GB</h6>
</div>
<div class="col-sm">
<small class="text-muted"><strong>TOTAL SENT</strong></small>
<h6 style="text-transform: uppercase;">{{conf_data['peer_data'][i]['total_sent']}} GB</h6>
</div>
</div>
</div>
</div>
{%endfor%}
</main>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
crossorigin="anonymous"></script>
<script>
setInterval(function(){
location.reload();
},10000)
</script>
</html>

View File

@@ -1,5 +0,0 @@
import os
import subprocess
try: status = subprocess.check_output("wg show wg0", shell=True)
except Exception: print("false")
else:print(status.decode("UTF-8"))