mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-10-01 09:00:13 +02:00
Merge branch 'main' into change-path
# Conflicts: # src/dashboard.py
This commit is contained in:
commit
344770a0a4
229
src/dashboard.py
229
src/dashboard.py
@ -3,10 +3,10 @@
|
|||||||
Under Apache-2.0 License
|
Under Apache-2.0 License
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Import other python files
|
||||||
|
from util import *
|
||||||
# Python Built-in Library
|
# Python Built-in Library
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from flask import Flask, request, render_template, redirect, url_for, session, abort, jsonify
|
from flask import Flask, request, render_template, redirect, url_for, session, abort, jsonify
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime, date, time, timedelta
|
from datetime import datetime, date, time, timedelta
|
||||||
@ -17,10 +17,15 @@ import hashlib
|
|||||||
import json, urllib.request
|
import json, urllib.request
|
||||||
import configparser
|
import configparser
|
||||||
import re
|
import re
|
||||||
|
import ipaddress
|
||||||
|
import sqlite3
|
||||||
|
import threading
|
||||||
# PIP installed library
|
# PIP installed library
|
||||||
import ifcfg
|
import ifcfg
|
||||||
from flask_qrcode import QRcode
|
from flask_qrcode import QRcode
|
||||||
from tinydb import TinyDB, Query
|
from tinydb import TinyDB, Query
|
||||||
|
from tinydb.storages import JSONStorage
|
||||||
|
from tinydb.middlewares import CachingMiddleware
|
||||||
from icmplib import ping, multiping, traceroute, resolve, Host, Hop
|
from icmplib import ping, multiping, traceroute, resolve, Host, Hop
|
||||||
# Dashboard Version
|
# Dashboard Version
|
||||||
dashboard_version = 'v3.0'
|
dashboard_version = 'v3.0'
|
||||||
@ -34,81 +39,14 @@ dashboard_conf = os.path.join(configuration_path, 'wg-dashboard.ini')
|
|||||||
update = ""
|
update = ""
|
||||||
# Flask App Configuration
|
# Flask App Configuration
|
||||||
app = Flask("WGDashboard")
|
app = Flask("WGDashboard")
|
||||||
|
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
||||||
app.secret_key = secrets.token_urlsafe(16)
|
app.secret_key = secrets.token_urlsafe(16)
|
||||||
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||||
# Enable QR Code Generator
|
# Enable QR Code Generator
|
||||||
QRcode(app)
|
QRcode(app)
|
||||||
|
|
||||||
"""
|
# TODO: Testing semaphore on reading/writing database
|
||||||
Helper Functions
|
sem = threading.RLock()
|
||||||
"""
|
|
||||||
# Regex Match
|
|
||||||
def regex_match(regex, text):
|
|
||||||
pattern = re.compile(regex)
|
|
||||||
return pattern.search(text) is not None
|
|
||||||
|
|
||||||
# Check IP format
|
|
||||||
def check_IP(ip):
|
|
||||||
ip_patterns = (
|
|
||||||
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}",
|
|
||||||
r"[0-9a-fA-F]{0,4}(:([0-9a-fA-F]{0,4})){1,7}$"
|
|
||||||
)
|
|
||||||
|
|
||||||
for match_pattern in ip_patterns:
|
|
||||||
match_result = regex_match(match_pattern, ip)
|
|
||||||
if match_result:
|
|
||||||
result = match_result
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
result = None
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Clean IP
|
|
||||||
def clean_IP(ip):
|
|
||||||
return ip.replace(' ', '')
|
|
||||||
|
|
||||||
# Clean IP with range
|
|
||||||
def clean_IP_with_range(ip):
|
|
||||||
return clean_IP(ip).split(',')
|
|
||||||
|
|
||||||
# Check IP with range
|
|
||||||
def check_IP_with_range(ip):
|
|
||||||
ip_patterns = (
|
|
||||||
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|\/)){4}([0-9]{1,2})(,|$)",
|
|
||||||
r"[0-9a-fA-F]{0,4}(:([0-9a-fA-F]{0,4})){1,7}\/([0-9]{1,3})(,|$)"
|
|
||||||
)
|
|
||||||
|
|
||||||
for match_pattern in ip_patterns:
|
|
||||||
match_result = regex_match(match_pattern, ip)
|
|
||||||
if match_result:
|
|
||||||
result = match_result
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
result = None
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Check allowed ips list
|
|
||||||
def check_Allowed_IPs(ip):
|
|
||||||
ip = clean_IP_with_range(ip)
|
|
||||||
for i in ip:
|
|
||||||
if not check_IP_with_range(i): return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check DNS
|
|
||||||
def check_DNS(dns):
|
|
||||||
dns = dns.replace(' ','').split(',')
|
|
||||||
status = True
|
|
||||||
for i in dns:
|
|
||||||
if not (check_IP(i) or regex_match("(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z]{0,61}[a-z]",i)):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check remote endpoint
|
|
||||||
def check_remote_endpoint(address):
|
|
||||||
|
|
||||||
return (check_IP(address) or regex_match("(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z]{0,61}[a-z]", address))
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -289,7 +227,10 @@ def get_allowed_ip(config_name, db, peers, conf_peer_data):
|
|||||||
|
|
||||||
# Look for new peers from WireGuard
|
# Look for new peers from WireGuard
|
||||||
def get_all_peers_data(config_name):
|
def get_all_peers_data(config_name):
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + '.json'))
|
db = TinyDB(os.path.join(db_path, config_name + '.json'))
|
||||||
|
|
||||||
peers = Query()
|
peers = Query()
|
||||||
conf_peer_data = read_conf_file(config_name)
|
conf_peer_data = read_conf_file(config_name)
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -346,6 +287,7 @@ def get_all_peers_data(config_name):
|
|||||||
toc = time.perf_counter()
|
toc = time.perf_counter()
|
||||||
print(f"Finish fetching data in {toc - tic:0.4f} seconds")
|
print(f"Finish fetching data in {toc - tic:0.4f} seconds")
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Frontend Related Functions
|
Frontend Related Functions
|
||||||
@ -353,14 +295,20 @@ Frontend Related Functions
|
|||||||
# Search for peers
|
# Search for peers
|
||||||
def get_peers(config_name, search, sort_t):
|
def get_peers(config_name, search, sort_t):
|
||||||
get_all_peers_data(config_name)
|
get_all_peers_data(config_name)
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peer = Query()
|
peer = Query()
|
||||||
if len(search) == 0:
|
if len(search) == 0:
|
||||||
result = db.all()
|
result = db.all()
|
||||||
else:
|
else:
|
||||||
result = db.search(peer.name.matches('(.*)(' + re.escape(search) + ')(.*)'))
|
result = db.search(peer.name.matches('(.*)(' + re.escape(search) + ')(.*)'))
|
||||||
result = sorted(result, key=lambda d: d[sort_t])
|
if sort_t == "allowed_ip":
|
||||||
|
result = sorted(result, key = lambda d: ipaddress.ip_network(d[sort_t].split(",")[0]))
|
||||||
|
else:
|
||||||
|
result = sorted(result, key=lambda d: d[sort_t])
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -391,6 +339,8 @@ def get_conf_listen_port(config_name):
|
|||||||
|
|
||||||
# Get configuration total data
|
# Get configuration total data
|
||||||
def get_conf_total_data(config_name):
|
def get_conf_total_data(config_name):
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
upload_total = 0
|
upload_total = 0
|
||||||
download_total = 0
|
download_total = 0
|
||||||
@ -404,6 +354,7 @@ def get_conf_total_data(config_name):
|
|||||||
upload_total = round(upload_total, 4)
|
upload_total = round(upload_total, 4)
|
||||||
download_total = round(download_total, 4)
|
download_total = round(download_total, 4)
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return [total, upload_total, download_total]
|
return [total, upload_total, download_total]
|
||||||
|
|
||||||
# Get configuration status
|
# Get configuration status
|
||||||
@ -467,17 +418,27 @@ def checkKeyMatch(private_key, public_key, config_name):
|
|||||||
if result['status'] == 'failed':
|
if result['status'] == 'failed':
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
match = db.search(peers.id == result['data'])
|
match = db.search(peers.id == result['data'])
|
||||||
if len(match) != 1 or result['data'] != public_key:
|
if len(match) != 1 or result['data'] != public_key:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return {'status': 'failed', 'msg': 'Please check your private key, it does not match with the public key.'}
|
return {'status': 'failed', 'msg': 'Please check your private key, it does not match with the public key.'}
|
||||||
else:
|
else:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return {'status': 'success'}
|
return {'status': 'success'}
|
||||||
|
|
||||||
# Check if there is repeated allowed IP
|
# Check if there is repeated allowed IP
|
||||||
def check_repeat_allowed_IP(public_key, ip, config_name):
|
def check_repeat_allowed_IP(public_key, ip, config_name):
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
|
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
|
db = TinyDB('db/' + config_name + '.json')
|
||||||
peers = Query()
|
peers = Query()
|
||||||
peer = db.search(peers.id == public_key)
|
peer = db.search(peers.id == public_key)
|
||||||
if len(peer) != 1:
|
if len(peer) != 1:
|
||||||
@ -485,8 +446,12 @@ def check_repeat_allowed_IP(public_key, ip, config_name):
|
|||||||
else:
|
else:
|
||||||
existed_ip = db.search((peers.id != public_key) & (peers.allowed_ip == ip))
|
existed_ip = db.search((peers.id != public_key) & (peers.allowed_ip == ip))
|
||||||
if len(existed_ip) != 0:
|
if len(existed_ip) != 0:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return {'status': 'failed', 'msg': "Allowed IP already taken by another peer."}
|
return {'status': 'failed', 'msg': "Allowed IP already taken by another peer."}
|
||||||
else:
|
else:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return {'status': 'success'}
|
return {'status': 'success'}
|
||||||
|
|
||||||
|
|
||||||
@ -497,6 +462,7 @@ Flask Functions
|
|||||||
# Before request
|
# Before request
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def auth_req():
|
def auth_req():
|
||||||
|
|
||||||
conf = configparser.ConfigParser(strict=False)
|
conf = configparser.ConfigParser(strict=False)
|
||||||
conf.read(dashboard_conf)
|
conf.read(dashboard_conf)
|
||||||
req = conf.get("Server", "auth_req")
|
req = conf.get("Server", "auth_req")
|
||||||
@ -844,6 +810,8 @@ def switch(config_name):
|
|||||||
# Add peer
|
# Add peer
|
||||||
@app.route('/add_peer/<config_name>', methods=['POST'])
|
@app.route('/add_peer/<config_name>', methods=['POST'])
|
||||||
def add_peer(config_name):
|
def add_peer(config_name):
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -853,26 +821,42 @@ def add_peer(config_name):
|
|||||||
DNS = data['DNS']
|
DNS = data['DNS']
|
||||||
keys = get_conf_peer_key(config_name)
|
keys = get_conf_peer_key(config_name)
|
||||||
if len(public_key) == 0 or len(DNS) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0:
|
if len(public_key) == 0 or len(DNS) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "Please fill in all required box."
|
return "Please fill in all required box."
|
||||||
if type(keys) != list:
|
if type(keys) != list:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return config_name + " is not running."
|
return config_name + " is not running."
|
||||||
if public_key in keys:
|
if public_key in keys:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "Public key already exist."
|
return "Public key already exist."
|
||||||
if len(db.search(peers.allowed_ip.matches(allowed_ips))) != 0:
|
if len(db.search(peers.allowed_ip.matches(allowed_ips))) != 0:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "Allowed IP already taken by another peer."
|
return "Allowed IP already taken by another peer."
|
||||||
if not check_DNS(DNS):
|
if not check_DNS(DNS):
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "DNS formate is incorrect. Example: 1.1.1.1"
|
return "DNS formate is incorrect. Example: 1.1.1.1"
|
||||||
if not check_Allowed_IPs(endpoint_allowed_ip):
|
if not check_Allowed_IPs(endpoint_allowed_ip):
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "Endpoint Allowed IPs format is incorrect."
|
return "Endpoint Allowed IPs format is incorrect."
|
||||||
if len(data['MTU']) != 0:
|
if len(data['MTU']) != 0:
|
||||||
try:
|
try:
|
||||||
mtu = int(data['MTU'])
|
mtu = int(data['MTU'])
|
||||||
except:
|
except:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "MTU format is not correct."
|
return "MTU format is not correct."
|
||||||
if len(data['keep_alive']) != 0:
|
if len(data['keep_alive']) != 0:
|
||||||
try:
|
try:
|
||||||
keep_alive = int(data['keep_alive'])
|
keep_alive = int(data['keep_alive'])
|
||||||
except:
|
except:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "Persistent Keepalive format is not correct."
|
return "Persistent Keepalive format is not correct."
|
||||||
try:
|
try:
|
||||||
status = subprocess.check_output(
|
status = subprocess.check_output(
|
||||||
@ -884,9 +868,11 @@ def add_peer(config_name):
|
|||||||
"endpoint_allowed_ip": endpoint_allowed_ip},
|
"endpoint_allowed_ip": endpoint_allowed_ip},
|
||||||
peers.id == public_key)
|
peers.id == public_key)
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "true"
|
return "true"
|
||||||
except subprocess.CalledProcessError as exc:
|
except subprocess.CalledProcessError as exc:
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return exc.output.strip()
|
return exc.output.strip()
|
||||||
|
|
||||||
# Remove peer
|
# Remove peer
|
||||||
@ -894,6 +880,8 @@ def add_peer(config_name):
|
|||||||
def remove_peer(config_name):
|
def remove_peer(config_name):
|
||||||
if get_conf_status(config_name) == "stopped":
|
if get_conf_status(config_name) == "stopped":
|
||||||
return "Your need to turn on " + config_name + " first."
|
return "Your need to turn on " + config_name + " first."
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -911,8 +899,11 @@ def remove_peer(config_name):
|
|||||||
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)
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return "true"
|
return "true"
|
||||||
except subprocess.CalledProcessError as exc:
|
except subprocess.CalledProcessError as exc:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return exc.output.strip()
|
return exc.output.strip()
|
||||||
|
|
||||||
# Save peer settings
|
# Save peer settings
|
||||||
@ -925,37 +916,55 @@ def save_peer_setting(config_name):
|
|||||||
DNS = data['DNS']
|
DNS = data['DNS']
|
||||||
allowed_ip = data['allowed_ip']
|
allowed_ip = data['allowed_ip']
|
||||||
endpoint_allowed_ip = data['endpoint_allowed_ip']
|
endpoint_allowed_ip = data['endpoint_allowed_ip']
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
if len(db.search(peers.id == id)) == 1:
|
if len(db.search(peers.id == id)) == 1:
|
||||||
check_ip = check_repeat_allowed_IP(id, allowed_ip, config_name)
|
check_ip = check_repeat_allowed_IP(id, allowed_ip, config_name)
|
||||||
if not check_IP_with_range(endpoint_allowed_ip):
|
if not check_IP_with_range(endpoint_allowed_ip):
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": "Endpoint Allowed IPs format is incorrect."})
|
return jsonify({"status": "failed", "msg": "Endpoint Allowed IPs format is incorrect."})
|
||||||
if not check_DNS(DNS):
|
if not check_DNS(DNS):
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": "DNS format is incorrect."})
|
return jsonify({"status": "failed", "msg": "DNS format is incorrect."})
|
||||||
if len(data['MTU']) != 0:
|
if len(data['MTU']) != 0:
|
||||||
try:
|
try:
|
||||||
mtu = int(data['MTU'])
|
mtu = int(data['MTU'])
|
||||||
except:
|
except:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": "MTU format is not correct."})
|
return jsonify({"status": "failed", "msg": "MTU format is not correct."})
|
||||||
if len(data['keep_alive']) != 0:
|
if len(data['keep_alive']) != 0:
|
||||||
try:
|
try:
|
||||||
keep_alive = int(data['keep_alive'])
|
keep_alive = int(data['keep_alive'])
|
||||||
except:
|
except:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": "Persistent Keepalive format is not correct."})
|
return jsonify({"status": "failed", "msg": "Persistent Keepalive format is not correct."})
|
||||||
if private_key != "":
|
if private_key != "":
|
||||||
check_key = checkKeyMatch(private_key, id, config_name)
|
check_key = checkKeyMatch(private_key, id, config_name)
|
||||||
if check_key['status'] == "failed":
|
if check_key['status'] == "failed":
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify(check_key)
|
return jsonify(check_key)
|
||||||
if check_ip['status'] == "failed":
|
if check_ip['status'] == "failed":
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify(check_ip)
|
return jsonify(check_ip)
|
||||||
try:
|
try:
|
||||||
if allowed_ip == "": allowed_ip = '""'
|
if allowed_ip == "":
|
||||||
|
allowed_ip = '""'
|
||||||
|
allowed_ip = allowed_ip.replace(" ", "")
|
||||||
change_ip = subprocess.check_output('wg set ' + config_name + " peer " + id + " allowed-ips " + allowed_ip,
|
change_ip = subprocess.check_output('wg set ' + config_name + " peer " + id + " allowed-ips " + allowed_ip,
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
shell=True, stderr=subprocess.STDOUT)
|
||||||
save_change_ip = subprocess.check_output('wg-quick save ' + config_name, shell=True,
|
save_change_ip = subprocess.check_output('wg-quick save ' + config_name, shell=True,
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
if change_ip.decode("UTF-8") != "":
|
if change_ip.decode("UTF-8") != "":
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": change_ip.decode("UTF-8")})
|
return jsonify({"status": "failed", "msg": change_ip.decode("UTF-8")})
|
||||||
db.update(
|
db.update(
|
||||||
{"name": name, "private_key": private_key,
|
{"name": name, "private_key": private_key,
|
||||||
@ -964,10 +973,15 @@ def save_peer_setting(config_name):
|
|||||||
"keepalive":data['keep_alive']},
|
"keepalive":data['keep_alive']},
|
||||||
peers.id == id)
|
peers.id == id)
|
||||||
db.close()
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "success", "msg": ""})
|
return jsonify({"status": "success", "msg": ""})
|
||||||
except subprocess.CalledProcessError as exc:
|
except subprocess.CalledProcessError as exc:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": str(exc.output.decode("UTF-8").strip())})
|
return jsonify({"status": "failed", "msg": str(exc.output.decode("UTF-8").strip())})
|
||||||
else:
|
else:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return jsonify({"status": "failed", "msg": "This peer does not exist."})
|
return jsonify({"status": "failed", "msg": "This peer does not exist."})
|
||||||
|
|
||||||
# Get peer settings
|
# Get peer settings
|
||||||
@ -975,6 +989,8 @@ def save_peer_setting(config_name):
|
|||||||
def get_peer_name(config_name):
|
def get_peer_name(config_name):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
id = data['id']
|
id = data['id']
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
result = db.search(peers.id == id)
|
result = db.search(peers.id == id)
|
||||||
@ -982,6 +998,7 @@ def get_peer_name(config_name):
|
|||||||
data = {"name": result[0]['name'], "allowed_ip": result[0]['allowed_ip'], "DNS": result[0]['DNS'],
|
data = {"name": result[0]['name'], "allowed_ip": result[0]['allowed_ip'], "DNS": result[0]['DNS'],
|
||||||
"private_key": result[0]['private_key'], "endpoint_allowed_ip": result[0]['endpoint_allowed_ip'],
|
"private_key": result[0]['private_key'], "endpoint_allowed_ip": result[0]['endpoint_allowed_ip'],
|
||||||
"mtu": result[0]['mtu'], "keep_alive": result[0]['keepalive']}
|
"mtu": result[0]['mtu'], "keep_alive": result[0]['keepalive']}
|
||||||
|
sem.release()
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
# Generate a private key
|
# Generate a private key
|
||||||
@ -1004,11 +1021,52 @@ def check_key_match(config_name):
|
|||||||
public_key = data['public_key']
|
public_key = data['public_key']
|
||||||
return jsonify(checkKeyMatch(private_key, public_key, config_name))
|
return jsonify(checkKeyMatch(private_key, public_key, config_name))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/qrcode/<config_name>", methods=['GET'])
|
||||||
|
def generate_qrcode(config_name):
|
||||||
|
id = request.args.get('id')
|
||||||
|
sem.acquire()
|
||||||
|
db = TinyDB('db/' + config_name + '.json')
|
||||||
|
peers = Query()
|
||||||
|
get_peer = db.search(peers.id == id)
|
||||||
|
config = get_dashboard_conf()
|
||||||
|
if len(get_peer) == 1:
|
||||||
|
peer = get_peer[0]
|
||||||
|
if peer['private_key'] != "":
|
||||||
|
public_key = get_conf_pub_key(config_name)
|
||||||
|
listen_port = get_conf_listen_port(config_name)
|
||||||
|
endpoint = config.get("Peers", "remote_endpoint") + ":" + listen_port
|
||||||
|
private_key = peer['private_key']
|
||||||
|
allowed_ip = peer['allowed_ip']
|
||||||
|
DNS = peer['DNS']
|
||||||
|
MTU = peer['mtu']
|
||||||
|
endpoint_allowed_ip = peer['endpoint_allowed_ip']
|
||||||
|
keepalive = peer['keepalive']
|
||||||
|
conf = {
|
||||||
|
"public_key": public_key,
|
||||||
|
"listen_port": listen_port,
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"private_key": private_key,
|
||||||
|
"allowed_ip": allowed_ip,
|
||||||
|
"DNS": DNS,
|
||||||
|
"mtu": MTU,
|
||||||
|
"endpoint_allowed_ip": endpoint_allowed_ip,
|
||||||
|
"keepalive": keepalive,
|
||||||
|
}
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
|
return render_template("qrcode.html", i=conf)
|
||||||
|
else:
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
|
return redirect("/configuration/" + config_name)
|
||||||
# Download configuration file
|
# Download configuration file
|
||||||
@app.route('/download/<config_name>', methods=['GET'])
|
@app.route('/<config_name>', methods=['GET'])
|
||||||
def download(config_name):
|
def download(config_name):
|
||||||
print(request.headers.get('User-Agent'))
|
print(request.headers.get('User-Agent'))
|
||||||
id = request.args.get('id')
|
id = request.args.get('id')
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
db = TinyDB(os.path.join(db_path, config_name + ".json"))
|
||||||
peers = Query()
|
peers = Query()
|
||||||
get_peer = db.search(peers.id == id)
|
get_peer = db.search(peers.id == id)
|
||||||
@ -1043,11 +1101,13 @@ def download(config_name):
|
|||||||
|
|
||||||
def generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive):
|
def generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive):
|
||||||
yield "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + DNS + "\nMTU = " + MTU + "\n\n[Peer]\nPublicKey = " + public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + endpoint+ "\nPersistentKeepalive = " + keepalive
|
yield "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + DNS + "\nMTU = " + MTU + "\n\n[Peer]\nPublicKey = " + public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + endpoint+ "\nPersistentKeepalive = " + keepalive
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return app.response_class(generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive),
|
return app.response_class(generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive),
|
||||||
mimetype='text/conf',
|
mimetype='text/conf',
|
||||||
headers={"Content-Disposition": "attachment;filename=" + filename + ".conf"})
|
headers={"Content-Disposition": "attachment;filename=" + filename + ".conf"})
|
||||||
else:
|
else:
|
||||||
|
db.close()
|
||||||
return redirect("/configuration/" + config_name)
|
return redirect("/configuration/" + config_name)
|
||||||
|
|
||||||
# Switch peer displate mode
|
# Switch peer displate mode
|
||||||
@ -1069,6 +1129,8 @@ Dashboard Tools Related
|
|||||||
@app.route('/get_ping_ip', methods=['POST'])
|
@app.route('/get_ping_ip', methods=['POST'])
|
||||||
def get_ping_ip():
|
def get_ping_ip():
|
||||||
config = request.form['config']
|
config = request.form['config']
|
||||||
|
sem.acquire()
|
||||||
|
|
||||||
db = TinyDB(os.path.join(db_path, config + ".json"))
|
db = TinyDB(os.path.join(db_path, config + ".json"))
|
||||||
html = ""
|
html = ""
|
||||||
for i in db.all():
|
for i in db.all():
|
||||||
@ -1082,6 +1144,8 @@ def get_ping_ip():
|
|||||||
if len(endpoint) == 2:
|
if len(endpoint) == 2:
|
||||||
html += "<option value=" + endpoint[0] + ">" + endpoint[0] + "</option>"
|
html += "<option value=" + endpoint[0] + ">" + endpoint[0] + "</option>"
|
||||||
html += "</optgroup>"
|
html += "</optgroup>"
|
||||||
|
db.close()
|
||||||
|
sem.release()
|
||||||
return html
|
return html
|
||||||
|
|
||||||
# Ping IP
|
# Ping IP
|
||||||
@ -1101,8 +1165,6 @@ def ping_ip():
|
|||||||
}
|
}
|
||||||
if returnjson['package_loss'] == 1.0:
|
if returnjson['package_loss'] == 1.0:
|
||||||
returnjson['package_loss'] = returnjson['package_sent']
|
returnjson['package_loss'] = returnjson['package_sent']
|
||||||
|
|
||||||
|
|
||||||
return jsonify(returnjson)
|
return jsonify(returnjson)
|
||||||
except Exception:
|
except Exception:
|
||||||
return "Error"
|
return "Error"
|
||||||
@ -1202,4 +1264,13 @@ if __name__ == "__main__":
|
|||||||
app_port = config.get("Server", "app_port")
|
app_port = config.get("Server", "app_port")
|
||||||
wg_conf_path = config.get("Server", "wg_conf_path")
|
wg_conf_path = config.get("Server", "wg_conf_path")
|
||||||
config.clear()
|
config.clear()
|
||||||
app.run(host=app_ip, debug=False, port=app_port)
|
app.run(host=app_ip, debug=False, port=app_port)
|
||||||
|
else:
|
||||||
|
init_dashboard()
|
||||||
|
update = check_update()
|
||||||
|
config = configparser.ConfigParser(strict=False)
|
||||||
|
config.read('wg-dashboard.ini')
|
||||||
|
app_ip = config.get("Server", "app_ip")
|
||||||
|
app_port = config.get("Server", "app_port")
|
||||||
|
wg_conf_path = config.get("Server", "wg_conf_path")
|
||||||
|
config.clear()
|
@ -1,5 +1,5 @@
|
|||||||
Flask
|
Flask
|
||||||
tinydb
|
tinydb==4.5.2
|
||||||
ifcfg
|
ifcfg
|
||||||
icmplib
|
icmplib
|
||||||
flask-qrcode
|
flask-qrcode
|
@ -117,22 +117,50 @@ body {
|
|||||||
|
|
||||||
.dot-running{
|
.dot-running{
|
||||||
background-color: #28a745!important;
|
background-color: #28a745!important;
|
||||||
|
box-shadow: 0 0 0 0.2rem #28a74545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h6-dot-running{
|
||||||
|
margin-left: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot-stopped{
|
.dot-stopped{
|
||||||
background-color: #6c757d!important;
|
background-color: #6c757d!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-running{
|
||||||
|
border-color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
.info h6{
|
.info h6{
|
||||||
line-break: anywhere;
|
line-break: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info .row .col-sm{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .row .col-sm small{
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .row .col-sm small strong:last-child(1){
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-control{
|
.btn-control{
|
||||||
border: none !important;
|
border: none !important;
|
||||||
padding: 0 1rem 0 0;
|
padding: 0 1rem 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-control:active, .btn-control:focus{
|
||||||
|
background-color: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.share_peer_btn_group .btn-control{
|
.share_peer_btn_group .btn-control{
|
||||||
padding: 0 0 0 1rem;
|
padding: 0 0 0 1rem;
|
||||||
}
|
}
|
||||||
@ -213,7 +241,7 @@ main{
|
|||||||
bottom: 3rem;
|
bottom: 3rem;
|
||||||
right: 2rem;
|
right: 2rem;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
border-radius: 100px;
|
border-radius: 100px !important;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
||||||
}
|
}
|
||||||
@ -274,4 +302,24 @@ main{
|
|||||||
|
|
||||||
.key:hover{
|
.key:hover{
|
||||||
color: #007bff;
|
color: #007bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card{
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.peer_list .card .button-group{
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control{
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn{
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content{
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
@ -107,8 +107,14 @@ var qrcodeModal = new bootstrap.Modal(document.getElementById('qrcode_modal'), {
|
|||||||
|
|
||||||
// QR Code
|
// QR Code
|
||||||
$("body").on("click", ".btn-qrcode-peer", function (){
|
$("body").on("click", ".btn-qrcode-peer", function (){
|
||||||
qrcodeModal.toggle();
|
var src = $(this).attr('img_src');
|
||||||
$("#qrcode_img").attr('src', $(this).attr('img_src'))
|
$.ajax({
|
||||||
|
"url": src,
|
||||||
|
"method": "GET"
|
||||||
|
}).done(function(res){
|
||||||
|
$("#qrcode_img").attr('src', res)
|
||||||
|
qrcodeModal.toggle();
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delete Peer Modal
|
// Delete Peer Modal
|
||||||
|
@ -109,7 +109,6 @@
|
|||||||
<i class="bi bi-plus-circle-fill" style=""></i> Add Peer
|
<i class="bi bi-plus-circle-fill" style=""></i> Add Peer
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -126,26 +125,35 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<div class="col-sm-6 col-lg-4">
|
<div class="col-sm-6 col-lg-4">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card mb-3">
|
<div class="card mb-3 card-{{i['status']}}">
|
||||||
<div class="card-header">
|
{# <div class="card-header">#}
|
||||||
|
{# <div class="row">#}
|
||||||
|
{# <div class="col">#}
|
||||||
|
{# <div class="card-header-body ">#}
|
||||||
|
{# {% if not i['name']%}#}
|
||||||
|
{# {{ "Untitled" }}#}
|
||||||
|
{# {% else %}#}
|
||||||
|
{# {{i['name']}}#}
|
||||||
|
{# {% endif %}#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col-sm">
|
||||||
<div class="card-header-body ">
|
<h4>
|
||||||
{% if not i['name']%}
|
{% if not i['name']%}
|
||||||
{{ "Untitled" }}
|
{{ "Untitled" }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{i['name']}}
|
{{i['name']}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# <span class="dot dot-{{i['status']}}"></span>#}
|
</h4>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="w-100"></div>
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<small class="text-muted"><strong>STATUS</strong></small>
|
<small class="text-muted"><strong>STATUS</strong></small>
|
||||||
<h6 style="text-transform: uppercase;" class="mb-2"><span class="dot dot-{{i['status']}}" style="margin-left: 0 !important;margin-top: 5px"></span></h6>
|
<h6 style="text-transform: uppercase;" class="mb-2 h6-dot-{{i['status']}}"><span class="dot dot-{{i['status']}}" style="margin-left: 0 !important;margin-top: 5px"></span></h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 peer_data_group" style="text-align: right">
|
<div class="col-6 peer_data_group" style="text-align: right">
|
||||||
<small class="text-muted"><strong>TRANSFER</strong></small>
|
<small class="text-muted"><strong>TRANSFER</strong></small>
|
||||||
@ -162,7 +170,7 @@
|
|||||||
<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="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>
|
||||||
@ -182,7 +190,7 @@
|
|||||||
<button type="button" class="btn btn-outline-danger btn-delete-peer btn-control" id="{{i['id']}}" data-toggle="modal"><i class="bi bi-x-circle-fill"></i></button>
|
<button type="button" class="btn btn-outline-danger btn-delete-peer btn-control" id="{{i['id']}}" data-toggle="modal"><i class="bi bi-x-circle-fill"></i></button>
|
||||||
{% if i['private_key'] %}
|
{% if i['private_key'] %}
|
||||||
<div class="share_peer_btn_group" style="margin-left: auto !important; display: inline">
|
<div class="share_peer_btn_group" style="margin-left: auto !important; display: inline">
|
||||||
<button type="button" class="btn btn-outline-success btn-qrcode-peer btn-control" img_src="{{ qrcode("[Interface]\nPrivateKey = "+i['private_key']+"\nAddress = "+i['allowed_ip']+"\nMTU = "+i['mtu']+"\nDNS = "+i['DNS']+"\n\n[Peer]\nPublicKey = "+conf_data['public_key']+"\nAllowedIPs = "+i['endpoint_allowed_ip']+"\nPersistentKeepalive = "+i['keepalive']+"\nEndpoint = "+wg_ip+":"+conf_data['listen_port']) }}">
|
<button type="button" class="btn btn-outline-success btn-qrcode-peer btn-control" img_src="/qrcode/{{ conf_data['name'] }}?id={{ i['id']|urlencode }}">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="width: 19px;" fill="#28a745"><path d="M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zM13 3v8h8V3h-8zm6 6h-4V5h4v4zM13 13h2v2h-2zM15 15h2v2h-2zM13 17h2v2h-2zM17 17h2v2h-2zM19 19h2v2h-2zM15 19h2v2h-2zM17 13h2v2h-2zM19 15h2v2h-2z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="width: 19px;" fill="#28a745"><path d="M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zM13 3v8h8V3h-8zm6 6h-4V5h4v4zM13 13h2v2h-2zM15 15h2v2h-2zM13 17h2v2h-2zM17 17h2v2h-2zM19 19h2v2h-2zM15 19h2v2h-2zM17 13h2v2h-2zM19 15h2v2h-2z"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<a href="/download/{{ conf_data['name'] }}?id={{ i['id']|urlencode }}" class="btn btn-outline-info btn-download-peer btn-control">
|
<a href="/download/{{ conf_data['name'] }}?id={{ i['id']|urlencode }}" class="btn btn-outline-info btn-download-peer btn-control">
|
||||||
|
1
src/templates/qrcode.html
Normal file
1
src/templates/qrcode.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ qrcode("[Interface]\nPrivateKey = "+i['private_key']+"\nAddress = "+i['allowed_ip']+"\nMTU = "+i['mtu']+"\nDNS = "+i['DNS']+"\n\n[Peer]\nPublicKey = "+i['public_key']+"\nAllowedIPs = "+i['endpoint_allowed_ip']+"\nPersistentKeepalive = "+i['keepalive']+"\nEndpoint = "+i['endpoint']) }}
|
80
src/util.py
Normal file
80
src/util.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
"""
|
||||||
|
Helper Functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# Regex Match
|
||||||
|
def regex_match(regex, text):
|
||||||
|
pattern = re.compile(regex)
|
||||||
|
return pattern.search(text) is not None
|
||||||
|
|
||||||
|
|
||||||
|
# Check IP format
|
||||||
|
def check_IP(ip):
|
||||||
|
ip_patterns = (
|
||||||
|
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}",
|
||||||
|
r"[0-9a-fA-F]{0,4}(:([0-9a-fA-F]{0,4})){1,7}$"
|
||||||
|
)
|
||||||
|
for match_pattern in ip_patterns:
|
||||||
|
match_result = regex_match(match_pattern, ip)
|
||||||
|
if match_result:
|
||||||
|
result = match_result
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result = None
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# Clean IP
|
||||||
|
def clean_IP(ip):
|
||||||
|
return ip.replace(' ', '')
|
||||||
|
|
||||||
|
|
||||||
|
# Clean IP with range
|
||||||
|
def clean_IP_with_range(ip):
|
||||||
|
return clean_IP(ip).split(',')
|
||||||
|
|
||||||
|
|
||||||
|
# Check IP with range
|
||||||
|
def check_IP_with_range(ip):
|
||||||
|
ip_patterns = (
|
||||||
|
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|\/)){4}([0-9]{1,2})(,|$)",
|
||||||
|
r"[0-9a-fA-F]{0,4}(:([0-9a-fA-F]{0,4})){1,7}\/([0-9]{1,3})(,|$)"
|
||||||
|
)
|
||||||
|
|
||||||
|
for match_pattern in ip_patterns:
|
||||||
|
match_result = regex_match(match_pattern, ip)
|
||||||
|
if match_result:
|
||||||
|
result = match_result
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result = None
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# Check allowed ips list
|
||||||
|
def check_Allowed_IPs(ip):
|
||||||
|
ip = clean_IP_with_range(ip)
|
||||||
|
for i in ip:
|
||||||
|
if not check_IP_with_range(i): return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# Check DNS
|
||||||
|
def check_DNS(dns):
|
||||||
|
dns = dns.replace(' ', '').split(',')
|
||||||
|
status = True
|
||||||
|
for i in dns:
|
||||||
|
if not (check_IP(i) or regex_match("(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z]{0,61}[a-z]", i)):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# Check remote endpoint
|
||||||
|
def check_remote_endpoint(address):
|
||||||
|
return (check_IP(address) or regex_match("(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z]{0,61}[a-z]",
|
||||||
|
address))
|
10
src/wgd.sh
10
src/wgd.sh
@ -33,9 +33,9 @@ _check_and_set_venv(){
|
|||||||
|
|
||||||
install_wgd(){
|
install_wgd(){
|
||||||
# Check Python3 version
|
# Check Python3 version
|
||||||
version_pass=$(python3 -c 'import sys; print("1") if (sys.version_info.major == 3 and sys.version_info.minor >= 7) else print("0");')
|
version_pass=$(python3 -c 'import sys; print("1") if (sys.version_info.major == 3 and sys.version_info.minor >= 8) else print("0");')
|
||||||
if [ $version_pass == "0" ]
|
if [ $version_pass == "0" ]
|
||||||
then printf "| WGDashboard required Python3.7+ |\n"
|
then printf "| WGDashboard required Python3.8+ |\n"
|
||||||
printf "%s\n" "$dashes"
|
printf "%s\n" "$dashes"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -47,14 +47,14 @@ install_wgd(){
|
|||||||
|
|
||||||
# set up the local environment
|
# set up the local environment
|
||||||
_check_and_set_venv
|
_check_and_set_venv
|
||||||
|
${VIRTUAL_ENV}/bin/python3 -m pip -U pip
|
||||||
python3 -m pip install -r requirements.txt > /dev/null 2>&1
|
${VIRTUAL_ENV}/bin/python3 -m pip install -U -r requirements.txt
|
||||||
printf "| WGDashboard installed successfully! |\n"
|
printf "| WGDashboard installed successfully! |\n"
|
||||||
|
|
||||||
printf "| Preparing the systemctl unit file |\n"
|
printf "| Preparing the systemctl unit file |\n"
|
||||||
sed -i "s#{{APP_ROOT}}#${APP_ROOT}#" wg-dashboard.service
|
sed -i "s#{{APP_ROOT}}#${APP_ROOT}#" wg-dashboard.service
|
||||||
sed -i "s#{{VIRTUAL_ENV}}#${VIRTUAL_ENV}#" wg-dashboard.service
|
sed -i "s#{{VIRTUAL_ENV}}#${VIRTUAL_ENV}#" wg-dashboard.service
|
||||||
cat wg-dashboard.service | sudo SYSTEMD_EDITOR=tee systemctl edit --force --full wg-dashboard.service
|
# cat wg-dashboard.service | sudo SYSTEMD_EDITOR=tee systemctl edit --force --full wg-dashboard.service
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
printf "| Consider 'systemctl enable wg-dashboard' |\n"
|
printf "| Consider 'systemctl enable wg-dashboard' |\n"
|
||||||
printf " and 'systemctl start wg-dashboard'\n"
|
printf " and 'systemctl start wg-dashboard'\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user