Compare commits

...

57 Commits

Author SHA1 Message Date
Donald Zou
9e38137e76 Removed DNS as a required field from peer settings 2024-05-03 10:15:00 +08:00
Donald Zou
210f5eabc9 Merge pull request #261 from donaldzou/donaldzou-patch-1
Update FUNDING.yml
2024-03-31 11:20:04 -04:00
Donald Zou
5f5c91a8ff Update FUNDING.yml 2024-03-31 11:19:54 -04:00
Donald Zou
05c7121c8a Update README.md 2024-03-31 00:55:46 -04:00
Donald Zou
551a8e9588 Add files via upload 2024-03-31 00:53:00 -04:00
Donald Zou
8fe5507ff8 Update README.md 2024-02-27 18:38:10 -05:00
Donald Zou
4aed647865 Merge pull request #254 from Upellift99/main
Enabling use of underscores in configuration name
2024-02-01 18:39:05 -05:00
John
74ab7aaa3d Enabling use of underscores in configuration name. 2024-02-01 09:53:04 +01:00
John
dcf2055851 Enabling use of underscores in configuration name. 2024-02-01 09:47:52 +01:00
Donald Zou
734a4b5e00 Merge pull request #252 from donaldzou/donaldzou-patch-1
Update README.md
2024-01-23 15:11:21 -05:00
Donald Zou
da70fac0b6 Update README.md 2024-01-23 15:11:02 -05:00
Donald Zou
3d6ecba4f5 Update README.md 2024-01-09 14:10:08 -05:00
Donald Zou
86220694ce Update README.md
Added instruction to install `net-tools`. It is required for the Python package `ifcfg`. Seems like it is not pre-installed on a fresh debian based system.
2023-12-10 13:01:45 -05:00
Donald Zou
77f31177c8 Update .gitignore 2023-12-10 12:56:49 -05:00
Donald Zou
33ff91aea8 Update .gitignore 2023-12-10 12:56:02 -05:00
Donald Zou
2c9cade70a Create SECURITY.md 2023-03-23 13:07:36 -04:00
Donald Zou
d7d7a84bd5 Update README.md 2022-04-10 09:35:50 -04:00
Donald Zou
990463fbea Update README.md 2022-04-10 09:29:07 -04:00
Donald Zou
0d9a8ba6f7 Update README.md 2022-04-06 21:05:24 -04:00
Donald Zou
edbaf3ac82 Update README.md 2022-03-29 12:27:39 -04:00
Donald Zou
cd84674ae0 Update README.md 2022-03-28 08:23:12 -04:00
Donald Zou
f60ea43f29 Create codeql-analysis.yml 2022-03-27 21:44:49 -04:00
Donald Zou
76f547a726 Update README.md 2022-03-26 11:14:27 -04:00
Donald Zou
dffe5e0819 Update README.md 2022-03-25 14:11:39 -04:00
Donald Zou
fb9ef0c547 Update README.md 2022-03-22 17:34:34 -04:00
Donald Cheng Hong Zou
d52cd2b17c Doing a update 2022-03-22 17:28:19 -04:00
Donald Cheng Hong Zou
cefa80f317 Fixed redirect functionality 2022-03-22 16:17:12 -04:00
Donald Cheng Hong Zou
191ff1abec Merge branch 'main' of https://github.com/donaldzou/WGDashboard 2022-02-28 13:29:25 -05:00
Donald Cheng Hong Zou
3bb86493cc Minor changes 2022-02-28 13:29:17 -05:00
Donald Zou
d1d3151e1e Update README.md 2022-02-27 15:50:55 -05:00
Donald Cheng Hong Zou
f9dc9ebdb3 Removed some unnecessary comments 2022-02-11 09:35:58 -05:00
Donald Cheng Hong Zou
3b478bcc2d OneDrive gone again.... 2022-02-04 21:36:46 -05:00
Donald Cheng Hong Zou
77bb78c381 OneDrive caused my whole project folder gone.... 2022-02-04 11:44:50 -05:00
Donald Cheng Hong Zou
cafa97f502 Changed version number 2022-01-31 16:09:50 -05:00
Donald Cheng Hong Zou
0d858493d5 Update README.md 2022-01-31 09:56:38 -05:00
Donald Cheng Hong Zou
99fb07c6b3 Fixed public key error with existed private key 2022-01-31 09:38:05 -05:00
Donald Zou
eaad971c0a Update README.md 2022-01-24 22:06:38 -05:00
Donald Cheng Hong Zou
377abd87fd Commit 2022-01-24 20:11:35 -05:00
Donald Zou
af71176296 Merge pull request #133 from donaldzou/v3.0.3-pr
v3.0.3
2022-01-23 19:34:06 -05:00
Donald Cheng Hong Zou
69737177ef Changed version number to v3.0.3 2022-01-23 19:30:43 -05:00
Donald Cheng Hong Zou
efae1222c1 Update dashboard.py 2022-01-23 19:25:12 -05:00
Donald Cheng Hong Zou
3caea1a903 Update README.md 2022-01-23 19:21:43 -05:00
Donald Cheng Hong Zou
a43478d627 Fixed no init_dashboard() for debug mode the first time 2022-01-23 19:19:38 -05:00
Donald Cheng Hong Zou
ed2c3f43c7 Added tracking loading time 2022-01-19 10:43:39 -05:00
Donald Cheng Hong Zou
fcfd816cec Remove pylint 2022-01-19 09:25:27 -05:00
Donald Cheng Hong Zou
2e3977e59c commit 2022-01-19 09:18:03 -05:00
Donald Cheng Hong Zou
3c68430336 Update pylint.yml 2022-01-19 09:12:57 -05:00
Donald Cheng Hong Zou
43afb86fa8 Update pylint.yml 2022-01-19 09:10:59 -05:00
Donald Cheng Hong Zou
194ccbdbb4 Update pylint.yml 2022-01-19 09:10:07 -05:00
Donald Cheng Hong Zou
7139e230cf Commit 2022-01-19 09:08:27 -05:00
Donald Zou
120d3b9f54 Update pylint.yml 2022-01-19 09:05:39 -05:00
Donald Zou
712460a040 Update pylint.yml 2022-01-19 09:03:35 -05:00
Donald Zou
be5594f1c9 Create pylint.yml 2022-01-19 09:01:35 -05:00
Donald Cheng Hong Zou
0a885117db Update README.md 2022-01-18 13:04:00 -05:00
Donald Zou
5b73654544 Update README.md 2022-01-18 12:43:37 -05:00
Donald Cheng Hong Zou
1485b78b7b Merge branch 'main' of https://github.com/donaldzou/WGDashboard 2022-01-18 12:43:20 -05:00
Donald Cheng Hong Zou
bfec57172a Update README.md 2022-01-18 12:43:11 -05:00
19 changed files with 341 additions and 74 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,4 @@
# These are supported funding model platforms
github: [donaldzou]
patreon: DonaldDonnyZou

