Merge pull request #4 from donaldzou/v20210403-alpha

v20210403 Bug Fixed
This commit is contained in:
Donald Zou 2021-04-03 14:31:11 -04:00 committed by GitHub
commit 742191111b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 247 additions and 122 deletions

View File

@ -4,16 +4,20 @@ import subprocess
from datetime import datetime, date, time, timedelta from datetime import datetime, date, time, timedelta
from operator import itemgetter from operator import itemgetter
from tinydb import TinyDB, Query from tinydb import TinyDB, Query
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 = {} conf_data = {}
def get_conf_peer_key(config_name): def get_conf_peer_key(config_name):
keys = [] keys = []
try: peer_key = subprocess.check_output("wg show "+config_name+" peers", shell=True) try:
except Exception: return "stopped" peer_key = subprocess.check_output("wg show " + config_name + " peers", shell=True)
except Exception:
return "stopped"
peer_key = peer_key.decode("UTF-8").split() peer_key = peer_key.decode("UTF-8").split()
for i in peer_key: keys.append(i) for i in peer_key: keys.append(i)
return keys return keys
@ -22,8 +26,10 @@ def get_conf_peer_key(config_name):
def get_conf_running_peer_number(config_name): def get_conf_running_peer_number(config_name):
running = 0 running = 0
# Get latest handshakes # Get latest handshakes
try: data_usage = subprocess.check_output("wg show "+config_name+" latest-handshakes", shell=True) try:
except Exception: return "stopped" 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() data_usage = data_usage.decode("UTF-8").split()
count = 0 count = 0
now = datetime.now() now = datetime.now()
@ -35,14 +41,53 @@ def get_conf_running_peer_number(config_name):
count += 2 count += 2
return running return running
def get_conf_peers_data(config_name): def get_conf_peers_data(config_name):
db = TinyDB('db/' + config_name + '.json') db = TinyDB('db/' + config_name + '.json')
peers = Query() peers = Query()
peer_data = {} peer_data = {}
# Read Configuration File Start
conf_location = "/etc/wireguard/"+config_name+".conf"
f = open(conf_location, 'r')
file = f.read().split("\n")
conf_peer_data = {
"Interface": {},
"Peers": []
}
interface = []
peers_start = 0
for i in range(len(file)):
if file[i] == "[Peer]":
peers_start = i
break
else:
if len(file[i]) > 0:
if file[i] != "[Interface]":
tmp = file[i].replace(" ", "").split("=", 1)
if len(tmp) == 2:
conf_peer_data['Interface'][tmp[0]] = tmp[1]
conf_peers = file[peers_start:]
peer = -1
for i in conf_peers:
if i == "[Peer]":
peer += 1
conf_peer_data["Peers"].append({})
else:
if len(i) > 0:
tmp = i.replace(" ", "").split("=", 1)
if len(tmp) == 2:
conf_peer_data["Peers"][peer][tmp[0]] = tmp[1]
# Read Configuration File End
# Get key # Get key
try: peer_key = subprocess.check_output("wg show "+config_name+" peers", shell=True) try:
except Exception: return "stopped" peer_key = subprocess.check_output("wg show " + config_name + " peers", shell=True)
except Exception:
return "stopped"
peer_key = peer_key.decode("UTF-8").split() peer_key = peer_key.decode("UTF-8").split()
now = datetime.now()
current_time = now.strftime("%Y-%m-%d %H:%M:%S")
for i in peer_key: for i in peer_key:
peer_data[i] = {} peer_data[i] = {}
if not db.search(peers.id == i): if not db.search(peers.id == i):
@ -59,30 +104,32 @@ def get_conf_peers_data(config_name):
"traffic": [] "traffic": []
}) })
# Get transfer # Get transfer
try: data_usage = subprocess.check_output("wg show "+config_name+" transfer", shell=True) try:
except Exception: return "stopped" data_usage = subprocess.check_output("wg show " + config_name + " transfer", shell=True)
except Exception:
return "stopped"
data_usage = data_usage.decode("UTF-8").split() data_usage = data_usage.decode("UTF-8").split()
count = 0 count = 0
upload_total = 0
download_total = 0
total = 0
for i in range(int(len(data_usage) / 3)): for i in range(int(len(data_usage) / 3)):
db.update({"total_receive": round(int(data_usage[count + 1]) / (1024 ** 3), 4), db.update({"total_receive": round(int(data_usage[count + 1]) / (1024 ** 3), 4),
"total_sent": round(int(data_usage[count + 2]) / (1024 ** 3), 4), "total_sent": round(int(data_usage[count + 2]) / (1024 ** 3), 4),
"total_data": round((int(data_usage[count+2])+int(data_usage[count+1]))/(1024**3),4)}, peers.id == data_usage[count]) "total_data": round((int(data_usage[count + 2]) + int(data_usage[count + 1])) / (1024 ** 3), 4)},
peers.id == data_usage[count])
peer_data[data_usage[count]]['total_receive'] = round(int(data_usage[count + 1]) / (1024 ** 3), 4) peer_data[data_usage[count]]['total_receive'] = round(int(data_usage[count + 1]) / (1024 ** 3), 4)
peer_data[data_usage[count]]['total_sent'] = round(int(data_usage[count + 2]) / (1024 ** 3), 4) peer_data[data_usage[count]]['total_sent'] = round(int(data_usage[count + 2]) / (1024 ** 3), 4)
peer_data[data_usage[count]]['total_data'] = round((int(data_usage[count+2])+int(data_usage[count+1]))/(1024**3),4) peer_data[data_usage[count]]['total_data'] = round(
(int(data_usage[count + 2]) + int(data_usage[count + 1])) / (1024 ** 3), 4)
traffic = db.search(peers.id == data_usage[count])[0]['traffic']
traffic.append({"time": current_time, "total_receive": round(int(data_usage[count + 1]) / (1024 ** 3), 4),
"total_sent": round(int(data_usage[count + 2]) / (1024 ** 3), 4)})
db.update({"traffic": traffic}, peers.id == data_usage[count])
count += 3 count += 3
# Get endpoint # Get endpoint
try: data_usage = subprocess.check_output("wg show "+config_name+" endpoints", shell=True) try:
except Exception: return "stopped" data_usage = subprocess.check_output("wg show " + config_name + " endpoints", shell=True)
except Exception:
return "stopped"
data_usage = data_usage.decode("UTF-8").split() data_usage = data_usage.decode("UTF-8").split()
count = 0 count = 0
for i in range(int(len(data_usage) / 2)): for i in range(int(len(data_usage) / 2)):
@ -92,8 +139,10 @@ def get_conf_peers_data(config_name):
count += 2 count += 2
# Get latest handshakes # Get latest handshakes
try: data_usage = subprocess.check_output("wg show "+config_name+" latest-handshakes", shell=True) try:
except Exception: return "stopped" 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() data_usage = data_usage.decode("UTF-8").split()
count = 0 count = 0
now = datetime.now() now = datetime.now()
@ -113,36 +162,41 @@ def get_conf_peers_data(config_name):
count += 2 count += 2
# Get allowed ip # Get allowed ip
try: data_usage = subprocess.check_output("wg show "+config_name+" allowed-ips", shell=True) for i in conf_peer_data["Peers"]:
except Exception: return "stopped" db.update({"allowed_ip":i['AllowedIPs']}, peers.id == i["PublicKey"])
data_usage = data_usage.decode("UTF-8").split()
count = 0
for i in range(int(len(data_usage)/2)):
db.update({"allowed_ip": data_usage[count+1]}, peers.id == data_usage[count])
peer_data[data_usage[count]]['allowed_ip'] = data_usage[count+1]
count += 2
def getdb(config_name):
get_conf_peers_data(config_name)
db = TinyDB('db/' + config_name + '.json')
result = db.all() result = db.all()
result = sorted(result, key=lambda d: d['status']) result = sorted(result, key=lambda d: d['status'])
return result return result
def get_conf_pub_key(config_name): def get_conf_pub_key(config_name):
try: pub_key = subprocess.check_output("wg show "+config_name+" public-key", shell=True, stderr=subprocess.STDOUT) try:
except Exception: return "stopped" pub_key = subprocess.check_output("wg show " + config_name + " public-key", shell=True,
stderr=subprocess.STDOUT)
except Exception:
return "stopped"
return pub_key.decode("UTF-8") return pub_key.decode("UTF-8")
def get_conf_listen_port(config_name): def get_conf_listen_port(config_name):
try: pub_key = subprocess.check_output("wg show "+config_name+" listen-port", shell=True, stderr=subprocess.STDOUT) try:
except Exception: return "stopped" pub_key = subprocess.check_output("wg show " + config_name + " listen-port", shell=True,
stderr=subprocess.STDOUT)
except Exception:
return "stopped"
return pub_key.decode("UTF-8") return pub_key.decode("UTF-8")
def get_conf_total_data(config_name): def get_conf_total_data(config_name):
try: data_usage = subprocess.check_output("wg show "+config_name+" transfer", shell=True, stderr=subprocess.STDOUT) try:
except Exception: return "stopped" data_usage = subprocess.check_output("wg show " + config_name + " transfer", shell=True,
stderr=subprocess.STDOUT)
except Exception:
return "stopped"
data_usage = data_usage.decode("UTF-8").split() data_usage = data_usage.decode("UTF-8").split()
count = 0 count = 0
upload_total = 0 upload_total = 0
@ -161,9 +215,12 @@ def get_conf_total_data(config_name):
def get_conf_status(config_name): def get_conf_status(config_name):
try: status = subprocess.check_output("wg show "+config_name, shell=True, stderr=subprocess.STDOUT) try:
except Exception: return "stopped" status = subprocess.check_output("wg show " + config_name, shell=True, stderr=subprocess.STDOUT)
else: return "running" except Exception:
return "stopped"
else:
return "running"
def get_conf_list(): def get_conf_list():
@ -174,11 +231,24 @@ def get_conf_list():
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": if temp['status'] == "running":
temp['checked'] = 'checked' temp['checked'] = 'checked'
else: temp['checked'] = "" else:
temp['checked'] = ""
conf.append(temp) conf.append(temp)
conf = sorted(conf, key=itemgetter('status')) conf = sorted(conf, key=itemgetter('status'))
return conf return conf
def get_running_conf_list():
conf = []
for i in os.listdir(conf_location):
if ".conf" in i:
i = i.replace('.conf', '')
if get_conf_status(i) == "running":
conf.append(i)
return conf
@app.route('/', methods=['GET']) @app.route('/', methods=['GET'])
def index(): def index():
return render_template('index.html', conf=get_conf_list()) return render_template('index.html', conf=get_conf_list())
@ -197,6 +267,7 @@ def conf(config_name):
conf_data['checked'] = "checked" 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('/get_config/<config_name>', methods=['GET']) @app.route('/get_config/<config_name>', methods=['GET'])
def get_conf(config_name): def get_conf(config_name):
db = TinyDB('db/' + config_name + '.json') db = TinyDB('db/' + config_name + '.json')
@ -207,7 +278,7 @@ def get_conf(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": getdb(config_name),
"running_peer": get_conf_running_peer_number(config_name), "running_peer": get_conf_running_peer_number(config_name),
} }
if conf_data['status'] == "stopped": if conf_data['status'] == "stopped":
@ -221,11 +292,15 @@ def get_conf(config_name):
def switch(config_name): def switch(config_name):
status = get_conf_status(config_name) status = get_conf_status(config_name)
if status == "running": if status == "running":
try: status = subprocess.check_output("wg-quick down "+config_name, shell=True) try:
except Exception: return redirect('/') status = subprocess.check_output("wg-quick down " + config_name, shell=True)
except Exception:
return redirect('/')
elif status == "stopped": elif status == "stopped":
try: status = subprocess.check_output("wg-quick up "+config_name, shell=True) try:
except Exception: return redirect('/') status = subprocess.check_output("wg-quick up " + config_name, shell=True)
except Exception:
return redirect('/')
return redirect('/') return redirect('/')
@ -240,7 +315,9 @@ def add_peer(config_name):
else: else:
status = "" status = ""
try: 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 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) status = subprocess.check_output("wg-quick save " + config_name, shell=True, stderr=subprocess.STDOUT)
return "true" return "true"
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
@ -248,6 +325,7 @@ def add_peer(config_name):
# return redirect('/configuration/'+config_name) # return redirect('/configuration/'+config_name)
@app.route('/remove_peer/<config_name>', methods=['POST']) @app.route('/remove_peer/<config_name>', methods=['POST'])
def remove_peer(config_name): def remove_peer(config_name):
db = TinyDB("db/" + config_name + ".json") db = TinyDB("db/" + config_name + ".json")
@ -259,13 +337,15 @@ def remove_peer(config_name):
return "This key does not exist" return "This key does not exist"
else: else:
try: try:
status = subprocess.check_output("wg set "+config_name+" peer "+delete_key+" remove", shell=True, stderr=subprocess.STDOUT) 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) status = subprocess.check_output("wg-quick save " + config_name, shell=True, stderr=subprocess.STDOUT)
db.remove(peers.id == delete_key) db.remove(peers.id == delete_key)
return "true" return "true"
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
return exc.output.strip() return exc.output.strip()
@app.route('/save_peer_name/<config_name>', methods=['POST']) @app.route('/save_peer_name/<config_name>', methods=['POST'])
def save_peer_name(config_name): def save_peer_name(config_name):
data = request.get_json() data = request.get_json()
@ -277,6 +357,7 @@ def save_peer_name(config_name):
db.update({"name": name}, peers.id == id) db.update({"name": name}, peers.id == id)
return id + " " + name return id + " " + name
@app.route('/get_peer_name/<config_name>', methods=['POST']) @app.route('/get_peer_name/<config_name>', methods=['POST'])
def get_peer_name(config_name): def get_peer_name(config_name):
data = request.get_json() data = request.get_json()
@ -287,9 +368,8 @@ def get_peer_name(config_name):
return result[0]['name'] return result[0]['name']
# db.update({"name": name}, peers.id == id) # db.update({"name": name}, peers.id == id)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=False, port=10086) app.run(host='0.0.0.0', debug=False, port=10086)
# for i in get_running_conf_list():
# p = Process(target=get_conf_peers_data, args=(i,))
# p.start()