70
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '30 5 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

6
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.vscode/sftp.json
src/.vscode/sftp.json
.vscode
.DS_Store
.idea
src/db
@@ -15,4 +14,5 @@ venv/**
log/**
release/*
src/db/wgdashboard.db
.jshintrc
.jshintrc
node_modules/

115
README.md
View File

@@ -1,3 +1,17 @@
### Development on v4
Hi Everyone, I've decided to promote the long time working `v3.1` to `v4`! This version will be a huge update on the structure of the app. The frontend will be completely handle on the client side with Vue.js, and communicate with the server via REST Api. With this design, it could be possible for the frontend app to connect to multiple server in the future. Stay tune to this new verion, I'm working very hard on this while balancing school and work. If you would like know whats going on, you can check out [this branch](https://github.com/donaldzou/WGDashboard/tree/v4) 😊
#### A preview on v4.0 🥹
![v4.0 Preview](https://raw.githubusercontent.com/donaldzou/WGDashboard/main/img/ScreenRecording2024-03-31at12.47.43AM-ezgif.com-video-to-gif-converter.gif)
<hr>
##### Known issue on WGDashboard `v3.0 - v3.0.6`
- [IPv6 in WireGuard might not fully support.](https://github.com/donaldzou/WGDashboard/issues/167)
<hr>
<p align="center">
<img alt="WGDashboard" src="img/logo.png" width="128">
</p>
@@ -9,7 +23,8 @@
</p>
<p align="center">
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard"></a>
<a href="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6"><img src="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6.svg" alt="wakatime"></a>
<a href="https://wakatime.com/badge/github/donaldzou/WGDashboard"><img src="https://wakatime.com/badge/github/donaldzou/WGDashboard.svg" alt="wakatime"></a>
<a href="https://hits.seeyoufarm.com"><img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fdonaldzou%2FWGDashboard&count_bg=%2379C83D&title_bg=%23555555&icon=github.svg&icon_color=%23E7E7E7&title=Visitor&edge_flat=false"/></a>
</p>
<p align="center">Monitoring WireGuard is not convinient, need to login into server and type <code>wg show</code>. That's why this platform is being created, to view all configurations and manage them in a easier way.</p>
<p align="center"><small>Note: This project is not affiliate to the official WireGuard Project ;)</small></p>
@@ -19,7 +34,7 @@
- 🎉 **New Features**
- **Moved from TinyDB to SQLite**: SQLite provide a better performance and loading speed when getting peers! Also avoided crashing the database due to **race condition**.
- **Added Gunicorn WSGI Server**: This could provide more stable on handling HTTP request, and more flexibility in the future (such as HTTPS support). **BIG THANKS to @pgalonza :heart:**
- **Add Peers by Bulk: ** User can add peers by bulk, just simply set the amount and click add.
- **Add Peers by Bulk:** User can add peers by bulk, just simply set the amount and click add.
- **Delete Peers by Bulk**: User can delete peers by bulk, without deleting peers one by one.
- **Download Peers in Zip**: User can download all *downloadable* peers in a zip.
- **Added Pre-shared Key to peers:** Now each peer can add with a pre-shared key to enhance security. Previously added peers can add the pre-shared key through the peer setting button.
@@ -28,8 +43,8 @@
- 🪚 **Bug Fixed**
- [IP Sorting range issues #99](https://github.com/donaldzou/WGDashboard/issues/99) [❤️ @barryboom]
- [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ ikidd]
- [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @ pgalonza]
- [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ikidd]
- [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @pgalonza]
- [Added MTU and PersistentKeepalive to QR code and download files #112](https://github.com/donaldzou/WGDashboard/pull/112) [:heart: @reafian]
- **And many other bugs provided by our beloved users** :heart:
- **🧐 Other Changes**
@@ -90,7 +105,8 @@
- **WireGuard** and **WireGuard-Tools (`wg-quick`)** are installed.
> Don't know how? Check this <a href="https://www.wireguard.com/install/">official documentation</a>
- Net Tools (`net-tools`) is installed.
- You can verify this by checking if `ifconfig` return a list of network interface. Such as `eth0`
- Configuration files under **`/etc/wireguard`**, but please note the following sample
```ini
@@ -115,7 +131,7 @@
1. Download WGDashboard
```shell
git clone -b v3.0 https://github.com/donaldzou/WGDashboard.git wgdashboard
git clone -b v3.0.6 https://github.com/donaldzou/WGDashboard.git wgdashboard
2. Open the WGDashboard folder
@@ -301,7 +317,7 @@ Since version 2.0, WGDashboard will be using a configuration file called `wg-das
| `app_ip` | IP address the dashboard will run with | `0.0.0.0` | Yes |
| `app_port` | Port the the dashboard will run with | `10086` | Yes |
| `auth_req` | Does the dashboard need authentication to access, if `auth_req = false` , user will not be access the **Setting** tab due to security consideration. **User can only edit the file directly in system**. | `true` | **No** |
| `version` | Dashboard Version | `v3.0` | **No** |
| `version` | Dashboard Version | `v3.0.6` | **No** |
| `dashboard_refresh_interval` | How frequent the dashboard will refresh on the configuration page | `60000ms` | Yes |
| `dashboard_sort` | How configuration is sorting | `status` | Yes |
| | | | |
@@ -348,17 +364,45 @@ Endpoint = 0.0.0.0:51820
<hr>
#### Update Method 1 (For `v3.0` or above)
1. Change your directory to `wgdashboard/src`
```bash
cd wgdashboard/src
```
2. Update the dashboard with the following
```bash
./wgd.sh update
chmod +x ./wgd.sh
```
> If this doesn't work, please use the method below. Sorry about that :(
#### Update Method 2
1. Change your directory to `wgdashboard`
```shell
cd wgdashboard
cd wgdashboard/src
```
2. Update the dashboard
```shell
git pull https://github.com/donaldzou/WGDashboard.git v3.0 --force
git pull https://github.com/donaldzou/WGDashboard.git v3.0.6 --force
```
3. Install
```shell
./wgd.sh install
```
Starting with `v3.0`, you can simply do `./wgd.sh update` !! (I hope, lol)
## 🥘 Experimental Functions
@@ -393,10 +437,58 @@ Starting with `v3.0`, you can simply do `./wgd.sh update` !! (I hope, lol)
## ⏰ Changelog
#### v3.0.6 - Mar 22, 2022
**Fixed Bug**
- When wgdashboard is running behind a proxy server, redirecting could cause using http while proxy is using https [❤️ from #161]
#### v3.0.5 - Jan 31, 2022
**Quick Fix**
- Fixed public key does not match when user used an existing private key
- Sorry for the wrong version number that causing the dashboard ask for update after updating.
#### v3.0.3 - Jan 23, 2022
- Fixed when dashboard configuration file cannot be found after a fresh install. [❤️ from #132 ]
#### v3.0 - Jan 18, 2022
- 🎉 **New Features**
- **Moved from TinyDB to SQLite**: SQLite provide a better performance and loading speed when getting peers! Also avoided crashing the database due to **race condition**.
- **Added Gunicorn WSGI Server**: This could provide more stable on handling HTTP request, and more flexibility in the future (such as HTTPS support). **BIG THANKS to @pgalonza :heart:**
- **Add Peers by Bulk:** User can add peers by bulk, just simply set the amount and click add.
- **Delete Peers by Bulk**: User can delete peers by bulk, without deleting peers one by one.
- **Download Peers in Zip**: User can download all *downloadable* peers in a zip.
- **Added Pre-shared Key to peers:** Now each peer can add with a pre-shared key to enhance security. Previously added peers can add the pre-shared key through the peer setting button.
- **Redirect Back to Previous Page:** The dashboard will now redirect you back to your previous page if the current session got timed out and you need to sign in again.
- **Added Some [🥘 Experimental Functions](https://github.com/donaldzou/WGDashboard#-experimental-functions)**
- 🪚 **Bug Fixed**
- [IP Sorting range issues #99](https://github.com/donaldzou/WGDashboard/issues/99) [❤️ @barryboom]
- [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ikidd]
- [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @pgalonza]
- [Added MTU and PersistentKeepalive to QR code and download files #112](https://github.com/donaldzou/WGDashboard/pull/112) [:heart: @reafian]
- **And many other bugs provided by our beloved users** :heart:
- **🧐 Other Changes**
- **Key generating moved to front-end**: No longer need to use the server's WireGuard to generate keys, thanks to the `wireguard.js` from the [official repository](https://git.zx2c4.com/wireguard-tools/tree/contrib/keygen-html/wireguard.js)!
- **Peer transfer calculation**: each peer will now show all transfer amount (previously was only showing transfer amount from the last configuration start-up).
- **UI adjustment on running peers**: peers will have a new style indicating that it is running.
- **`wgd.sh` finally can update itself**: So now user could update the whole dashboard from `wgd.sh`, with the `update` command.
- **Minified JS and CSS files**: Although only a small changes on the file size, but I think is still a good practice to save a bit of bandwidth ;)
*And many other small changes for performance and bug fixes! :laughing:*
> If you have any other brilliant ideas for this project, please shout it in here [#129](https://github.com/donaldzou/WGDashboard/issues/129) :heart:
**For users who is using `v2.x.x` please be sure to read [this](https://github.com/donaldzou/WGDashboard#please-note-for-user-who-is-using-v231-or-below) before updating WGDashboard ;)**
#### v2.3.1 - Sep 8, 2021
- Updated dashboard's name to **WGDashboard**!!
#### v2.3 - Sep 8, 2021
- 🎉 **New Features**
@@ -478,7 +570,8 @@ Bug Fixed:
- [jQuery](https://jquery.com) `v3.5.1`
- Python
- [Flask](https://pypi.org/project/Flask/) `v2.0.1`
- [ifcfg](https://pypi.org/project/ifcfg/) `v0.21`
- [ifcfg](https://pypi.org/project/ifcfg/) `v0.24`
- [psutil](https://pypi.org/project/psutil/) `v5.9.8`
- [icmplib](https://pypi.org/project/icmplib/) `v2.1.1`
- [flask-qrcode](https://pypi.org/project/Flask-QRcode/) `v3.0.0`

10
SECURITY.md Normal file
View File

@@ -0,0 +1,10 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

View File

@@ -4,7 +4,6 @@ Under Apache-2.0 License
"""
import sqlite3
from flask import g
import configparser
import hashlib
import ipaddress
@@ -22,7 +21,8 @@ from datetime import datetime, timedelta
from operator import itemgetter
# PIP installed library
import ifcfg
from flask import Flask, request, render_template, redirect, url_for, session, jsonify
import psutil
from flask import Flask, request, render_template, redirect, url_for, session, jsonify, g
from flask_qrcode import QRcode
from icmplib import ping, traceroute
@@ -31,22 +31,27 @@ from util import regex_match, check_DNS, check_Allowed_IPs, check_remote_endpoin
check_IP_with_range, clean_IP_with_range
# Dashboard Version
DASHBOARD_VERSION = 'v3.0'
DASHBOARD_VERSION = 'v3.0.6'
# WireGuard's configuration path
WG_CONF_PATH = None
# Dashboard Config Name
configuration_path = os.getenv('CONFIGURATION_PATH', '.')
DB_PATH = os.path.join(configuration_path, 'db')
if not os.path.isdir(DB_PATH):
os.mkdir(DB_PATH)
DASHBOARD_CONF = os.path.join(configuration_path, 'wg-dashboard.ini')
# Upgrade Required
UPDATE = None
# Flask App Configuration
app = Flask("WGDashboard")
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
app.secret_key = secrets.token_urlsafe(16)
app.config['TEMPLATES_AUTO_RELOAD'] = True
# Enable QR Code Generator
QRcode(app)
@@ -66,9 +71,9 @@ def get_dashboard_conf():
Get dashboard configuration
@return: configparser.ConfigParser
"""
config = configparser.ConfigParser(strict=False)
config.read(DASHBOARD_CONF)
return config
r_config = configparser.ConfigParser(strict=False)
r_config.read(DASHBOARD_CONF)
return r_config
def set_dashboard_conf(config):
@@ -99,7 +104,6 @@ def get_conf_peer_key(config_name):
return config_name + " is not running."
# Get numbers of connected peer of a configuration
def get_conf_running_peer_number(config_name):
"""
Get number of running peers on wireguard interface.
@@ -128,7 +132,6 @@ def get_conf_running_peer_number(config_name):
return running
# Read [Interface] section from configuration file
def read_conf_file_interface(config_name):
"""
Get interface settings.
@@ -161,7 +164,6 @@ def read_conf_file(config_name):
@rtype: dict
"""
# Read Configuration File Start
conf_location = WG_CONF_PATH + "/" + config_name + ".conf"
f = open(conf_location, 'r')
file = f.read().split("\n")
@@ -190,7 +192,7 @@ def read_conf_file(config_name):
conf_peer_data["Peers"].append({})
elif peer > -1:
if len(i) > 0:
tmp = re.split('\s*=\s*', i, 1)
tmp = re.split(r'\s*=\s*', i, 1)
if len(tmp) == 2:
conf_peer_data["Peers"][peer][tmp[0]] = tmp[1]
@@ -224,10 +226,10 @@ def get_latest_handshake(config_name):
status = "stopped"
if int(data_usage[count + 1]) > 0:
g.cur.execute("UPDATE %s SET latest_handshake = '%s', status = '%s' WHERE id='%s'"
% (config_name, str(minus).split(".", maxsplit=1)[0], status, data_usage[count]))
% (config_name, str(minus).split(".", maxsplit=1)[0], status, data_usage[count]))
else:
g.cur.execute("UPDATE %s SET latest_handshake = '(None)', status = '%s' WHERE id='%s'"
% (config_name, status, data_usage[count]))
% (config_name, status, data_usage[count]))
count += 2
@@ -294,6 +296,7 @@ def get_endpoint(config_name):
count += 2
def get_allowed_ip(conf_peer_data, config_name):
"""
Get allowed ips from all peers of a configuration
@@ -470,8 +473,8 @@ def get_conf_status(config_name):
@param config_name:
@return: Return a string indicate the running status
"""
ifconfig = dict(ifcfg.interfaces().items())
return "running" if config_name in ifconfig.keys() else "stopped"
addrs = psutil.net_if_addrs()
return "running" if config_name in addrs else "stopped"
def get_conf_list():
@@ -626,7 +629,6 @@ def close_DB(exception):
g.db.close()
# Before request
@app.before_request
def auth_req():
"""
@@ -652,7 +654,10 @@ def auth_req():
else:
session['message'] = ""
conf.clear()
return redirect("/signin?redirect=" + str(request.url))
redirectURL = str(request.url)
redirectURL = redirectURL.replace("http://", "")
redirectURL = redirectURL.replace("https://", "")
return redirect("/signin?redirect=" + redirectURL)
else:
if request.endpoint in ['signin', 'signout', 'auth', 'settings', 'update_acct', 'update_pwd',
'update_app_ip_port', 'update_wg_conf_path']:
@@ -678,7 +683,7 @@ def signin():
if "message" in session:
message = session['message']
session.pop("message")
return render_template('signin.html', message=message)
return render_template('signin.html', message=message, version=DASHBOARD_VERSION)
# Sign Out
@@ -1092,7 +1097,7 @@ def add_peer_bulk(config_name):
if not amount.isdigit() or int(amount) < 1:
return "Amount must be integer larger than 0"
amount = int(amount)
if not check_DNS(dns_addresses):
if len(dns_addresses) > 0 and not check_DNS(dns_addresses):
return "DNS formate is incorrect. Example: 1.1.1.1"
if not check_Allowed_IPs(endpoint_allowed_ip):
return "Endpoint Allowed IPs format is incorrect."
@@ -1155,7 +1160,7 @@ def add_peer(config_name):
enable_preshared_key = data["enable_preshared_key"]
preshared_key = data['preshared_key']
keys = get_conf_peer_key(config_name)
if len(public_key) == 0 or len(dns_addresses) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0:
if len(public_key) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0:
return "Please fill in all required box."
if not isinstance(keys, list):
return config_name + " is not running."
@@ -1166,7 +1171,7 @@ def add_peer(config_name):
.fetchone()
if check_dup_ip[0] != 0:
return "Allowed IP already taken by another peer."
if not check_DNS(dns_addresses):
if len(dns_addresses) > 0 and not check_DNS(dns_addresses):
return "DNS formate is incorrect. Example: 1.1.1.1"
if not check_Allowed_IPs(endpoint_allowed_ip):
return "Endpoint Allowed IPs format is incorrect."
@@ -1258,7 +1263,7 @@ def save_peer_setting(config_name):
check_ip = check_repeat_allowed_ip(id, allowed_ip, config_name)
if not check_IP_with_range(endpoint_allowed_ip):
return jsonify({"status": "failed", "msg": "Endpoint Allowed IPs format is incorrect."})
if not check_DNS(dns_addresses):
if len(dns_addresses) > 0 and not check_DNS(dns_addresses):
return jsonify({"status": "failed", "msg": "DNS format is incorrect."})
if len(data['MTU']) == 0 or not data['MTU'].isdigit():
return jsonify({"status": "failed", "msg": "MTU format is not correct."})
@@ -1417,12 +1422,30 @@ def download_all(config_name):
filename = filename + "_" + config_name
psk = ""
if preshared_key != "":
psk = "\nPresharedKey = " + preshared_key
psk = "PresharedKey = " + preshared_key
return_data = f'''[Interface]
PrivateKey = {private_key}
Address = {allowed_ip}
MTU = {str(mtu_value)}
return_data = "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \
dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
'''
if len(dns_addresses) > 0:
return_data += f'DNS = {dns_addresses}'
return_data += f'''
[Peer]
PublicKey = {public_key}
AllowedIPs = {endpoint_allowed_ip}
Endpoint = {endpoint}
PersistentKeepalive = {str(keepalive)}
{psk}
'''
# return_data = "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \
# dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
# public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
# endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
data.append({"filename": f"{filename}.conf", "content": return_data})
return jsonify({"status": True, "peers": data, "filename": f"{config_name}.zip"})
@@ -1470,12 +1493,30 @@ def download(config_name):
filename = filename + "_" + config_name
psk = ""
if preshared_key != "":
psk = "\nPresharedKey = " + preshared_key
psk = "PresharedKey = " + preshared_key
return_data = "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \
dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
return_data = f'''[Interface]
PrivateKey = {private_key}
Address = {allowed_ip}
MTU = {str(mtu_value)}
'''
if len(dns_addresses) > 0:
return_data += f'DNS = {dns_addresses}'
return_data += f'''
[Peer]
PublicKey = {public_key}
AllowedIPs = {endpoint_allowed_ip}
Endpoint = {endpoint}
PersistentKeepalive = {str(keepalive)}
{psk}
'''
# return_data = "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \
# dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
# public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
# endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
return jsonify({"status": True, "filename": f"{filename}.conf", "content": return_data})
return jsonify({"status": False, "filename": "", "content": ""})
@@ -1700,11 +1741,11 @@ def get_host_bind():
config.read('wg-dashboard.ini')
app_ip = config.get("Server", "app_ip")
app_port = config.get("Server", "app_port")
return app_ip, app_port
if __name__ == "__main__":
init_dashboard()
UPDATE = check_update()
config = configparser.ConfigParser(strict=False)
config.read('wg-dashboard.ini')

View File

@@ -1,5 +1,6 @@
Flask
ifcfg
psutil
icmplib
flask-qrcode
gunicorn

BIN
src/static/.DS_Store vendored

Binary file not shown.

View File

@@ -1,5 +1,6 @@
body {
font-size: .875rem;
/*font-family: 'Poppins', sans-serif;*/
}
.feather {
@@ -407,8 +408,26 @@ main{
.btn{
border-radius: 8px;
/*padding: 0.6rem 0.9em;*/
}
#username, #password{
padding: 0.6rem calc( 0.9rem + 32px );
height: inherit;
}
label[for="username"], label[for="password"]{
font-size: 1rem;
margin: 0 !important;
transform: translateY(30px) translateX(16px);
padding: 0;
}
/*label[for="password"]{*/
/* transform: translateY(32px) translateX(16px);*/
/*}*/
.modal-content{
border-radius: 10px;
}

File diff suppressed because one or more lines are too long

View File

@@ -155,7 +155,7 @@
let $enable_preshare_key = $("#enable_preshare_key");
let data_list = [$new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
if ($new_add_amount.val() > 0 && !$new_add_amount.hasClass("is-invalid")){
if ($new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
if ($new_add_endpoint_allowed_ip.val() !== ""){
let conf = $add_peer.getAttribute('conf_id');
let keys = [];
for (let i = 0; i < $new_add_amount.val(); i++) {
@@ -338,8 +338,12 @@
* Load Peers from server to configuration page
* @param searchString
*/
let d1 = new Date();
let time = 0;
let count = 0;
function loadPeers(searchString){
startProgressBar();
d1 = new Date();
$.ajax({
method: "GET",
url: `/get_config/${conf_name}?search=${encodeURIComponent(searchString)}`,
@@ -354,6 +358,12 @@
$(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
$("i[data-toggle='tooltip']").tooltip();
endProgressBar();
let d2 = new Date();
let seconds = (d2 - d1);
time += seconds;
count += 1;
console.log(`Average ${time/count}ms`);
$("#peer_loading_time").html(`Peer Loading Time: ${seconds}ms`);
}).fail(function(){
noResponding();
});
@@ -623,7 +633,7 @@ $add_peer.addEventListener("click",function(){
let $enable_preshare_key = $("#enable_preshare_key");
$add_peer.setAttribute("disabled","disabled");
$add_peer.innerHTML = "Adding...";
if ($allowed_ips.val() !== "" && $public_key.val() !== "" && $new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
if ($allowed_ips.val() !== "" && $public_key.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
let conf = $add_peer.getAttribute('conf_id');
let data_list = [$private_key, $allowed_ips, $new_add_name, $new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
data_list.forEach((ele) => ele.attr("disabled", "disabled"));
@@ -914,7 +924,7 @@ $("#save_peer_setting").on("click",function (){
let $peer_mtu = $("#peer_mtu");
let $peer_keep_alive = $("#peer_keep_alive");
if ($peer_DNS_textbox.val() !== "" &&
if (
$peer_allowed_ip_textbox.val() !== "" && $peer_endpoint_allowed_ips.val() !== ""){
let peer_id = $(this).attr("peer_id");
let conf_id = $(this).attr("conf_id");

File diff suppressed because one or more lines are too long

View File

@@ -171,6 +171,17 @@
return String.fromCharCode.apply(null, base64);
}
function base64ToKey(base64) {
let binary_string = window.atob(base64);
let len = binary_string.length;
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
let uint8 = new Uint8Array(bytes.buffer);
return uint8;
}
function putU32(b, n)
{
b.push(n & 0xff, (n >>> 8) & 0xff, (n >>> 16) & 0xff, (n >>> 24) & 0xff);
@@ -282,7 +293,8 @@
};
},
generatePublicKey: function (privateKey){
return keyToBase64(generatePublicKey(privateKey))
privateKey = base64ToKey(privateKey);
return keyToBase64(generatePublicKey(privateKey));
},
generateZipFiles: function(res){

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,6 @@
</div>
</div>
{% include "navbar.html" %}
<div class="container-fluid" id="right_body">
{% include "sidebar.html" %}
<div class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
@@ -120,6 +119,7 @@
</div>
</div>
<div class="row peer_list"></div>
<small id="peer_loading_time" class="text-muted"></small>
</main>
</div>
</div>
@@ -192,7 +192,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="new_add_DNS">DNS <code>(Required)</code></label>
<label for="new_add_DNS">DNS</label>
<input type="text" class="form-control" id="new_add_DNS" value="{{ DNS }}">
</div>
</div>
@@ -297,7 +297,7 @@
</div>
<div class="col-sm-6">
<div class="mb-3">
<label for="peer_DNS_textbox" class="form-label">DNS <code>(Required)</code></label>
<label for="peer_DNS_textbox" class="form-label">DNS</label>
<input type="text" class="form-control" id="peer_DNS_textbox">
</div>
</div>
@@ -410,8 +410,8 @@
{% include "tools.html" %}
</body>
{% include "footer.html" %}
<script src="{{ url_for('static',filename='js/wireguard.min.js') }}"></script>
<script src="{{ url_for('static',filename='js/configuration.min.js') }}"></script>
<script src="{{ url_for('static',filename='js/wireguard.js') }}"></script>
<script src="{{ url_for('static',filename='js/configuration.js') }}"></script>
<script>
/* global peers */
let load_timeout;

View File

@@ -1,3 +1,3 @@
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
<script src="{{ url_for('static',filename='js/tools.min.js') }}"></script>
<script src="{{ url_for('static',filename='js/tools.js') }}"></script>

View File

@@ -14,41 +14,46 @@
<div class="container-fluid login-container-fluid">
<main role="main" class="container login-container">
<div class="login-box" style="margin: auto !important;">
<h1 class="text-center">Sign In</h1>
<h1 class="text-center">Sign in</h1>
<h5 class="text-center">to WGDashboard</h5>
<form style="margin-left: auto !important; margin-right: auto !important; max-width: 500px;" action="/auth" method="post">
{% if message != "" %}
<div class="alert alert-warning" role="alert">You need to sign in first</div>
{% endif %}
<div class="alert alert-danger d-none" role="alert"></div>
<div class="alert alert-danger d-none" role="alert" style="margin-top: 1rem; margin-bottom: 0rem;"></div>
<div class="form-group">
<label for="username" class="text-left" style="font-size: 1rem"><i class="bi bi-person-circle"></i> Username</label>
<input type="text" class="form-control" id="username" name="username" required>
<label for="username" class="text-left" style="font-size: 1rem"><i class="bi bi-person-circle"></i></label>
<input type="text" class="form-control" id="username" name="username" placeholder="Your username" required>
</div>
<div class="form-group">
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i> Password</label>
<input type="password" class="form-control" id="password" name="password" required>
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i></label>
<input type="password" class="form-control" id="password" name="password" placeholder="Your password" required>
</div>
<button type="submit" class="btn btn-dark" style="width: 100%;">Sign In</button>
<button type="submit" class="btn btn-dark" style="width: 100%">Sign In</button>
</form>
</div>
</main>
</div>
<small class="text-muted" style="position: fixed; bottom: 0; width: 100%; text-align: center; margin-bottom: 2rem">Version: {{ version }}</small>
</body>
{% include "footer.html" %}
<script>
$("button").on("click", function(e){
let req = $("input[required]");
let loginButton = $('button[type="submit"]');
loginButton.on("click", function(e){
e.preventDefault();
let $password = $("#password");
let $username = $("#username");
let req = [$password, $username];
let check = true
for (let i = 0; i < req.length; i++){
if ($(req[i]).val().length === 0){
$("button").html("Sign In");
loginButton.html("Sign In");
check = false;
$("input[required]").addClass("is-invalid");
$(req[i]).addClass("is-invalid");
break;
}
}
if (check){
e.preventDefault();
$(this).html("Signing In...").attr("disabled", "disabled");
$.ajax({
url: "/auth",
@@ -62,13 +67,17 @@
if (res.status === true){
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get("redirect")){
window.location.replace(urlParams.get("redirect"))
if (document.URL.substring(0, 5) == "http:"){
window.location.replace(`http://${urlParams.get("redirect")}`)
}else if (document.URL.substring(0, 5) == "https"){
window.location.replace(`https://${urlParams.get("redirect")}`)
}
}else{
window.location.replace("/");
}
}else{
$(".alert").html(res.msg).removeClass("d-none");
$("button").html("Sign In").removeAttr("disabled");
$(".alert").html(res.msg).removeClass("d-none").fadeIn();
loginButton.html("Sign In").removeAttr("disabled");
$("input[required]").addClass("is-invalid");
}
});

1
src/wgd.sh Executable file → Normal file
View File

@@ -33,6 +33,7 @@ help () {
}
_check_and_set_venv(){
# This function will not be using in v3.0
# deb/ubuntu users: might need a 'apt install python3.8-venv'
# set up the local environment
APP_ROOT=`pwd`