View File

@ -9,6 +9,7 @@
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet"> <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"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.0.1/dist/chart.min.js"></script>
</head> </head>
<body> <body>
@ -171,7 +172,7 @@
load_data(); load_data();
setInterval(function(){ setInterval(function(){
load_data(); load_data();
}, 10000) }, 15000)
}); });
</script> </script>
<script> <script>

View File

@ -52,29 +52,42 @@
{% for i in conf_data['peer_data']%} {% for i in conf_data['peer_data']%}
<div class="card mb-3"> <div class="card mb-3">
<div class="card-header"> <div class="card-header">
<div class="row">
<div class="col">
<div class="card-header-body ">
{% if not i['name']%} {% if not i['name']%}
{{ "Untitled Peer" }} {{ "Untitled Peer" }}
{% else %} {% else %}
{{i['name']}} {{i['name']}}
{% endif %} {% endif %}
<span class="dot dot-{{i['status']}}"></span>
</div>
</div>
<div class="col" style="text-align: right">
<p class="text-primary" style="text-transform: uppercase; display: inline-block; margin-bottom: 0; margin-right: 1rem"><i class="bi bi-arrow-down-right"></i> {{i['total_receive']}} GB</p>
<p class="text-success" style="text-transform: uppercase; display: inline-block; margin-bottom: 0"><i class="bi bi-arrow-up-right"></i> {{i['total_sent']}} GB</p>
</div>
</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<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>#}
</div> {# </div>#}
<div class="col-sm"> <div class="col-sm">
<small class="text-muted"><strong>PEER</strong></small> <small class="text-muted"><strong>PEER</strong></small>
<h6><samp>{{i['id']}}</samp></h6> <h6><samp class="ml-auto">{{i['id']}}</samp></h6>
</div> </div>
<div class="w-100"></div>
<div class="col-sm"> <div class="col-sm">
<small class="text-muted"><strong>ALLOWED IP</strong></small> <small class="text-muted"><strong>ALLOWED IP</strong></small>
<h6 style="text-transform: uppercase;">{{i['allowed_ip']}}</h6> <h6 style="text-transform: uppercase;">{{i['allowed_ip']}}</h6>
</div> </div>
<div class="w-100"></div>
<div class="col-sm"> <div class="col-sm">
<small class="text-muted"><strong>LATEST HANDSHAKE</strong></small> <small class="text-muted"><strong>LATEST HANDSHAKE</strong></small>
<h6 style="text-transform: uppercase;">{{i['latest_handshake']}}</h6> <h6 style="text-transform: uppercase;">{{i['latest_handshake']}}</h6>
@ -83,19 +96,50 @@
<small class="text-muted"><strong>END POINT</strong></small> <small class="text-muted"><strong>END POINT</strong></small>
<h6 style="text-transform: uppercase;">{{i['endpoint']}}</h6> <h6 style="text-transform: uppercase;">{{i['endpoint']}}</h6>
</div> </div>
<div class="w-100"></div> {# <div class="w-100"></div>#}
{# <div class="col-sm">#} {# <div class="col-sm">#}
{# <small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>#} {# <canvas id="{{ i['id'] }}_chart" style="width: 100%" height="200"></canvas>#}
{# <h6 style="text-transform: uppercase;">{{i['total_data']}} GB</h6>#}
{# </div>#} {# </div>#}
<div class="col-sm"> {# <script>#}
<small class="text-muted"><strong>TOTAL RECEIVED</strong></small> {# var data = "{{ i['traffic'] }}";#}
<h6 style="text-transform: uppercase;"><i class="bi bi-arrow-down-right"></i> {{i['total_receive']}} GB</h6> {# data = data.replaceAll("&#39;", "\"")#}
</div> {# data = JSON.parse(data)#}
<div class="col-sm"> {# y_label = [];#}
<small class="text-muted"><strong>TOTAL SENT</strong></small> {# data_point = [];#}
<h6 style="text-transform: uppercase;"><i class="bi bi-arrow-up-right"></i> {{i['total_sent']}} GB</h6> {# for (var i = 1; i < data.length; i++){#}
</div> {# y_label.push(data[i]['time'])#}
{# data_point.push(data[i]['total_sent'] - data[i-1]['total_sent']);#}
{# }#}
{# var ctx = document.getElementById('{{ i['id'] }}_chart');#}
{# var plot_data =#}
{# {#}
{# labels: y_label,#}
{# datasets:[{#}
{# label: "Traffic",#}
{# data: data_point,#}
{# fill: false,#}
{# borderColor: 'rgb(75, 192, 192)',#}
{# tension: 0.1#}
{# }],#}
{# options: {#}
{# scales: {#}
{# xAxes: [{#}
{# type: 'time',#}
{# ticks: {#}
{# autoSkip: true,#}
{# maxTicksLimit: 12#}
{# }#}
{# }]#}
{# },#}
{# responsive: true#}
{# }#}
{# }#}
{##}
{# var myLineChart = new Chart(ctx, {#}
{# type: 'line',#}
{# data: plot_data#}
{# });#}
{# </script>#}
<div class="w-100"></div> <div class="w-100"></div>
<div class="col-sm"> <div class="col-sm">
<!-- <small class="text-muted"><strong>ACTION</strong></small> --> <!-- <small class="text-muted"><strong>ACTION</strong></small> -->