mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-12-09 01:51:20 +00:00
+
This commit is contained in:
parent
bc1f6edc5a
commit
65da97a367
@ -1,7 +1,7 @@
|
||||
#FROM nginx:alpine3.18
|
||||
FROM node:20.9.0-alpine3.18
|
||||
|
||||
RUN apk update && apk add --no-cache bash
|
||||
RUN apk update && apk add --no-cache bash nginx
|
||||
|
||||
USER node:node
|
||||
|
||||
|
||||
12
Global-Configs/Master-Key/master.conf
Normal file
12
Global-Configs/Master-Key/master.conf
Normal file
@ -0,0 +1,12 @@
|
||||
[Interface]
|
||||
PrivateKey = 4KX5qp4T8ANIoEk/eFJuYwi2g7/qD/6U9bzg2fUb60U=
|
||||
Address = 10.0.0.254/32
|
||||
DNS = 10.2.0.100,10.2.0.100
|
||||
MTU = 1420
|
||||
|
||||
[Peer]
|
||||
PublicKey = STk0MVroIsxKg0yMkorsQTiTFhk1R99yjP97Soe4MVA=
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = 0.0.0.0:443
|
||||
PersistentKeepalive = 21
|
||||
PresharedKey = nD4vaypUdgiHFfxDU5Fb6pWuN3KDVgKMsfIpndaYHj8=
|
||||
0
Global-Configs/Wiregate-Database/wgdashboard.db
Normal file
0
Global-Configs/Wiregate-Database/wgdashboard.db
Normal file
19
WG-Dash/.dockerignore
Normal file
19
WG-Dash/.dockerignore
Normal file
@ -0,0 +1,19 @@
|
||||
.vscode
|
||||
.DS_Store
|
||||
.idea
|
||||
src/db
|
||||
__pycache__
|
||||
src/test.py
|
||||
*.db
|
||||
master-key/master.conf
|
||||
env/
|
||||
src/wg-dashboard.ini
|
||||
src/static/pic.xd
|
||||
*.conf
|
||||
private_key.txt
|
||||
public_key.txt
|
||||
venv/**
|
||||
log/**
|
||||
release/*
|
||||
src/db/wgdashboard.db
|
||||
.jshintrc
|
||||
21
WG-Dash/Dockerfile
Normal file
21
WG-Dash/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /home/app
|
||||
RUN apk update && \
|
||||
apk add --no-cache python3 py3-pip py3-bcrypt py3-pillow uwsgi-python3 && \
|
||||
apk add --no-cache build-base linux-headers wireguard-tools openssl nginx && \
|
||||
apk add --no-cache net-tools iproute2 iptables ip6tables openssl-dev && \
|
||||
apk add --no-cache inotify-tools procps openresolv libc-dev pcre-dev && \
|
||||
mkdir /home/app/master-key
|
||||
|
||||
COPY ./src /home/app
|
||||
|
||||
|
||||
RUN pip install --upgrade pip --no-cache-dir --break-system-packages && \
|
||||
python3 -m pip install -r /home/app/requirements.txt --no-cache-dir --break-system-packages && \
|
||||
chmod u+x /home/app/entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/home/app/entrypoint.sh"]
|
||||
|
||||
|
||||
|
||||
201
WG-Dash/LICENSE
Normal file
201
WG-Dash/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
13
WG-Dash/src/FIREWALLS/Admins/wg0-dwn.sh
Normal file
13
WG-Dash/src/FIREWALLS/Admins/wg0-dwn.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=ADMINS
|
||||
WIREGUARD_LAN=10.0.0.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
26
WG-Dash/src/FIREWALLS/Admins/wg0-nat.sh
Normal file
26
WG-Dash/src/FIREWALLS/Admins/wg0-nat.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=ADMINS
|
||||
WIREGUARD_LAN=10.0.0.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# Accept traffic from any Wireguard IP address connected to the Wireguard server
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -j ACCEPT
|
||||
|
||||
# Allow traffic to the local loopback interface
|
||||
iptables -A $CHAIN_NAME -o lo -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
13
WG-Dash/src/FIREWALLS/Guest/wg3-dwn.sh
Normal file
13
WG-Dash/src/FIREWALLS/Guest/wg3-dwn.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=GUESTS
|
||||
WIREGUARD_LAN=192.168.20.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
30
WG-Dash/src/FIREWALLS/Guest/wg3-nat.sh
Normal file
30
WG-Dash/src/FIREWALLS/Guest/wg3-nat.sh
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=GUESTS
|
||||
WIREGUARD_LAN=192.168.20.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# Drop incoming traffic from guests to wg-dashboard
|
||||
iptables -A INPUT -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# DNS
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.100 -p udp --dport 53 -j ACCEPT
|
||||
# Drop traffic to your any private IP address
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -j DROP
|
||||
# Accept outgoing connections to HTTP(S) ports to any IP address (public because of rule above)
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 0.0.0.0/0 -p tcp -m multiport --dports 80,443 -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
20
WG-Dash/src/FIREWALLS/IPV6/wg0-dwn.sh
Normal file
20
WG-Dash/src/FIREWALLS/IPV6/wg0-dwn.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=IPV6ADMINS
|
||||
WIREGUARD_LAN=192.168.30.1/24
|
||||
WIREGUARD_LAN_IPV6=2001:db8:30:1::/64
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
ip6tables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN_IPV6
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
ip6tables -D FORWARD -j $CHAIN_NAME
|
||||
ip6tables -F $CHAIN_NAME
|
||||
ip6tables -X $CHAIN_NAME
|
||||
37
WG-Dash/src/FIREWALLS/IPV6/wg0-nat.sh
Normal file
37
WG-Dash/src/FIREWALLS/IPV6/wg0-nat.sh
Normal file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=IPV6ADMINS
|
||||
WIREGUARD_LAN=192.168.30.1/24
|
||||
WIREGUARD_LAN_IPV6=2001:db8:30:1::/64
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
ip6tables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN_IPV6
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
ip6tables -N $CHAIN_NAME
|
||||
ip6tables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
ip6tables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# Accept traffic from any Wireguard IP address connected to the Wireguard server
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -j ACCEPT
|
||||
ip6tables -A $CHAIN_NAME -s $WIREGUARD_LAN_IPV6 -i $WIREGUARD_INTERFACE -j ACCEPT
|
||||
|
||||
# Allow traffic to the local loopback interface
|
||||
iptables -A $CHAIN_NAME -o lo -j ACCEPT
|
||||
# Allow traffic to the local loopback interface
|
||||
ip6tables -A $CHAIN_NAME -o lo -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
ip6tables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
ip6tables -A $CHAIN_NAME -j RETURN
|
||||
20
WG-Dash/src/FIREWALLS/IPV6/wg1-dwn.sh
Normal file
20
WG-Dash/src/FIREWALLS/IPV6/wg1-dwn.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=IPV6MEMBERS
|
||||
WIREGUARD_LAN=192.168.40.1/24
|
||||
WIREGUARD_LAN_IPV6=2001:db8:40:1::/64
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
ip6tables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN_IPV6
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
ip6tables -D FORWARD -j $CHAIN_NAME
|
||||
ip6tables -F $CHAIN_NAME
|
||||
ip6tables -X $CHAIN_NAME
|
||||
50
WG-Dash/src/FIREWALLS/IPV6/wg1-nat.sh
Normal file
50
WG-Dash/src/FIREWALLS/IPV6/wg1-nat.sh
Normal file
@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=IPV6MEMBERS
|
||||
WIREGUARD_LAN=192.168.40.1/24
|
||||
WIREGUARD_LAN_IPV6=2001:db8:40:1::/64
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
ip6tables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN_IPV6
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
ip6tables -N $CHAIN_NAME
|
||||
ip6tables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
ip6tables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# Drop incoming traffic from wg1 to wg-dashboard
|
||||
iptables -A INPUT -i $WIREGUARD_INTERFACE -j DROP
|
||||
ip6tables -A INPUT -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Accept DNS from Adguard
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.100 -p udp --dport 53 -j ACCEPT
|
||||
# Accept Channels FEC
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.4 -p tcp --dport 80 -j ACCEPT
|
||||
# Drop Direct Forward traffic to Dockge
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.2 -j DROP
|
||||
# Drop Forward traffic to AdGuard Dashboard
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.100 -j DROP
|
||||
# Drop Forward traffic to Unbound (members should be restricted form accesing the means of modifying the network)
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.200 -j DROP
|
||||
# Drop Forward traffic to Channels Database
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.5 -j DROP
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.4 -j DROP
|
||||
|
||||
# Accept outgoing connections to HTTP(S) ports to any IP address (public because of rule above)
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 0.0.0.0/0 -p tcp -m multiport --dports 20,21,22,80,443,3389 -j ACCEPT
|
||||
# Accept outgoing connections to HTTP(S) ports to any IP address (public because of rule above)
|
||||
ip6tables -A $CHAIN_NAME -s $WIREGUARD_LAN_IPV6 -i $WIREGUARD_INTERFACE -d ::/0 -p tcp -m multiport --dports 20,21,22,80,443,3389 -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
ip6tables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
ip6tables -A $CHAIN_NAME -j RETURN
|
||||
13
WG-Dash/src/FIREWALLS/LAN-only-users/wg2-dwn.sh
Normal file
13
WG-Dash/src/FIREWALLS/LAN-only-users/wg2-dwn.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=LANP2P
|
||||
WIREGUARD_LAN=172.16.0.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
23
WG-Dash/src/FIREWALLS/LAN-only-users/wg2-nat.sh
Normal file
23
WG-Dash/src/FIREWALLS/LAN-only-users/wg2-nat.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=LANP2P
|
||||
WIREGUARD_LAN=172.16.0.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
#Accept on connections to peers of LAN zone only
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 172.16.0.1/24 -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
13
WG-Dash/src/FIREWALLS/Members/wg1-dwn.sh
Normal file
13
WG-Dash/src/FIREWALLS/Members/wg1-dwn.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=MEMEBERS
|
||||
WIREGUARD_LAN=192.168.10.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
|
||||
iptables -t nat -D POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Remove and delete the WIREGUARD_wg0 chain
|
||||
iptables -D FORWARD -j $CHAIN_NAME
|
||||
iptables -F $CHAIN_NAME
|
||||
iptables -X $CHAIN_NAME
|
||||
43
WG-Dash/src/FIREWALLS/Members/wg1-nat.sh
Normal file
43
WG-Dash/src/FIREWALLS/Members/wg1-nat.sh
Normal file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
WIREGUARD_INTERFACE=MEMEBERS
|
||||
WIREGUARD_LAN=192.168.10.1/24
|
||||
MASQUERADE_INTERFACE=eth0
|
||||
|
||||
iptables -t nat -I POSTROUTING -o $MASQUERADE_INTERFACE -j MASQUERADE -s $WIREGUARD_LAN
|
||||
|
||||
# Add a WIREGUARD_wg0 chain to the FORWARD chain
|
||||
CHAIN_NAME="WIREGUARD_$WIREGUARD_INTERFACE"
|
||||
iptables -N $CHAIN_NAME
|
||||
iptables -A FORWARD -j $CHAIN_NAME
|
||||
|
||||
# Accept related or established traffic
|
||||
iptables -A $CHAIN_NAME -o $WIREGUARD_INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# Drop incoming traffic from wg1 to wg-dashboard
|
||||
iptables -A INPUT -i $WIREGUARD_INTERFACE -j DROP
|
||||
# Accept DNS from Adguard
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.100 -p udp --dport 53 -j ACCEPT
|
||||
|
||||
|
||||
# Accept Channels FEC
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.4 -p tcp --dport 80 -j ACCEPT
|
||||
|
||||
# Drop Direct Forward traffic to Dockge
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.2 -j DROP
|
||||
# Drop Direct Forward traffic to AdGuard Dashboard
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.100 -j DROP
|
||||
# Drop Direct Forward traffic to Unbound
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.200 -j DROP
|
||||
# Drop Forward traffic to Channels Database
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.5 -j DROP
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 10.2.0.4 -j DROP
|
||||
|
||||
|
||||
# Accept outgoing connections to HTTP(S) ports to any IP address (public because of rule above)
|
||||
iptables -A $CHAIN_NAME -s $WIREGUARD_LAN -i $WIREGUARD_INTERFACE -d 0.0.0.0/0 -p tcp -m multiport --dports 20,21,22,80,443,3389 -j ACCEPT
|
||||
|
||||
# Drop everything else coming through the Wireguard interface
|
||||
iptables -A $CHAIN_NAME -i $WIREGUARD_INTERFACE -j DROP
|
||||
|
||||
# Return to FORWARD chain
|
||||
iptables -A $CHAIN_NAME -j RETURN
|
||||
55
WG-Dash/src/api.py
Normal file
55
WG-Dash/src/api.py
Normal file
@ -0,0 +1,55 @@
|
||||
import ipaddress, subprocess, datetime, os, util
|
||||
from util import *
|
||||
|
||||
notEnoughParameter = {"status": False, "reason": "Please provide all required parameters."}
|
||||
good = {"status": True, "reason": ""}
|
||||
|
||||
def ret(status=True, reason="", data=""):
|
||||
return {"status": status, "reason": reason, "data": data}
|
||||
|
||||
def togglePeerAccess(data, g):
|
||||
checkUnlock = g.cur.execute(f"SELECT * FROM {data['config']} WHERE id='{data['peerID']}'").fetchone()
|
||||
if checkUnlock:
|
||||
moveUnlockToLock = g.cur.execute(
|
||||
f"INSERT INTO {data['config']}_restrict_access SELECT * FROM {data['config']} WHERE id = '{data['peerID']}'")
|
||||
if g.cur.rowcount == 1:
|
||||
print(g.cur.rowcount)
|
||||
print(util.deletePeers(data['config'], [data['peerID']], g.cur, g.db))
|
||||
else:
|
||||
moveLockToUnlock = g.cur.execute(
|
||||
f"SELECT * FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'").fetchone()
|
||||
try:
|
||||
if len(moveLockToUnlock[-1]) == 0:
|
||||
status = subprocess.check_output(
|
||||
f"wg set {data['config']} peer {moveLockToUnlock[0]} allowed-ips {moveLockToUnlock[11]}",
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
else:
|
||||
now = str(datetime.datetime.now().strftime("%m%d%Y%H%M%S"))
|
||||
f_name = now + "_tmp_psk.txt"
|
||||
f = open(f_name, "w+")
|
||||
f.write(moveLockToUnlock[-1])
|
||||
f.close()
|
||||
subprocess.check_output(
|
||||
f"wg set {data['config']} peer {moveLockToUnlock[0]} allowed-ips {moveLockToUnlock[11]} preshared-key {f_name}",
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
os.remove(f_name)
|
||||
status = subprocess.check_output(f"wg-quick save {data['config']}", shell=True, stderr=subprocess.STDOUT)
|
||||
g.cur.execute(
|
||||
f"INSERT INTO {data['config']} SELECT * FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'")
|
||||
if g.cur.rowcount == 1:
|
||||
g.cur.execute(f"DELETE FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'")
|
||||
|
||||
except subprocess.CalledProcessError as exc:
|
||||
return {"status": False, "reason": str(exc.output.strip())}
|
||||
return good
|
||||
|
||||
|
||||
|
||||
class settings:
|
||||
def setTheme(self, theme, config, setConfig):
|
||||
themes = ['light', 'dark']
|
||||
if theme not in themes:
|
||||
return ret(status=False, reason="Theme does not exist")
|
||||
config['Server']['dashboard_theme'] = theme
|
||||
setConfig(config)
|
||||
return ret()
|
||||
1818
WG-Dash/src/dashboard.py
Normal file
1818
WG-Dash/src/dashboard.py
Normal file
File diff suppressed because it is too large
Load Diff
99
WG-Dash/src/entrypoint.sh
Normal file
99
WG-Dash/src/entrypoint.sh
Normal file
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
chmod u+x /home/app/wgd.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/Admins/wg0-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/Admins/wg0-nat.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/Members/wg1-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/Members/wg1-nat.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/LAN-only-users/wg2-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/LAN-only-users/wg2-nat.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/Guest/wg3-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/Guest/wg3-nat.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/IPV6/wg0-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/IPV6/wg0-nat.sh
|
||||
|
||||
chmod u+x /home/app/FIREWALLS/IPV6/wg1-dwn.sh
|
||||
chmod u+x /home/app/FIREWALLS/IPV6/wg1-nat.sh
|
||||
|
||||
|
||||
|
||||
if [ ! -f "/etc/wireguard/wg0.conf" ]; then
|
||||
/home/app/wgd.sh newconfig
|
||||
|
||||
fi
|
||||
run_wireguard_up() {
|
||||
config_files=$(find /etc/wireguard -type f -name "*.conf")
|
||||
|
||||
for file in $config_files; do
|
||||
config_name=$(basename "$file" ".conf")
|
||||
chmod 600 "/etc/wireguard/$config_name.conf"
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
config_nginx () {
|
||||
rm /etc/nginx/http.d/default.conf
|
||||
cat <<EOF > "/etc/nginx/http.d/default.conf"
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass 127.0.0.1:10086; # uWSGI service address and port
|
||||
}
|
||||
|
||||
# Set the location of the uWSGI static folder
|
||||
location /static/ {
|
||||
alias /home/app/static/;
|
||||
}
|
||||
|
||||
# Set security headers
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
|
||||
# Disable server version information
|
||||
server_tokens off;
|
||||
|
||||
# Configure error pages
|
||||
error_page 400 401 402 403 404 /error.html;
|
||||
location = /error.html {
|
||||
root /path/to/error/pages;
|
||||
}
|
||||
|
||||
# Deny access to hidden files
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
run_wireguard_up #>/dev/null 2>&1 &&
|
||||
wg-quick up ADMINS
|
||||
config_nginx &&
|
||||
nginx &&
|
||||
/home/app/wgd.sh start
|
||||
|
||||
5
WG-Dash/src/requirements.txt
Normal file
5
WG-Dash/src/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Flask
|
||||
ifcfg
|
||||
configparser
|
||||
icmplib
|
||||
flask-qrcode
|
||||
7
WG-Dash/src/static/css/bootstrap.min.css
vendored
Normal file
7
WG-Dash/src/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
WG-Dash/src/static/css/bootstrap.min.css.map
Normal file
1
WG-Dash/src/static/css/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
934
WG-Dash/src/static/css/dashboard.css
Normal file
934
WG-Dash/src/static/css/dashboard.css
Normal file
@ -0,0 +1,934 @@
|
||||
body {
|
||||
font-size: .875rem;
|
||||
/*font-family: 'Poppins', sans-serif;*/
|
||||
}
|
||||
|
||||
.codeFont{
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
.feather {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
/* Behind the navbar */
|
||||
padding: 48px 0 0;
|
||||
/* Height of navbar */
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.sidebar-sticky {
|
||||
position: relative;
|
||||
top: 0;
|
||||
height: calc(100vh - 48px);
|
||||
padding-top: .5rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
/* Scrollable contents if viewport is shorter than content. */
|
||||
}
|
||||
|
||||
@supports ((position: -webkit-sticky) or (position: sticky)) {
|
||||
.sidebar-sticky {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .nav-link, .bottomNavContainer .nav-link{
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
transition: 0.2s cubic-bezier(0.82, -0.07, 0, 1.01);
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
padding-left: 30px;
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
|
||||
.sidebar .nav-link .feather {
|
||||
margin-right: 4px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active, .bottomNavContainer .nav-link.active {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover .feather,
|
||||
.sidebar .nav-link.active .feather {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: .75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Navbar
|
||||
*/
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
font-size: 1rem;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler {
|
||||
top: .25rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.form-control:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.navbar .form-control {
|
||||
padding: .75rem 1rem;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.form-control-dark {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
border-color: rgba(255, 255, 255, .1);
|
||||
}
|
||||
|
||||
.form-control-dark:focus {
|
||||
border-color: transparent;
|
||||
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50px;
|
||||
display: inline-block;
|
||||
margin-left: auto !important;
|
||||
}
|
||||
|
||||
.dot-running {
|
||||
background-color: #28a745!important;
|
||||
box-shadow: 0 0 0 0.2rem #28a74545;
|
||||
}
|
||||
|
||||
.h6-dot-running {
|
||||
margin-left: 0.3rem;
|
||||
}
|
||||
|
||||
.dot-stopped {
|
||||
background-color: #6c757d!important;
|
||||
}
|
||||
|
||||
.card-running {
|
||||
border-color: #28a745;
|
||||
}
|
||||
|
||||
.info h6 {
|
||||
line-break: anywhere;
|
||||
transition: all 0.4s cubic-bezier(0.96, -0.07, 0.34, 1.01);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.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 {
|
||||
border: none !important;
|
||||
padding: 0;
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
|
||||
.btn-control:hover{
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.btn-control:active,
|
||||
.btn-control:focus {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-qrcode-peer {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.btn-qrcode-peer:active,
|
||||
.btn-qrcode-peer:hover {
|
||||
transform: scale(0.9) rotate(180deg);
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.btn-download-peer:active,
|
||||
.btn-download-peer:hover {
|
||||
color: #17a2b8 !important;
|
||||
transform: translateY(5px);
|
||||
}
|
||||
|
||||
.share_peer_btn_group .btn-control {
|
||||
margin: 0 0 0 1rem;
|
||||
padding: 0 !important;
|
||||
transition: all 0.4s cubic-bezier(1, -0.43, 0, 1.37);
|
||||
}
|
||||
|
||||
.btn-control:hover {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.btn-delete-peer:hover {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.btn-lock-peer:hover {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.btn-lock-peer.lock{
|
||||
color: #6c757d
|
||||
}
|
||||
|
||||
.btn-lock-peer.lock:hover{
|
||||
color: #6c757d
|
||||
}
|
||||
|
||||
.btn-control.btn-outline-primary:hover{
|
||||
color: #007bff
|
||||
}
|
||||
|
||||
/* .btn-setting-peer:hover {
|
||||
color: #007bff
|
||||
} */
|
||||
|
||||
.btn-download-peer:hover {
|
||||
color: #17a2b8;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.card-col {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.switch:hover {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.btn-group-label:hover {
|
||||
color: #007bff;
|
||||
border-color: #007bff;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.peer_data_group {
|
||||
text-align: right;
|
||||
display: flex;
|
||||
margin-bottom: 0.5rem
|
||||
}
|
||||
|
||||
.peer_data_group p {
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0;
|
||||
margin-right: 1rem
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.peer_data_group {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.index-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.peer_list {
|
||||
margin-bottom: 7rem
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.add_btn {
|
||||
bottom: 1.5rem !important;
|
||||
}
|
||||
.peer_list {
|
||||
margin-bottom: 7rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-manage-group {
|
||||
z-index: 99;
|
||||
position: fixed;
|
||||
bottom: 3rem;
|
||||
right: 2rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.btn-manage-group .setting_btn_menu {
|
||||
position: absolute;
|
||||
top: -124px;
|
||||
background-color: white;
|
||||
padding: 1rem 0;
|
||||
right: 0;
|
||||
box-shadow: 0 10px 20px rgb(0 0 0 / 19%), 0 6px 6px rgb(0 0 0 / 23%);
|
||||
border-radius: 10px;
|
||||
min-width: 250px;
|
||||
display: none;
|
||||
transform: translateY(-30px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s cubic-bezier(0.58, 0.03, 0.05, 1.28);
|
||||
}
|
||||
|
||||
.btn-manage-group .setting_btn_menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.setting_btn_menu.showing {
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.setting_btn_menu a {
|
||||
display: flex;
|
||||
padding: 0.5rem 1rem;
|
||||
transition: all 0.1s ease-in-out;
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.setting_btn_menu a:hover {
|
||||
background-color: #efefef;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.setting_btn_menu a i {
|
||||
margin-right: auto !important;
|
||||
}
|
||||
|
||||
.add_btn {
|
||||
height: 54px;
|
||||
z-index: 99;
|
||||
border-radius: 100px !important;
|
||||
padding: 0 14px;
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
|
||||
margin-right: 1rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.setting_btn {
|
||||
height: 54px;
|
||||
z-index: 99;
|
||||
border-radius: 100px !important;
|
||||
padding: 0 14px;
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotating
|
||||
/* Safari and Chrome */
|
||||
|
||||
{
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.rotating::before {
|
||||
-webkit-animation: rotating 0.75s linear infinite;
|
||||
-moz-animation: rotating 0.75s linear infinite;
|
||||
-ms-animation: rotating 0.75s linear infinite;
|
||||
-o-animation: rotating 0.75s linear infinite;
|
||||
animation: rotating 0.75s linear infinite;
|
||||
}
|
||||
|
||||
.peer_private_key_textbox_switch {
|
||||
position: absolute;
|
||||
right: 2rem;
|
||||
transform: translateY(-28px);
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#peer_private_key_textbox,
|
||||
#private_key,
|
||||
#public_key,
|
||||
#peer_preshared_key_textbox {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
transition: 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.key {
|
||||
transition: 0.2s ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.key:hover {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.peer_list .card .button-group {
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
/*padding: 0.6rem 0.9em;*/
|
||||
}
|
||||
|
||||
.login-box #username,
|
||||
.login-box #password {
|
||||
padding: 0.6rem calc( 0.9rem + 32px);
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.login-box label[for="username"],
|
||||
.login-box 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;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
@-webkit-keyframes loading {
|
||||
0% {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
50% {
|
||||
background-color: #adadad;
|
||||
}
|
||||
100% {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes loading {
|
||||
0% {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
50% {
|
||||
background-color: #adadad;
|
||||
}
|
||||
100% {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
.conf_card {
|
||||
transition: 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.conf_card:hover {
|
||||
border-color: #007bff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.info_loading {
|
||||
/* animation: loading 2s infinite ease-in-out;
|
||||
/* border-radius: 5px; */
|
||||
height: 19.19px;
|
||||
/* transition: 0.3s ease-in-out; */
|
||||
|
||||
/* transform: translateX(40px); */
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
#conf_status_btn {
|
||||
transition: 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
#conf_status_btn.info_loading {
|
||||
height: 38px;
|
||||
border-radius: 5px;
|
||||
animation: loading 3s infinite ease-in-out;
|
||||
}
|
||||
|
||||
#qrcode_img img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#selected_ip_list .badge,
|
||||
#selected_peer_list .badge {
|
||||
margin: 0.1rem
|
||||
}
|
||||
|
||||
#add_modal.ip_modal_open {
|
||||
transition: filter 0.2s ease-in-out;
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
|
||||
#delete_bulk_modal .list-group a.active {
|
||||
background-color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
#selected_peer_list {
|
||||
max-height: 80px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.no-response {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
background: #000000ba;
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: all 1s ease-in-out;
|
||||
}
|
||||
|
||||
.no-response.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.no-response.active.show {
|
||||
opacity: 100;
|
||||
}
|
||||
|
||||
.no-response .container>* {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-responding {
|
||||
transition: all 1s ease-in-out;
|
||||
filter: blur(10px);
|
||||
}
|
||||
|
||||
pre.index-alert {
|
||||
margin-bottom: 0;
|
||||
padding: 1rem;
|
||||
background-color: #343a40;
|
||||
border: 1px solid rgba(0, 0, 0, .125);
|
||||
border-radius: .25rem;
|
||||
margin-top: 1rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.peerNameCol {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.2rem
|
||||
}
|
||||
|
||||
.peerName {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.peerLightContainer {
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
margin-left: auto !important;
|
||||
}
|
||||
|
||||
.conf_card .dot,
|
||||
.info .dot {
|
||||
transform: translateX(10px);
|
||||
}
|
||||
|
||||
#config_body {
|
||||
transition: 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
#config_body.firstLoading {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.chartTitle {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chartControl {
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chartTitle h6 {
|
||||
margin-bottom: 0;
|
||||
line-height: 1;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.chartContainer.fullScreen {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
background-color: white;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc( 100% + 15px);
|
||||
height: 100%;
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
.chartContainer.fullScreen .col-sm {
|
||||
padding-right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chartContainer.fullScreen .chartCanvasContainer {
|
||||
width: 100%;
|
||||
height: calc( 100% - 47px) !important;
|
||||
max-height: calc( 100% - 47px) !important;
|
||||
}
|
||||
|
||||
#switch{
|
||||
transition: all 200ms ease-in;
|
||||
}
|
||||
|
||||
.toggle--switch{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toggleLabel{
|
||||
width: 64px;
|
||||
height: 32px;
|
||||
background-color: #6c757d17;
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: 2px solid #6c757d8c;
|
||||
border-radius: 100px;
|
||||
transition: all 200ms ease-in;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.toggle--switch.waiting + .toggleLabel{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.toggleLabel::before{
|
||||
background-color: #6c757d;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
content: "";
|
||||
border-radius: 100px;
|
||||
margin: 1px;
|
||||
position: absolute;
|
||||
animation-name: off;
|
||||
animation-duration: 350ms;
|
||||
animation-fill-mode: forwards;
|
||||
transition: all 200ms ease-in;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggleLabel:hover::before{
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
|
||||
.toggle--switch:checked + .toggleLabel{
|
||||
background-color: #007bff17 !important;
|
||||
border: 2px solid #007bff8c;
|
||||
}
|
||||
|
||||
.toggle--switch:checked + .toggleLabel::before{
|
||||
background-color: #007bff;
|
||||
animation-name: on;
|
||||
animation-duration: 350ms;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes on {
|
||||
0%{
|
||||
left: 0px;
|
||||
}
|
||||
60%{
|
||||
left: 0px;
|
||||
width: 40px;
|
||||
}
|
||||
100%{
|
||||
left: 32px;
|
||||
width: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes off {
|
||||
0%{
|
||||
left: 32px;
|
||||
}
|
||||
60%{
|
||||
left: 18px;
|
||||
width: 40px;
|
||||
}
|
||||
100%{
|
||||
left: 0px;
|
||||
width: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
.toastContainer{
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
|
||||
.toast{
|
||||
min-width: 300px;
|
||||
background-color: rgba(255,255,255,1);
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.toast-header{
|
||||
background-color: rgba(255,255,255);
|
||||
}
|
||||
|
||||
.toast-progressbar{
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: #007bff;
|
||||
border-bottom-left-radius: .25rem;
|
||||
}
|
||||
|
||||
.addConfigurationAvailableIPs{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.input-feedback{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#addConfigurationModal label{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#addConfigurationModal label a{
|
||||
margin-left: auto !important;
|
||||
}
|
||||
|
||||
#reGeneratePrivateKey{
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
|
||||
.addConfigurationToggleStatus.waiting{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/*.conf_card .card-body .row .card-col{*/
|
||||
/* margin-bottom: 0.5rem;*/
|
||||
/*}*/
|
||||
|
||||
.peerDataUsageChartContainer{
|
||||
min-height: 50vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.peerDataUsageChartControl{
|
||||
display: block !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.peerDataUsageChartControl .switchUnit{
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
.peerDataUsageChartControl .switchTimePeriod{
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px){
|
||||
#peerDataUsage .modal-xl {
|
||||
max-width: 95vw;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom{
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px){
|
||||
.bottom{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.btn-manage-group{
|
||||
bottom: calc( 3rem + 40px + env(safe-area-inset-bottom, 5px));
|
||||
}
|
||||
|
||||
main{
|
||||
padding-bottom: calc( 3rem + 40px + env(safe-area-inset-bottom, 5px));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bottomNavContainer{
|
||||
display: flex;
|
||||
color: #333;
|
||||
padding-bottom: env(safe-area-inset-bottom, 5px);
|
||||
box-shadow: inset 0 1px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
.bottomNavButton{
|
||||
width: 25vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 0.7rem 0;
|
||||
color: rgba(51, 51, 51, 0.5);
|
||||
cursor: pointer;
|
||||
transition: all ease-in 0.2s;
|
||||
}
|
||||
|
||||
.bottomNavButton.active{
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.bottomNavButton i{
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.bottomNavButton .subNav{
|
||||
width: 100vw;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #272b30;
|
||||
display: none;
|
||||
animation-duration: 400ms;
|
||||
padding-bottom: env(safe-area-inset-bottom, 5px);
|
||||
}
|
||||
|
||||
.bottomNavButton .subNav.active{
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.bottomNavButton .subNav .nav .nav-item .nav-link{
|
||||
padding: 0.7rem 1rem;
|
||||
}
|
||||
|
||||
.bottomNavWrapper{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #000000a1;
|
||||
position: fixed;
|
||||
z-index: 1030;
|
||||
display: none;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.bottomNavWrapper.active{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sb-update-url .dot-running{
|
||||
transform: translateX(10px);
|
||||
}
|
||||
|
||||
.list-group-item{
|
||||
transition: all 0.1s ease-in;
|
||||
}
|
||||
|
||||
.theme-switch-btn{
|
||||
width: 100%;
|
||||
}
|
||||
1
WG-Dash/src/static/css/dashboard.min.css
vendored
Normal file
1
WG-Dash/src/static/css/dashboard.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
391
WG-Dash/src/static/css/theme/dark.css
Normal file
391
WG-Dash/src/static/css/theme/dark.css
Normal file
@ -0,0 +1,391 @@
|
||||
:root {
|
||||
--green: hsl(120deg, 30%, 50%) !important;
|
||||
--blue: hsl(235deg, 60%, 60%) !important;
|
||||
--red: hsl(0deg, 60%, 60%) !important;
|
||||
--magenta: hsl(315deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #222222;
|
||||
color: hsl(0deg, 0%, 80%);
|
||||
}
|
||||
|
||||
a.text-primary:focus, a.text-primary:hover {
|
||||
color: hsl(235deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
border-color: hsl(235deg, 60%, 60%) !important;
|
||||
background: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: hsl(235deg, 60%, 50%) !important;
|
||||
border-color: hsl(235deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.btn-outline-primary {
|
||||
color: hsl(235deg, 60%, 60%) !important;
|
||||
border-color: hsl(235deg, 60%, 60%) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.btn-outline-primary:hover, .btn-outline-primary.active {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
}
|
||||
.btn-outline-primary.active {
|
||||
background-color: hsl(235deg, 60%, 60%) !important;
|
||||
border-color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
.btn-outline-primary:hover {
|
||||
background-color: hsl(235deg, 60%, 50%) !important;
|
||||
border-color: hsl(235deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
border-color: hsl(120deg, 30%, 50%) !important;
|
||||
background: hsl(120deg, 30%, 50%) !important;
|
||||
}
|
||||
.btn-success:hover {
|
||||
background-color: hsl(120deg, 30%, 40%) !important;
|
||||
border-color: hsl(120deg, 30%, 40%) !important;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
background-color: #272727;
|
||||
border-color: #272727;
|
||||
color: white;
|
||||
}
|
||||
.list-group-item:hover {
|
||||
background-color: #333333;
|
||||
border-color: #333333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.delete-peer-bulk-badge.badge-danger {
|
||||
background-color: hsl(0deg, 60%, 60%);
|
||||
}
|
||||
.delete-peer-bulk-badge.badge-danger:hover {
|
||||
background-color: hsl(0deg, 60%, 50%);
|
||||
}
|
||||
|
||||
#delete_bulk_modal .list-group a.active {
|
||||
background-color: hsl(0deg, 60%, 60%);
|
||||
border: hsl(0deg, 60%, 60%);
|
||||
}
|
||||
#delete_bulk_modal .list-group a.active:hover {
|
||||
background-color: hsl(0deg, 60%, 50%);
|
||||
border: hsl(0deg, 60%, 50%);
|
||||
}
|
||||
|
||||
#available_ip_modal .list-group a.active {
|
||||
background-color: hsl(235deg, 60%, 60%);
|
||||
border: hsl(235deg, 60%, 60%);
|
||||
}
|
||||
#available_ip_modal .list-group a.active:hover {
|
||||
background-color: hsl(235deg, 60%, 50%);
|
||||
border: hsl(235deg, 60%, 50%);
|
||||
}
|
||||
|
||||
.available-ip-badge.badge-primary {
|
||||
background-color: hsl(235deg, 60%, 60%);
|
||||
}
|
||||
.available-ip-badge.badge-primary:hover {
|
||||
background-color: hsl(235deg, 60%, 50%);
|
||||
}
|
||||
|
||||
.btn-outline-success {
|
||||
color: hsl(120deg, 30%, 50%) !important;
|
||||
border-color: hsl(120deg, 30%, 50%) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.btn-outline-success:hover, .btn-outline-success.active {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
}
|
||||
.btn-outline-success.active {
|
||||
background-color: hsl(120deg, 30%, 50%) !important;
|
||||
border-color: hsl(120deg, 30%, 50%) !important;
|
||||
}
|
||||
.btn-outline-success:hover {
|
||||
background-color: hsl(120deg, 30%, 40%) !important;
|
||||
border-color: hsl(120deg, 30%, 40%) !important;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
border-color: hsl(0deg, 60%, 60%) !important;
|
||||
background: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
.btn-danger:hover {
|
||||
background-color: hsl(0deg, 60%, 50%) !important;
|
||||
border-color: hsl(0deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.btn-outline-danger {
|
||||
color: hsl(0deg, 60%, 60%) !important;
|
||||
border-color: hsl(0deg, 60%, 60%) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.btn-outline-danger:hover, .btn-outline-danger.active {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
}
|
||||
.btn-outline-danger.active {
|
||||
background-color: hsl(0deg, 60%, 60%) !important;
|
||||
border-color: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
.btn-outline-danger:hover {
|
||||
background-color: hsl(0deg, 60%, 50%) !important;
|
||||
border-color: hsl(0deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
border-color: #424242 !important;
|
||||
background: #424242 !important;
|
||||
}
|
||||
.btn-secondary:hover {
|
||||
background-color: #383838 !important;
|
||||
border-color: #383838 !important;
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
color: #424242 !important;
|
||||
border-color: #424242 !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.btn-outline-secondary:hover, .btn-outline-secondary.active {
|
||||
color: hsl(0deg, 0%, 90%) !important;
|
||||
}
|
||||
.btn-outline-secondary.active {
|
||||
background-color: #424242 !important;
|
||||
border-color: #424242 !important;
|
||||
}
|
||||
.btn-outline-secondary:hover {
|
||||
background-color: #383838 !important;
|
||||
border-color: #383838 !important;
|
||||
}
|
||||
|
||||
.btn-control.btn-lock-peer.lock {
|
||||
color: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
.btn-control.btn-lock-peer.lock:hover {
|
||||
color: hsl(0deg, 60%, 50%) !important;
|
||||
}
|
||||
.btn-control:hover {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.btn-control:hover.btn-outline-primary {
|
||||
color: hsl(235deg, 60%, 50%) !important;
|
||||
}
|
||||
.btn-control:hover.btn-outline-success {
|
||||
color: hsl(120deg, 30%, 40%) !important;
|
||||
}
|
||||
.btn-control:hover.btn-outline-danger {
|
||||
color: hsl(0deg, 60%, 50%) !important;
|
||||
}
|
||||
.btn-control:hover.btn-outline-secondary {
|
||||
color: #383838 !important;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: #2c2c2c !important;
|
||||
border-color: transparent !important;
|
||||
color: hsl(0deg, 0%, 80%) !important;
|
||||
}
|
||||
|
||||
.form-control:disabled {
|
||||
color: #777777 !important;
|
||||
}
|
||||
|
||||
.card .form-control {
|
||||
background: #2c2c2c !important;
|
||||
}
|
||||
|
||||
.conf_card a {
|
||||
color: hsl(235deg, 60%, 60%);
|
||||
}
|
||||
.conf_card:hover {
|
||||
border-color: hsl(235deg, 60%, 60%);
|
||||
}
|
||||
|
||||
.sidebar .nav-link,
|
||||
.bottomNavContainer .nav-link {
|
||||
color: hsl(0deg, 0%, 80%);
|
||||
}
|
||||
.sidebar .nav-link:hover,
|
||||
.bottomNavContainer .nav-link:hover {
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
nav#sidebarMenu.col-md-3.col-lg-2.d-md-block.bg-light.sidebar.collapse,
|
||||
.navbar-brand,
|
||||
.bg-dark {
|
||||
background-color: #1e1e1e !important;
|
||||
background: #1e1e1e !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #272727;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: hsl(0deg, 0%, 50%) !important;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: hsl(120deg, 30%, 50%) !important;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: hsl(190deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
a.text-success:focus,
|
||||
a.text-success:hover {
|
||||
color: hsl(120deg, 30%, 40%) !important;
|
||||
}
|
||||
|
||||
a.text-danger:focus,
|
||||
a.text-danger:hover {
|
||||
color: hsl(0deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
a.text-info:focus,
|
||||
a.text-info:hover {
|
||||
color: hsl(190deg, 60%, 50%) !important;
|
||||
}
|
||||
|
||||
.dot-running {
|
||||
background-color: hsl(120deg, 30%, 50%) !important;
|
||||
}
|
||||
|
||||
.card-running {
|
||||
border-color: hsl(120deg, 30%, 50%);
|
||||
}
|
||||
|
||||
.toggle--switch:checked + .toggleLabel::before {
|
||||
background-color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
.toggle--switch:checked + .toggleLabel {
|
||||
background-color: #2e336b !important;
|
||||
border-color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active,
|
||||
.bottomNavContainer .nav-link.active {
|
||||
color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #2e2e2e;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
background-color: #1e1e1e;
|
||||
border-color: #2e2e2e;
|
||||
}
|
||||
|
||||
code {
|
||||
color: hsl(315deg, 60%, 60%);
|
||||
}
|
||||
|
||||
.close {
|
||||
color: hsl(0deg, 0%, 80%);
|
||||
text-shadow: none;
|
||||
}
|
||||
.close:hover {
|
||||
color: hsl(0deg, 0%, 70%);
|
||||
}
|
||||
|
||||
.chartContainer.fullScreen {
|
||||
background-color: #222222 !important;
|
||||
}
|
||||
|
||||
.popover {
|
||||
background-color: #333333 !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
color: hsl(0deg, 0%, 80%) !important;
|
||||
}
|
||||
|
||||
div.toast {
|
||||
background-color: #424242 !important;
|
||||
}
|
||||
div.toast div.toast-header {
|
||||
background-color: #333333 !important;
|
||||
color: hsl(0deg, 0%, 80%) !important;
|
||||
border-bottom-color: #424242 !important;
|
||||
}
|
||||
div.toast div.toast-body {
|
||||
background-color: #383838 !important;
|
||||
color: hsl(0deg, 0%, 80%) !important;
|
||||
}
|
||||
div.toast div.toast-body.text-danger {
|
||||
color: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
div.toast div.toast-progressbar {
|
||||
background-color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
div.toast div.toast-progressbar.bg-danger {
|
||||
background-color: hsl(0deg, 60%, 60%) !important;
|
||||
}
|
||||
|
||||
.bs-popover-auto[x-placement^=right] > .arrow::after,
|
||||
.bs-popover-right > .arrow::after {
|
||||
border-right-color: #333333 !important;
|
||||
}
|
||||
|
||||
.btn-manage-group .setting_btn_menu {
|
||||
background-color: #2c2c2c !important;
|
||||
}
|
||||
|
||||
.setting_btn_menu a:hover {
|
||||
background-color: #333333 !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
color: hsl(0deg, 0%, 80%) !important;
|
||||
}
|
||||
.table th,
|
||||
.table td {
|
||||
border-color: #333333 !important;
|
||||
}
|
||||
|
||||
.btn-outline-primary.focus, .btn-outline-primary:focus, .btn-primary.focus, .btn-primary:focus {
|
||||
box-shadow: 0 0 0 0.2rem rgba(144, 153, 255, 0.29) !important;
|
||||
}
|
||||
|
||||
.bottomNav {
|
||||
background-color: #272727 !important;
|
||||
}
|
||||
.bottomNav .bottomNavButton {
|
||||
color: hsl(0deg, 0%, 60%);
|
||||
}
|
||||
.bottomNav .bottomNavButton.active {
|
||||
color: hsl(235deg, 60%, 60%) !important;
|
||||
}
|
||||
.bottomNav .subNav {
|
||||
background-color: #272727 !important;
|
||||
}
|
||||
|
||||
.key:hover {
|
||||
color: hsl(235deg, 60%, 60%);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=dark.css.map */
|
||||
1
WG-Dash/src/static/css/theme/dark.css.map
Normal file
1
WG-Dash/src/static/css/theme/dark.css.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["dark.scss"],"names":[],"mappings":"AAgCA;EACE;EACA;EACA;EACA;;;AAGF;EACE,YAvCS;EAwCT,OAdS;;;AAiBX;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE,kBAzFS;EA0FT,cA1FS;EA2FT;;AAEA;EACE,kBA3FO;EA4FP,cA5FO;EA6FP;;;AAMJ;EACE,kBA3FQ;;AA4FR;EACE,kBA9FM;;;AAoGN;EACE,kBApGI;EAqGJ,QArGI;;AAuGJ;EACE,kBAzGE;EA0GF,QA1GE;;;AAkHN;EACE,kBA/GK;EAgHL,QAhHK;;AAkHL;EACE,kBApHG;EAqHH,QArHG;;;AA2HX;EACE,kBA3HS;;AA4HT;EACE,kBA9HO;;;AAkIX;EACE;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAKF;EACE;;AACA;EACE;;AAIJ;EACE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAKN;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIA;EACE,OAnQO;;AAqQT;EACE,cAtQO;;;AA0QX;AAAA;EAEE,OAnQS;;AAqQT;AAAA;EACE,YAhSO;;;AAoSX;AAAA;AAAA;EAGE;EACA;;;AAGF;EACE,YA1SS;;;AA6SX;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE,cA5UU;;;AA+UZ;EACE;;;AAEF;EACE;EACA;;;AAGF;AAAA;EAEE;;;AAGF;EACE,cApWS;;;AAuWX;EACE,kBA5WS;;;AA+WX;AAAA;EAEE,kBAlXS;EAmXT,cA9WS;;;AAiXX;EACE,OA/VY;;;AAkWd;EACE,OAhWS;EAiWT;;AAEA;EACE,OAnWO;;;AAuWX;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;AAEA;AAAA;EAEE;;;AAKJ;EACE;;;AAIA;EACE;;AAIA;EACE,OAhbK;;AAobT;EACE;;AAGF;EACE;;;AAKJ;EACE,OA1cS","file":"dark.css"}
|
||||
1
WG-Dash/src/static/css/theme/dark.min.css
vendored
Normal file
1
WG-Dash/src/static/css/theme/dark.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
WG-Dash/src/static/css/theme/dark.min.css.map
Normal file
1
WG-Dash/src/static/css/theme/dark.min.css.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["dark.scss"],"names":[],"mappings":"AAgCA,MACE,0CACA,yCACA,sCACA,4CAGF,KACE,WAvCS,KAwCT,MAdS,KAiBX,0CACE,yBAGF,aACE,yBACA,gCACA,8BAEA,mBACE,oCACA,gCAIJ,qBACE,yBACA,gCACA,oCAEA,uDAEE,yBAGF,4BACE,oCACA,gCAGF,2BACE,oCACA,gCAIJ,aACE,yBACA,gCACA,8BAEA,mBACE,oCACA,gCAIJ,iBACE,iBAzFS,QA0FT,aA1FS,QA2FT,WAEA,uBACE,iBA3FO,KA4FP,aA5FO,KA6FP,WAMJ,qCACE,iBA3FQ,QA4FR,2CACE,iBA9FM,KAoGN,wCACE,iBApGI,QAqGJ,OArGI,QAuGJ,8CACE,iBAzGE,KA0GF,OA1GE,KAkHN,yCACE,iBA/GK,QAgHL,OAhHK,QAkHL,+CACE,iBApHG,QAqHH,OArHG,QA2HX,kCACE,iBA3HS,QA4HT,wCACE,iBA9HO,QAkIX,qBACE,yBACA,gCACA,oCAEA,uDAEE,yBAGF,4BACE,oCACA,gCAGF,2BACE,oCACA,gCAIJ,YACE,yBACA,gCACA,8BAEA,kBACE,iCACA,6BAIJ,oBACE,yBACA,gCACA,oCAEA,qDAEE,yBAGF,2BACE,oCACA,gCAGF,0BACE,iCACA,6BAIJ,eACE,yBACA,gCACA,8BAEA,qBACE,oCACA,gCAIJ,uBACE,yBACA,gCACA,oCAEA,2DAEE,yBAGF,8BACE,oCACA,gCAGF,6BACE,oCACA,gCAKF,gCACE,yBACA,sCACE,sBAIJ,mBACE,0CAEA,uCACE,yBAGF,uCACE,yBAGF,sCACE,sBAGF,yCACE,yBAKN,cACE,oCACA,sCACA,sBAGF,uBACE,sBAGF,oBACE,8BAIA,aACE,MAnQO,QAqQT,iBACE,aAtQO,QA0QX,iDAEE,MAnQS,KAqQT,6DACE,WAhSO,KAoSX,8FAGE,oCACA,8BAGF,MACE,WA1SS,QA6SX,YACE,sBAGF,aACE,yBAGF,cACE,yBAGF,cACE,yBAGF,WACE,yBAGF,0CAEE,yBAGF,wCAEE,sBAGF,oCAEE,yBAGF,aACE,oCAGF,cACE,aA5UU,QA+UZ,6CACE,oCAEF,qCACE,oCACA,gCAGF,+DAEE,yBAGF,GACE,aApWS,QAuWX,eACE,iBA5WS,KA+WX,4BAEE,iBAlXS,QAmXT,aA9WS,QAiXX,KACE,MA/VY,QAkWd,OACE,MAhWS,KAiWT,iBAEA,aACE,MAnWO,QAuWX,2BACE,iCAGF,SACE,iCACA,uBAGF,cACE,sBAGF,UACE,oCAEA,2BACE,iCACA,sBACA,uCAGF,yBACE,oCACA,sBAGF,qCACE,yBAGF,gCACE,oCAGF,0CACE,oCAIJ,mFAEE,mCAGF,oCACE,oCAGF,0BACE,iCAGF,OACE,sBAEA,oBAEE,6BAKJ,4FACE,wDAIA,WACE,oCAIA,4BACE,MAhbK,KAobT,mCACE,yBAGF,mBACE,oCAKJ,WACE,MA1cS","file":"dark.min.css"}
|
||||
1
WG-Dash/src/static/css/theme/dark.min.min.css
vendored
Normal file
1
WG-Dash/src/static/css/theme/dark.min.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
480
WG-Dash/src/static/css/theme/dark.scss
Normal file
480
WG-Dash/src/static/css/theme/dark.scss
Normal file
@ -0,0 +1,480 @@
|
||||
$grey-100: #1e1e1e;
|
||||
$grey-200: #222222;
|
||||
$grey-300: #242424;
|
||||
$grey-400: #272727;
|
||||
$grey-500: #2c2c2c;
|
||||
$grey-600: #2e2e2e;
|
||||
$grey-700: #333333;
|
||||
$grey-800: #383838;
|
||||
$grey-900: #424242;
|
||||
$grey-1000: #777777;
|
||||
|
||||
$green-400: hsl(120deg, 30%, 40%);
|
||||
$green-500: hsl(120deg, 30%, 50%);
|
||||
|
||||
$red-400: hsl(0deg, 60%, 50%);
|
||||
$red-500: hsl(0deg, 60%, 60%);
|
||||
|
||||
$blue-400: hsl(235deg, 60%, 50%);
|
||||
$blue-500: hsl(235deg, 60%, 60%);
|
||||
$blue-400-clear: rgba(51, 64, 204, 0.25);
|
||||
|
||||
$cyan-400: hsl(190deg, 60%, 50%);
|
||||
$cyan-500: hsl(190deg, 60%, 60%);
|
||||
|
||||
$magenta-500: hsl(315deg, 60%, 60%);
|
||||
|
||||
$text-100: hsl(0deg, 0%, 90%);
|
||||
$text-200: hsl(0deg, 0%, 80%);
|
||||
$text-300: hsl(0deg, 0%, 70%);
|
||||
$text-400: hsl(0deg, 0%, 60%);
|
||||
$text-500: hsl(0deg, 0%, 50%);
|
||||
|
||||
:root {
|
||||
--green: #{$green-500} !important;
|
||||
--blue: #{$blue-500} !important;
|
||||
--red: #{$red-500} !important;
|
||||
--magenta: #{$magenta-500} !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background: $grey-200;
|
||||
color: $text-200;
|
||||
}
|
||||
|
||||
a.text-primary:focus, a.text-primary:hover{
|
||||
color: $blue-400 !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: $text-100 !important;
|
||||
border-color: $blue-500 !important;
|
||||
background: $blue-500 !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $blue-400 !important;
|
||||
border-color: $blue-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline-primary {
|
||||
color: $blue-500 !important;
|
||||
border-color: $blue-500 !important;
|
||||
background: transparent !important;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: $text-100 !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $blue-500 !important;
|
||||
border-color: $blue-500 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $blue-400 !important;
|
||||
border-color: $blue-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
color: $text-100 !important;
|
||||
border-color: $green-500 !important;
|
||||
background: $green-500 !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $green-400 !important;
|
||||
border-color: $green-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item{
|
||||
background-color: $grey-400;
|
||||
border-color: $grey-400;
|
||||
color: white;
|
||||
|
||||
&:hover{
|
||||
background-color: $grey-700;
|
||||
border-color: $grey-700;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.delete-peer-bulk-badge.badge-danger{
|
||||
background-color: $red-500;
|
||||
&:hover{
|
||||
background-color: $red-400;
|
||||
}
|
||||
}
|
||||
|
||||
#delete_bulk_modal{
|
||||
.list-group{
|
||||
a.active{
|
||||
background-color: $red-500;
|
||||
border: $red-500;
|
||||
|
||||
&:hover{
|
||||
background-color: $red-400;
|
||||
border: $red-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#available_ip_modal{
|
||||
.list-group{
|
||||
a.active{
|
||||
background-color: $blue-500;
|
||||
border: $blue-500;
|
||||
|
||||
&:hover{
|
||||
background-color: $blue-400;
|
||||
border: $blue-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.available-ip-badge.badge-primary{
|
||||
background-color: $blue-500;
|
||||
&:hover{
|
||||
background-color: $blue-400;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline-success {
|
||||
color: $green-500 !important;
|
||||
border-color: $green-500 !important;
|
||||
background: transparent !important;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: $text-100 !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $green-500 !important;
|
||||
border-color: $green-500 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $green-400 !important;
|
||||
border-color: $green-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
color: $text-100 !important;
|
||||
border-color: $red-500 !important;
|
||||
background: $red-500 !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $red-400 !important;
|
||||
border-color: $red-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline-danger {
|
||||
color: $red-500 !important;
|
||||
border-color: $red-500 !important;
|
||||
background: transparent !important;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: $text-100 !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $red-500 !important;
|
||||
border-color: $red-500 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $red-400 !important;
|
||||
border-color: $red-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
color: $text-100 !important;
|
||||
border-color: $grey-900 !important;
|
||||
background: $grey-900 !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $grey-800 !important;
|
||||
border-color: $grey-800 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
color: $grey-900 !important;
|
||||
border-color: $grey-900 !important;
|
||||
background: transparent !important;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: $text-100 !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $grey-900 !important;
|
||||
border-color: $grey-900 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $grey-800 !important;
|
||||
border-color: $grey-800 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-control {
|
||||
&.btn-lock-peer.lock {
|
||||
color: $red-500 !important;
|
||||
&:hover {
|
||||
color: $red-400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
|
||||
&.btn-outline-primary {
|
||||
color: $blue-400 !important;
|
||||
}
|
||||
|
||||
&.btn-outline-success {
|
||||
color: $green-400 !important;
|
||||
}
|
||||
|
||||
&.btn-outline-danger {
|
||||
color: $red-400 !important;
|
||||
}
|
||||
|
||||
&.btn-outline-secondary {
|
||||
color: $grey-800 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: $grey-500 !important;
|
||||
border-color: transparent !important;
|
||||
color: $text-200 !important;
|
||||
}
|
||||
|
||||
.form-control:disabled{
|
||||
color: $grey-1000 !important;
|
||||
}
|
||||
|
||||
.card .form-control {
|
||||
background: $grey-500 !important;
|
||||
}
|
||||
|
||||
.conf_card{
|
||||
a{
|
||||
color: $blue-500;
|
||||
}
|
||||
&:hover{
|
||||
border-color: $blue-500;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .nav-link,
|
||||
.bottomNavContainer .nav-link {
|
||||
color: $text-200;
|
||||
|
||||
&:hover {
|
||||
background: $grey-200;
|
||||
}
|
||||
}
|
||||
|
||||
nav#sidebarMenu.col-md-3.col-lg-2.d-md-block.bg-light.sidebar.collapse,
|
||||
.navbar-brand,
|
||||
.bg-dark {
|
||||
background-color: $grey-100 !important;
|
||||
background: $grey-100 !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: $grey-400;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: $text-500 !important;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: $red-500 !important;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: $green-500 !important;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: $blue-500 !important;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: $cyan-500 !important;
|
||||
}
|
||||
|
||||
a.text-success:focus,
|
||||
a.text-success:hover {
|
||||
color: $green-400 !important;
|
||||
}
|
||||
|
||||
a.text-danger:focus,
|
||||
a.text-danger:hover {
|
||||
color: $red-400 !important;
|
||||
}
|
||||
|
||||
a.text-info:focus,
|
||||
a.text-info:hover {
|
||||
color: $cyan-400 !important;
|
||||
}
|
||||
|
||||
.dot-running {
|
||||
background-color: $green-500 !important;
|
||||
}
|
||||
|
||||
.card-running {
|
||||
border-color: $green-500;
|
||||
}
|
||||
|
||||
.toggle--switch:checked + .toggleLabel::before {
|
||||
background-color: $blue-500 !important;
|
||||
}
|
||||
.toggle--switch:checked + .toggleLabel {
|
||||
background-color: mix($blue-500, #000f) !important;
|
||||
border-color: $blue-500 !important;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active,
|
||||
.bottomNavContainer .nav-link.active {
|
||||
color: $blue-500 !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: $grey-600;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: $grey-200;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
background-color: $grey-100;
|
||||
border-color: $grey-600;
|
||||
}
|
||||
|
||||
code {
|
||||
color: $magenta-500;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: $text-200;
|
||||
text-shadow: none;
|
||||
|
||||
&:hover {
|
||||
color: $text-300;
|
||||
}
|
||||
}
|
||||
|
||||
.chartContainer.fullScreen {
|
||||
background-color: $grey-200 !important;
|
||||
}
|
||||
|
||||
.popover {
|
||||
background-color: $grey-700 !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
color: $text-200 !important;
|
||||
}
|
||||
|
||||
div.toast {
|
||||
background-color: $grey-900 !important;
|
||||
|
||||
div.toast-header {
|
||||
background-color: $grey-700 !important;
|
||||
color: $text-200 !important;
|
||||
border-bottom-color: $grey-900 !important;
|
||||
}
|
||||
|
||||
div.toast-body {
|
||||
background-color: $grey-800 !important;
|
||||
color: $text-200 !important;
|
||||
}
|
||||
|
||||
div.toast-body.text-danger{
|
||||
color: $red-500 !important;
|
||||
}
|
||||
|
||||
div.toast-progressbar {
|
||||
background-color: $blue-500 !important;
|
||||
}
|
||||
|
||||
div.toast-progressbar.bg-danger {
|
||||
background-color: $red-500 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.bs-popover-auto[x-placement^="right"] > .arrow::after,
|
||||
.bs-popover-right > .arrow::after {
|
||||
border-right-color: $grey-700 !important;
|
||||
}
|
||||
|
||||
.btn-manage-group .setting_btn_menu {
|
||||
background-color: $grey-500 !important;
|
||||
}
|
||||
|
||||
.setting_btn_menu a:hover {
|
||||
background-color: $grey-700 !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
color: $text-200 !important;
|
||||
|
||||
th,
|
||||
td {
|
||||
border-color: $grey-700 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn-outline-primary.focus, .btn-outline-primary:focus, .btn-primary.focus, .btn-primary:focus{
|
||||
box-shadow: 0 0 0 0.2rem rgb(144 153 255 / 29%) !important;
|
||||
}
|
||||
|
||||
.bottomNav{
|
||||
&{
|
||||
background-color: $grey-400 !important;
|
||||
}
|
||||
|
||||
.bottomNavButton{
|
||||
&{
|
||||
color: $text-400;
|
||||
}
|
||||
}
|
||||
|
||||
.bottomNavButton.active{
|
||||
color: $blue-500 !important;
|
||||
}
|
||||
|
||||
.subNav{
|
||||
background-color: $grey-400 !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.key:hover{
|
||||
color: $blue-500;
|
||||
}
|
||||
|
||||
|
||||
BIN
WG-Dash/src/static/img/192x192ios.png
Normal file
BIN
WG-Dash/src/static/img/192x192ios.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
WG-Dash/src/static/img/icon-192x192.png
Normal file
BIN
WG-Dash/src/static/img/icon-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
WG-Dash/src/static/img/icon-256x256.png
Normal file
BIN
WG-Dash/src/static/img/icon-256x256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
WG-Dash/src/static/img/icon-384x384.png
Normal file
BIN
WG-Dash/src/static/img/icon-384x384.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
WG-Dash/src/static/img/icon-512x512.png
Normal file
BIN
WG-Dash/src/static/img/icon-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
BIN
WG-Dash/src/static/img/logo.png
Normal file
BIN
WG-Dash/src/static/img/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
1678
WG-Dash/src/static/js/configuration.js
Normal file
1678
WG-Dash/src/static/js/configuration.js
Normal file
File diff suppressed because it is too large
Load Diff
138
WG-Dash/src/static/js/index.js
Normal file
138
WG-Dash/src/static/js/index.js
Normal file
@ -0,0 +1,138 @@
|
||||
let numberToast = 0,
|
||||
emptyInputFeedback = "Can't leave empty";
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
let $add_configuration = $("#add_configuration"),
|
||||
addConfigurationModal = $("#addConfigurationModal");
|
||||
|
||||
function showToast(a) {
|
||||
$(".toastContainer").append(`<div id="${numberToast}-toast" class="toast hide" role="alert" data-delay="500">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto">WGDashboard</strong>
|
||||
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="toast-body">${a}</div>
|
||||
<div class="toast-progressbar"></div>
|
||||
</div>`), $(`#${numberToast}-toast`).toast("show"), $(`#${numberToast}-toast .toast-body`).html(a), $(`#${numberToast}-toast .toast-progressbar`).css("transition", `width ${$(`#${numberToast}-toast .toast-progressbar`).parent().data("delay")}ms cubic-bezier(0, 0, 0, 0)`), $(`#${numberToast}-toast .toast-progressbar`).css("width", "0px"), numberToast++
|
||||
}
|
||||
|
||||
function genKeyPair() {
|
||||
let a = window.wireguard.generateKeypair();
|
||||
$("#addConfigurationPrivateKey").val(a.privateKey).data("checked", !0)
|
||||
}
|
||||
|
||||
function ajaxPostJSON(a, t, e) {
|
||||
$.ajax({
|
||||
url: a,
|
||||
method: "POST",
|
||||
data: JSON.stringify(t),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}).done(function(a) {
|
||||
e(a)
|
||||
})
|
||||
}
|
||||
|
||||
function validInput(a) {
|
||||
a.removeClass("is-invalid").addClass("is-valid").removeAttr("disabled").data("checked", !0)
|
||||
}
|
||||
|
||||
function invalidInput(a, t, e) {
|
||||
a.removeClass("is-valid").addClass("is-invalid").removeAttr("disabled").data("checked", !1), t.addClass("invalid-feedback").text(e)
|
||||
}
|
||||
|
||||
function checkPort(a) {
|
||||
let t = a;
|
||||
t.attr("disabled", "disabled");
|
||||
let e = $("#addConfigurationListenPortFeedback");
|
||||
0 == t.val().length ? invalidInput(t, e, emptyInputFeedback) : ajaxPostJSON("/api/addConfigurationPortCheck", {
|
||||
port: t.val()
|
||||
}, function a(i) {
|
||||
i.status ? validInput(t) : invalidInput(t, e, i.reason)
|
||||
})
|
||||
}
|
||||
|
||||
function checkAddress(a) {
|
||||
let t = a;
|
||||
t.attr("disabled", "disabled");
|
||||
let e = $(".addConfigurationAvailableIPs"),
|
||||
i = $("#addConfigurationAddressFeedback");
|
||||
0 == t.val().length ? (invalidInput(t, i, emptyInputFeedback), e.html("N/A")) : ajaxPostJSON("/api/addConfigurationAddressCheck", {
|
||||
address: t.val()
|
||||
}, function a(n) {
|
||||
n.status ? (e.html(`<strong>${n.data}</strong>`), validInput(t)) : (invalidInput(t, i, n.reason), e.html("N/A"))
|
||||
})
|
||||
}
|
||||
|
||||
function checkName(a) {
|
||||
let t = a,
|
||||
e = $("#addConfigurationNameFeedback");
|
||||
t.val(t.val().replace(/\s/g, "")).attr("disabled", "disabled"), 0 === t.val().length ? invalidInput(t, e, emptyInputFeedback) : ajaxPostJSON("/api/addConfigurationNameCheck", {
|
||||
name: t.val()
|
||||
}, function a(i) {
|
||||
i.status ? validInput(t) : invalidInput(t, e, i.reason)
|
||||
})
|
||||
}
|
||||
addConfigurationModal.modal({
|
||||
keyboard: !1,
|
||||
backdrop: "static",
|
||||
show: !1
|
||||
}), addConfigurationModal.on("hidden.bs.modal", function() {
|
||||
$("#add_configuration_form").trigger("reset"), $("#add_configuration_form input").removeClass("is-valid").removeClass("is-invalid"), $(".addConfigurationAvailableIPs").text("N/A")
|
||||
}), $(".toggle--switch").on("change", function() {
|
||||
$(this).addClass("waiting").attr("disabled", "disabled");
|
||||
let a = $(this).data("conf-id"),
|
||||
t = $(this).prop("checked"),
|
||||
e = $(this);
|
||||
$(this).siblings("label"), $.ajax({
|
||||
url: `/switch/${a}`
|
||||
}).done(function(i) {
|
||||
let n = $(`div[data-conf-id="${a}"] .dot`);
|
||||
i.status ? t ? (n.removeClass("dot-stopped").addClass("dot-running"), n.siblings().text("Running"), showToast(`${a} is running.`)) : (n.removeClass("dot-running").addClass("dot-stopped"), showToast(`${a} is stopped.`)) : (e.parents().children(".card-message").html(`<pre class="index-alert">Configuration toggle failed. Please check the following error message:<br><code>${i.message}</code></pre>`), t ? e.prop("checked", !1) : e.prop("checked", !0)), e.removeClass("waiting").removeAttr("disabled")
|
||||
})
|
||||
}), $(".sb-home-url").addClass("active"), $(".card-body").on("click", function(a) {
|
||||
"toggleLabel" !== $(a.target).attr("class") && "toggle--switch" !== $(a.target).attr("class") && window.open($(this).find("a").attr("href"), "_self")
|
||||
}), $("#reGeneratePrivateKey").on("click", function() {
|
||||
genKeyPair()
|
||||
}), $("#toggleAddConfiguration").on("click", function() {
|
||||
addConfigurationModal.modal("toggle"), genKeyPair()
|
||||
}), $("#addConfigurationPrivateKey").on("change", function() {
|
||||
$privateKey = $(this), $privateKeyFeedback = $("#addConfigurationPrivateKeyFeedback"), 44 != $privateKey.val().length ? invalidInput($privateKey, $privateKeyFeedback, "Invalid length") : validInput($privateKey)
|
||||
}), $("#addConfigurationListenPort").on("change", function() {
|
||||
checkPort($(this))
|
||||
}), $("#addConfigurationAddress").on("change", function() {
|
||||
checkAddress($(this))
|
||||
}), $("#addConfigurationName").on("change", function() {
|
||||
checkName($(this))
|
||||
}), $("#addConfigurationBtn").on("click", function() {
|
||||
$(this);
|
||||
let a = $("#add_configuration_form input"),
|
||||
t = !0;
|
||||
for (let e = 0; e < a.length; e++) {
|
||||
let i = $(a[e]);
|
||||
void 0 == i.attr("required") || (0 == i.val().length && "addConfigurationPrivateKey" !== i.attr("name") && (invalidInput(i, i.siblings(".input-feedback"), emptyInputFeedback), t = !1), 44 != i.val().length && "addConfigurationPrivateKey" == i.attr("name") && (invalidInput(i, i.siblings(".input-feedback"), "Invalid length"), t = !1), i.data("checked") || (t = !1))
|
||||
}
|
||||
if (t) {
|
||||
$("#addConfigurationModal .modal-footer .btn").hide(), $(".addConfigurationStatus").removeClass("d-none");
|
||||
let n = {},
|
||||
o = [];
|
||||
for (let d = 0; d < a.length; d++) {
|
||||
let s = $(a[d]);
|
||||
n[s.attr("name")] = s.val(), o.push(s.attr("name"))
|
||||
}
|
||||
ajaxPostJSON("/api/addConfiguration", n, a => {
|
||||
let t = a.data;
|
||||
$(".addConfigurationAddStatus").removeClass("text-primary").addClass("text-success").html(`<i class="bi bi-check-circle-fill"></i> ${t} added successfully.`), a.status ? setTimeout(() => {
|
||||
$(".addConfigurationToggleStatus").removeClass("waiting").html('<div class="spinner-border spinner-border-sm" role="status"></div> Toggle Configuration'), $.ajax({
|
||||
url: `/switch/${t}`
|
||||
}).done(function(a) {
|
||||
a.status ? ($(".addConfigurationToggleStatus").removeClass("text-primary").addClass("text-success").html('<i class="bi bi-check-circle-fill"></i> Toggle Successfully. Refresh in 5 seconds.'), setTimeout(() => {
|
||||
$(".addConfigurationToggleStatus").text("Refeshing..."), location.reload()
|
||||
}, 5e3)) : ($(".addConfigurationToggleStatus").removeClass("text-primary").addClass("text-danger").html(`<i class="bi bi-x-circle-fill"></i> ${t} toggle failed.`), $("#addCconfigurationAlertMessage").removeClass("d-none").html(`${t} toggle failed. Please check the following error message:<br>${a.message}`))
|
||||
})
|
||||
}, 500) : ($(".addConfigurationStatus").removeClass("text-primary").addClass("text-danger").html(`<i class="bi bi-x-circle-fill"></i> ${t} adding failed.`), $("#addCconfigurationAlert").removeClass("d-none").children(".alert-body").text(a.reason))
|
||||
})
|
||||
}
|
||||
});
|
||||
10
WG-Dash/src/static/js/index.min.js
vendored
Normal file
10
WG-Dash/src/static/js/index.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
59
WG-Dash/src/static/js/settings.js
Normal file
59
WG-Dash/src/static/js/settings.js
Normal file
@ -0,0 +1,59 @@
|
||||
$(".sb-settings-url").addClass("active");
|
||||
|
||||
$(".confirm_modal").click(function () {
|
||||
$(".app_new_ip").text($("#app_ip")[0].value);
|
||||
$(".app_new_port").text($("#app_port")[0].value);
|
||||
});
|
||||
|
||||
$(".confirm_restart").click(function () {
|
||||
$(".cancel_restart").remove();
|
||||
countdown = 7;
|
||||
$.post('/update_app_ip_port', $('.update_app_ip_port').serialize());
|
||||
url = $("#app_ip")[0].value + ":" + $("#app_port")[0].value;
|
||||
$(".confirm_restart").attr("disabled", "disabled");
|
||||
|
||||
setInterval(function () {
|
||||
if (countdown === 0) {
|
||||
window.location.replace("http://" + url);
|
||||
}
|
||||
$(".confirm_restart").text("Redirecting you in " + countdown + " seconds.");
|
||||
countdown--;
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
$(".change_path").click(function () {
|
||||
$(this).attr("disabled", "disabled");
|
||||
countdown = 5;
|
||||
setInterval(function () {
|
||||
if (countdown === 0) {
|
||||
location.reload();
|
||||
}
|
||||
$(".change_path").text("Redirecting you in " + countdown + " seconds.");
|
||||
countdown--;
|
||||
}, 1000);
|
||||
$.post('/update_wg_conf_path', $('.update_wg_conf_path').serialize());
|
||||
});
|
||||
|
||||
$(".bottomNavSettings").addClass("active");
|
||||
|
||||
$(".theme-switch-btn").on("click", function(){
|
||||
if (!$(this).hasClass("active")){
|
||||
let theme = $(this).data("theme");
|
||||
$(".theme-switch-btn").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "/api/settings/setTheme",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
data: JSON.stringify({"theme": theme})
|
||||
}).done(function(res){
|
||||
if (res.status == true){
|
||||
if (theme == "light"){
|
||||
$("#darkThemeCSS").remove();
|
||||
} else {
|
||||
$("head").append('<link rel="stylesheet" type="text/css" href="/static/css/theme/dark.min.css" id="darkThemeCSS">');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
1
WG-Dash/src/static/js/settings.min.js
vendored
Normal file
1
WG-Dash/src/static/js/settings.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
$(".sb-settings-url").addClass("active"),$(".confirm_modal").click(function(){$(".app_new_ip").html($("#app_ip")[0].value),$(".app_new_port").html($("#app_port")[0].value)}),$(".confirm_restart").click(function(){$(".cancel_restart").remove(),countdown=7,$.post("/update_app_ip_port",$(".update_app_ip_port").serialize()),url=$("#app_ip")[0].value+":"+$("#app_port")[0].value,$(".confirm_restart").attr("disabled","disabled"),setInterval(function(){0===countdown&&window.location.replace("http://"+url),$(".confirm_restart").html("Redirecting you in "+countdown+" seconds."),countdown--},1e3)}),$(".change_path").click(function(){$(this).attr("disabled","disabled"),countdown=5,setInterval(function(){0===countdown&&location.reload(),$(".change_path").html("Redirecting you in "+countdown+" seconds."),countdown--},1e3),$.post("/update_wg_conf_path",$(".update_wg_conf_path").serialize())}),$(".bottomNavSettings").addClass("active"),$(".theme-switch-btn").on("click",function(){if(!$(this).hasClass("active")){let t=$(this).data("theme");$(".theme-switch-btn").removeClass("active"),$(this).addClass("active"),$.ajax({method:"POST",url:"/api/settings/setTheme",headers:{"Content-Type":"application/json"},data:JSON.stringify({theme:t})}).done(function(e){!0==e.status&&("light"==t?$("#darkThemeCSS").remove():$("head").append('<link rel="stylesheet" type="text/css" href="/static/css/theme/dark.min.css" id="darkThemeCSS">'))})}});
|
||||
67
WG-Dash/src/static/js/tools.js
Normal file
67
WG-Dash/src/static/js/tools.js
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* tools.js - Copyright(C) 2021 Donald Zou [https://github.com/donaldzou]
|
||||
*/
|
||||
|
||||
$(".ip_dropdown").on("change",function (){
|
||||
$(".modal.show .btn").removeAttr("disabled");
|
||||
});
|
||||
|
||||
$(".conf_dropdown").on("change", function (){
|
||||
$(".modal.show .ip_dropdown").html('<option value="none" selected="selected" disabled>Loading...');
|
||||
$.ajax({
|
||||
url: "/get_ping_ip",
|
||||
method: "POST",
|
||||
data: "config=" + $(this).children("option:selected").val(),
|
||||
success: function (res){
|
||||
$(".modal.show .ip_dropdown").html("");
|
||||
$(".modal.show .ip_dropdown").append('<option value="none" selected="selected" disabled>Choose an IP');
|
||||
$(".modal.show .ip_dropdown").append(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
// Ping Tools
|
||||
$(".send_ping").on("click", function (){
|
||||
$(this).attr("disabled","disabled");
|
||||
$(this).html("Pinging...");
|
||||
$("#ping_modal .form-control").attr("disabled","disabled");
|
||||
$.ajax({
|
||||
method:"POST",
|
||||
data: "ip="+ $(':selected', $("#ping_modal .ip_dropdown")).val() +
|
||||
"&count=" + $("#ping_modal .ping_count").val(),
|
||||
url: "/ping_ip",
|
||||
success: function (res){
|
||||
$(".ping_result tbody").html("");
|
||||
let html = '<tr><th scope="row">Address</th><td>'+res.address+'</td></tr>' +
|
||||
'<tr><th scope="row">Is Alive</th><td>'+res.is_alive+'</td></tr>' +
|
||||
'<tr><th scope="row">Min RTT</th><td>'+res.min_rtt+'ms</td></tr>' +
|
||||
'<tr><th scope="row">Average RTT </th><td>'+res.avg_rtt+'ms</td></tr>' +
|
||||
'<tr><th scope="row">Max RTT</th><td>'+res.max_rtt+'ms</td></tr>' +
|
||||
'<tr><th scope="row">Package Sent</th><td>'+res.package_sent+'</td></tr>' +
|
||||
'<tr><th scope="row">Package Received</th><td>'+res.package_received+'</td></tr>' +
|
||||
'<tr><th scope="row">Package Loss</th><td>'+res.package_loss+'</td></tr>';
|
||||
$(".ping_result tbody").html(html);
|
||||
$(".send_ping").removeAttr("disabled");
|
||||
$(".send_ping").html("Ping");
|
||||
$("#ping_modal .form-control").removeAttr("disabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Traceroute Tools
|
||||
$(".send_traceroute").on("click", function (){
|
||||
$(this).attr("disabled","disabled");
|
||||
$(this).html("Tracing...");
|
||||
$("#traceroute_modal .form-control").attr("disabled","disabled");
|
||||
$.ajax({
|
||||
url: "/traceroute_ip",
|
||||
method: "POST",
|
||||
data: "ip=" + $(':selected', $("#traceroute_modal .ip_dropdown")).val(),
|
||||
success: function (res){
|
||||
$(".traceroute_result tbody").html("");
|
||||
res.forEach((ele) =>
|
||||
$(".traceroute_result tbody").append('<tr><th scope="row">'+ele.hop+'</th><td>'+ele.ip+'</td><td>'+ele.avg_rtt+'</td><td>'+ele.min_rtt+'</td><td>'+ele.max_rtt+'</td></tr>'));
|
||||
$(".send_traceroute").removeAttr("disabled").html("Traceroute");
|
||||
$("#traceroute_modal .form-control").removeAttr("disabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
1
WG-Dash/src/static/js/tools.min.js
vendored
Normal file
1
WG-Dash/src/static/js/tools.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
$(".ip_dropdown").on("change",function(){$(".modal.show .btn").removeAttr("disabled")}),$(".conf_dropdown").on("change",function(){$(".modal.show .ip_dropdown").html('<option value="none" selected="selected" disabled>Loading...'),$.ajax({url:"/get_ping_ip",method:"POST",data:"config="+$(this).children("option:selected").val(),success:function(t){$(".modal.show .ip_dropdown").html(""),$(".modal.show .ip_dropdown").append('<option value="none" selected="selected" disabled>Choose an IP'),$(".modal.show .ip_dropdown").append(t)}})}),$(".send_ping").on("click",function(){$(this).attr("disabled","disabled"),$(this).html("Pinging..."),$("#ping_modal .form-control").attr("disabled","disabled"),$.ajax({method:"POST",data:"ip="+$(":selected",$("#ping_modal .ip_dropdown")).val()+"&count="+$("#ping_modal .ping_count").val(),url:"/ping_ip",success:function(t){$(".ping_result tbody").html("");let e='<tr><th scope="row">Address</th><td>'+t.address+'</td></tr><tr><th scope="row">Is Alive</th><td>'+t.is_alive+'</td></tr><tr><th scope="row">Min RTT</th><td>'+t.min_rtt+'ms</td></tr><tr><th scope="row">Average RTT </th><td>'+t.avg_rtt+'ms</td></tr><tr><th scope="row">Max RTT</th><td>'+t.max_rtt+'ms</td></tr><tr><th scope="row">Package Sent</th><td>'+t.package_sent+'</td></tr><tr><th scope="row">Package Received</th><td>'+t.package_received+'</td></tr><tr><th scope="row">Package Loss</th><td>'+t.package_loss+"</td></tr>";$(".ping_result tbody").html(e),$(".send_ping").removeAttr("disabled"),$(".send_ping").html("Ping"),$("#ping_modal .form-control").removeAttr("disabled")}})}),$(".send_traceroute").on("click",function(){$(this).attr("disabled","disabled"),$(this).html("Tracing..."),$("#traceroute_modal .form-control").attr("disabled","disabled"),$.ajax({url:"/traceroute_ip",method:"POST",data:"ip="+$(":selected",$("#traceroute_modal .ip_dropdown")).val(),success:function(t){$(".traceroute_result tbody").html(""),t.forEach(t=>$(".traceroute_result tbody").append('<tr><th scope="row">'+t.hop+"</th><td>"+t.ip+"</td><td>"+t.avg_rtt+"</td><td>"+t.min_rtt+"</td><td>"+t.max_rtt+"</td></tr>")),$(".send_traceroute").removeAttr("disabled").html("Traceroute"),$("#traceroute_modal .form-control").removeAttr("disabled")}})});
|
||||
313
WG-Dash/src/static/js/wireguard.js
Normal file
313
WG-Dash/src/static/js/wireguard.js
Normal file
@ -0,0 +1,313 @@
|
||||
/*! SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
function gf(init) {
|
||||
var r = new Float64Array(16);
|
||||
if (init) {
|
||||
for (var i = 0; i < init.length; ++i)
|
||||
r[i] = init[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function pack(o, n) {
|
||||
var b, m = gf(), t = gf();
|
||||
for (var i = 0; i < 16; ++i)
|
||||
t[i] = n[i];
|
||||
carry(t);
|
||||
carry(t);
|
||||
carry(t);
|
||||
for (var j = 0; j < 2; ++j) {
|
||||
m[0] = t[0] - 0xffed;
|
||||
for (var i = 1; i < 15; ++i) {
|
||||
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
|
||||
m[i - 1] &= 0xffff;
|
||||
}
|
||||
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
|
||||
b = (m[15] >> 16) & 1;
|
||||
m[14] &= 0xffff;
|
||||
cswap(t, m, 1 - b);
|
||||
}
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
o[2 * i] = t[i] & 0xff;
|
||||
o[2 * i + 1] = t[i] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
function carry(o) {
|
||||
var c;
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
o[(i + 1) % 16] += (i < 15 ? 1 : 38) * Math.floor(o[i] / 65536);
|
||||
o[i] &= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
function cswap(p, q, b) {
|
||||
var t, c = ~(b - 1);
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
t = c & (p[i] ^ q[i]);
|
||||
p[i] ^= t;
|
||||
q[i] ^= t;
|
||||
}
|
||||
}
|
||||
|
||||
function add(o, a, b) {
|
||||
for (var i = 0; i < 16; ++i)
|
||||
o[i] = (a[i] + b[i]) | 0;
|
||||
}
|
||||
|
||||
function subtract(o, a, b) {
|
||||
for (var i = 0; i < 16; ++i)
|
||||
o[i] = (a[i] - b[i]) | 0;
|
||||
}
|
||||
|
||||
function multmod(o, a, b) {
|
||||
var t = new Float64Array(31);
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
for (var j = 0; j < 16; ++j)
|
||||
t[i + j] += a[i] * b[j];
|
||||
}
|
||||
for (var i = 0; i < 15; ++i)
|
||||
t[i] += 38 * t[i + 16];
|
||||
for (var i = 0; i < 16; ++i)
|
||||
o[i] = t[i];
|
||||
carry(o);
|
||||
carry(o);
|
||||
}
|
||||
|
||||
function invert(o, i) {
|
||||
var c = gf();
|
||||
for (var a = 0; a < 16; ++a)
|
||||
c[a] = i[a];
|
||||
for (var a = 253; a >= 0; --a) {
|
||||
multmod(c, c, c);
|
||||
if (a !== 2 && a !== 4)
|
||||
multmod(c, c, i);
|
||||
}
|
||||
for (var a = 0; a < 16; ++a)
|
||||
o[a] = c[a];
|
||||
}
|
||||
|
||||
function clamp(z) {
|
||||
z[31] = (z[31] & 127) | 64;
|
||||
z[0] &= 248;
|
||||
}
|
||||
|
||||
function generatePublicKey(privateKey) {
|
||||
var r, z = new Uint8Array(32);
|
||||
var a = gf([1]),
|
||||
b = gf([9]),
|
||||
c = gf(),
|
||||
d = gf([1]),
|
||||
e = gf(),
|
||||
f = gf(),
|
||||
_121665 = gf([0xdb41, 1]),
|
||||
_9 = gf([9]);
|
||||
for (var i = 0; i < 32; ++i)
|
||||
z[i] = privateKey[i];
|
||||
clamp(z);
|
||||
for (var i = 254; i >= 0; --i) {
|
||||
r = (z[i >>> 3] >>> (i & 7)) & 1;
|
||||
cswap(a, b, r);
|
||||
cswap(c, d, r);
|
||||
add(e, a, c);
|
||||
subtract(a, a, c);
|
||||
add(c, b, d);
|
||||
subtract(b, b, d);
|
||||
multmod(d, e, e);
|
||||
multmod(f, a, a);
|
||||
multmod(a, c, a);
|
||||
multmod(c, b, e);
|
||||
add(e, a, c);
|
||||
subtract(a, a, c);
|
||||
multmod(b, a, a);
|
||||
subtract(c, d, f);
|
||||
multmod(a, c, _121665);
|
||||
add(a, a, d);
|
||||
multmod(c, c, a);
|
||||
multmod(a, d, f);
|
||||
multmod(d, b, _9);
|
||||
multmod(b, e, e);
|
||||
cswap(a, b, r);
|
||||
cswap(c, d, r);
|
||||
}
|
||||
invert(c, c);
|
||||
multmod(a, a, c);
|
||||
pack(z, a);
|
||||
return z;
|
||||
}
|
||||
|
||||
function generatePresharedKey() {
|
||||
var privateKey = new Uint8Array(32);
|
||||
window.crypto.getRandomValues(privateKey);
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
function generatePrivateKey() {
|
||||
var privateKey = generatePresharedKey();
|
||||
clamp(privateKey);
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
function encodeBase64(dest, src) {
|
||||
var input = Uint8Array.from([(src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63]);
|
||||
for (var i = 0; i < 4; ++i)
|
||||
dest[i] = input[i] + 65 +
|
||||
(((25 - input[i]) >> 8) & 6) -
|
||||
(((51 - input[i]) >> 8) & 75) -
|
||||
(((61 - input[i]) >> 8) & 15) +
|
||||
(((62 - input[i]) >> 8) & 3);
|
||||
}
|
||||
|
||||
function keyToBase64(key) {
|
||||
var i, base64 = new Uint8Array(44);
|
||||
for (i = 0; i < 32 / 3; ++i)
|
||||
encodeBase64(base64.subarray(i * 4), key.subarray(i * 3));
|
||||
encodeBase64(base64.subarray(i * 4), Uint8Array.from([key[i * 3 + 0], key[i * 3 + 1], 0]));
|
||||
base64[43] = 61;
|
||||
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);
|
||||
}
|
||||
|
||||
function putU16(b, n)
|
||||
{
|
||||
b.push(n & 0xff, (n >>> 8) & 0xff);
|
||||
}
|
||||
|
||||
function putBytes(b, a)
|
||||
{
|
||||
for (var i = 0; i < a.length; ++i)
|
||||
b.push(a[i] & 0xff);
|
||||
}
|
||||
|
||||
function encodeString(s)
|
||||
{
|
||||
var utf8 = unescape(encodeURIComponent(s));
|
||||
var b = new Uint8Array(utf8.length);
|
||||
for (var i = 0; i < utf8.length; ++i)
|
||||
b[i] = utf8.charCodeAt(i);
|
||||
return b;
|
||||
}
|
||||
|
||||
function crc32(b)
|
||||
{
|
||||
if (!crc32.table) {
|
||||
crc32.table = [];
|
||||
for (var c = 0, n = 0; n < 256; c = ++n) {
|
||||
for (var k = 0; k < 8; ++k)
|
||||
c = ((c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1));
|
||||
crc32.table[n] = c;
|
||||
}
|
||||
}
|
||||
var crc = -1;
|
||||
for (var i = 0; i < b.length; ++i)
|
||||
crc = (crc >>> 8) ^ crc32.table[(crc ^ b[i]) & 0xff];
|
||||
return (crc ^ (-1)) >>> 0;
|
||||
}
|
||||
|
||||
function createZipFile(files)
|
||||
{
|
||||
var b = [];
|
||||
var cd = [];
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
var name = encodeString(files[i].filename);
|
||||
var contents = encodeString(files[i].content);
|
||||
var crc = crc32(contents);
|
||||
|
||||
putU32(b, 0x04034b50); /* signature */
|
||||
putU16(b, 20); /* version needed */
|
||||
putU16(b, 0); /* flags */
|
||||
putU16(b, 0); /* compression method */
|
||||
putU16(b, 0); /* mtime */
|
||||
putU16(b, 0); /* mdate */
|
||||
putU32(b, crc); /* crc32 */
|
||||
putU32(b, contents.length); /* compressed size */
|
||||
putU32(b, contents.length); /* uncompressed size */
|
||||
putU16(b, name.length); /* file name length */
|
||||
putU16(b, 0); /* extra field length */
|
||||
putBytes(b, name);
|
||||
putBytes(b, contents);
|
||||
|
||||
putU32(cd, 0x02014b50); /* signature */
|
||||
putU16(cd, 0); /* version made */
|
||||
putU16(cd, 20); /* version needed */
|
||||
putU16(cd, 0); /* flags */
|
||||
putU16(cd, 0); /* compression method */
|
||||
putU16(cd, 0); /* mtime */
|
||||
putU16(cd, 0); /* mdate */
|
||||
putU32(cd, crc); /* crc32 */
|
||||
putU32(cd, contents.length); /* compressed size */
|
||||
putU32(cd, contents.length); /* uncompressed size */
|
||||
putU16(cd, name.length); /* file name length */
|
||||
putU16(cd, 0); /* extra field length */
|
||||
putU16(cd, 0); /* file comment length */
|
||||
putU16(cd, 0); /* disk number start */
|
||||
putU16(cd, 0); /* internal file attributes */
|
||||
putU32(cd, 32); /* external file attributes - 'archive' bit set (32) */
|
||||
putU32(cd, offset); /* relative offset of local header */
|
||||
putBytes(cd, name); /* file name */
|
||||
|
||||
offset += 30 + contents.length + name.length
|
||||
}
|
||||
putBytes(b, cd); /* central directory */
|
||||
putU32(b, 0x06054b50); /* end of central directory signature */
|
||||
putU16(b, 0); /* number of this disk */
|
||||
putU16(b, 0); /* number of disk with central directory start */
|
||||
putU16(b, files.length); /* number of entries on disk */
|
||||
putU16(b, files.length); /* number of entries */
|
||||
putU32(b, cd.length); /* length of central directory */
|
||||
putU32(b, offset); /* offset to start of central directory */
|
||||
putU16(b, 0); /* zip comment size */
|
||||
return Uint8Array.from(b);
|
||||
}
|
||||
|
||||
window.wireguard = {
|
||||
generateKeypair: function() {
|
||||
var privateKey = generatePrivateKey();
|
||||
var publicKey = generatePublicKey(privateKey);
|
||||
var presharedKey = generatePresharedKey();
|
||||
return {
|
||||
publicKey: keyToBase64(publicKey),
|
||||
privateKey: keyToBase64(privateKey),
|
||||
presharedKey: keyToBase64(presharedKey)
|
||||
};
|
||||
},
|
||||
generatePublicKey: function (privateKey){
|
||||
privateKey = base64ToKey(privateKey);
|
||||
return keyToBase64(generatePublicKey(privateKey));
|
||||
},
|
||||
|
||||
generateZipFiles: function(res){
|
||||
var files = res.peers;
|
||||
var zipFile = createZipFile(files);
|
||||
var blob = new Blob([zipFile], { type: "application/zip" });
|
||||
var a = document.createElement("a");
|
||||
a.download = res.filename;
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.style.display = "none";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
};
|
||||
})();
|
||||
1
WG-Dash/src/static/js/wireguard.min.js
vendored
Normal file
1
WG-Dash/src/static/js/wireguard.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
31
WG-Dash/src/static/json/manifest.json
Normal file
31
WG-Dash/src/static/json/manifest.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"theme_color": "#343a40",
|
||||
"background_color": "#343a40",
|
||||
"display": "fullscreen",
|
||||
"scope": "/",
|
||||
"start_url": "/",
|
||||
"name": "WireGate",
|
||||
"short_name": "WireGate",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/img/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/img/icon-256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/img/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/img/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
467
WG-Dash/src/templates/configuration.html
Normal file
467
WG-Dash/src/templates/configuration.html
Normal file
@ -0,0 +1,467 @@
|
||||
<!-- configuration.html - < WGDashboard > - Copyright(C) 2021 Donald Zou [https://github.com/donaldzou]-->
|
||||
<html lang="en">
|
||||
{% with title=title%}
|
||||
{% include "header.html"%}
|
||||
{% endwith %}
|
||||
<body>
|
||||
<div class="no-response">
|
||||
<div class="container">
|
||||
<h1 class="text-white display-1"><i class="bi bi-emoji-frown-fill"></i></h1>
|
||||
<h4 class="text-white">Oops!<br>I can't connect to the server.</h4>
|
||||
</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">
|
||||
|
||||
</div>
|
||||
<div id="config_body">
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
||||
<div class="info mt-4">
|
||||
<div>
|
||||
<pre class="index-alert d-none" style="margin-bottom: 1rem;"></pre>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>ZONE</strong></small>
|
||||
<h1 class="mb-3"><samp id="conf_name">{{ title }}</samp></h1>
|
||||
</div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>SWITCH</strong></small><br>
|
||||
<!-- <div id="conf_status_btn" class="info_loading"></div> -->
|
||||
<div id="switch" class="info_loading">
|
||||
<input type="checkbox" class="toggle--switch" id="toggle--switch">
|
||||
<label for="toggle--switch" class="toggleLabel"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>STATUS</strong></small>
|
||||
<h6 style="text-transform: uppercase;" id="conf_status" class="info_loading"></h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>CONNECTED PEERS</strong></small>
|
||||
<h6 style="text-transform: uppercase;" id="conf_connected_peers" class="info_loading"></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
|
||||
<h6 style="text-transform: uppercase;" id="conf_total_data_usage" class="info_loading"></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL RECEIVED</strong></small>
|
||||
<h6 style="text-transform: uppercase;" id="conf_total_data_received" class="info_loading"></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL SENT</strong></small>
|
||||
<h6 style="text-transform: uppercase;" id="conf_total_data_sent" class="info_loading"></h6>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted">
|
||||
<strong>PUBLIC KEY</strong>
|
||||
<strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong>
|
||||
</small>
|
||||
<h6 class="info_loading"><samp class="key" id="conf_public_key"></samp></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>LISTEN PORT</strong></small>
|
||||
<h6 style="text-transform: uppercase;" class="info_loading"><samp id="conf_listen_port"></samp></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>ADDRESS</strong></small>
|
||||
<h6 style="text-transform: uppercase;" class="info_loading"><samp id="conf_address"></samp></h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row chartContainer">
|
||||
<div class="col-sm">
|
||||
<div class="chartTitle">
|
||||
<h6>Data Usage / Refresh Interval</h6>
|
||||
<div class="chartControl" style="margin-left: auto">
|
||||
<div class="btn-group" role="group">
|
||||
<button class="btn btn-outline-primary btn-sm switchUnit" data-unit="GB">GB</button>
|
||||
<button class="btn btn-outline-primary btn-sm switchUnit" data-unit="MB">MB</button>
|
||||
<button class="btn btn-outline-primary btn-sm switchUnit" data-unit="KB">KB</button>
|
||||
<button class="btn btn-outline-primary btn-sm fullScreen"><i class="bi bi-fullscreen"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chartCanvasContainer" style="width: 100%; height: 300px">
|
||||
<canvas id="totalDataUsageChartObj" width="100" height="100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="button-div mb-3">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label for="search_peer_textbox"><small class="text-muted">Search Peers</small></label>
|
||||
<input type="text" class="form-control" id="search_peer_textbox" placeholder="Enter Peer's Name" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label for="sort_by_dropdown"><small class="text-muted">Sort Peers By</small></label>
|
||||
<select class="form-control" id="sort_by_dropdown">
|
||||
<option value="status">Status</option>
|
||||
<option value="name">Name</option>
|
||||
<option value="allowed_ip">Allowed IP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label><small class="text-muted">Refresh Interval</small></label><br>
|
||||
<div class="btn-group interval-btn-group" role="group" style="width: 100%">
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary btn-group-label refresh" data-toggle="tooltip" data-placement="bottom" title="Refresh Peers"><i class="bi bi-arrow-repeat"></i></button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="5000">5s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="10000">10s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="30000">30s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="60000">1m</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label><small class="text-muted">Display Mode</small></label><br>
|
||||
<div class="btn-group display-btn-group" role="group" style="width: 100%">
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode" data-display-mode="grid"><i class="bi bi-grid-fill" style="font-size: 1.5rem;"></i></button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode" data-display-mode="list"><i class="bi bi-list" style="font-size: 1.5rem;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-manage-group">
|
||||
<button type="button" class="btn btn-primary add_btn"><i class="bi bi-plus-circle-fill" style=""></i></button>
|
||||
<button type="button" class="btn btn-secondary setting_btn"><i class="bi bi-three-dots"></i></button>
|
||||
<div class="setting_btn_menu">
|
||||
<a class="text-danger" id="delete_peers_by_bulk_btn"><i class="bi bi-trash-fill"></i> Delete Peers</a>
|
||||
<a class="text-info" id="download_all_peers" data-url="/download_all/{{conf_data['name']}}"><i class="bi bi-cloud-download-fill"></i> Download All Peers</a>
|
||||
<hr>
|
||||
<a class="text-primary" id="configuration_setting"><i class="bi bi-gear-fill"></i> Configration Settings</a>
|
||||
<a class="text-danger" id="configuration_delete"><i class="bi bi-trash3-fill"></i> Delete Configuration</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row peer_list"></div>
|
||||
<small id="peer_loading_time" class="text-muted"></small>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="add_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Add New Peer</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<div class="custom-control custom-switch" style="margin-bottom: 1rem">
|
||||
<input class="custom-control-input" type="checkbox" id="bulk_add">
|
||||
<label class="custom-control-label" for="bulk_add"><strong>Add Peers by bulk</strong></label>
|
||||
<i class="bi bi-question-circle-fill" style="cursor: pointer" data-container="body" data-toggle="popover" data-placement="right" data-trigger="click" data-content="By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP."></i>
|
||||
</div>
|
||||
<div class="form-group" style="margin: 0">
|
||||
<input type="number" class="form-control" id="new_add_amount" min="1" placeholder="Amount" disabled>
|
||||
<div id="bulk_amount_validation" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<div id="add_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="add_peer_form">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label for="private_key">Private Key</label>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control non-bulk" id="private_key" aria-describedby="private_key">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-danger non-bulk" id="re_generate_key" data-toggle="tooltip" data-placement="top" title="Regenerate Key"><i class="bi bi-arrow-repeat"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="public_key">Public Key <code>(Required)</code></label>
|
||||
<input type="text" class="form-control non-bulk" id="public_key" aria-describedby="public_key" disabled>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="new_add_name">Name</label>
|
||||
<input type="text" class="form-control non-bulk" id="new_add_name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="allowed_ips">Allowed IPs <code>(Required)</code></label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control non-bulk" id="allowed_ips">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary non-bulk" id="search_available_ip" data-toggle="tooltip" data-placement="top" title="Search Available IPs">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="position: absolute; top: 4px; right: 1rem;" class="text-success" id="allowed_ips_indicator"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="new_add_DNS">DNS <code>(Required)</code></label>
|
||||
<input type="text" class="form-control" id="new_add_DNS" value="{{ DNS }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="new_add_endpoint_allowed_ip">Endpoint Allowed IPs <code>(Required)</code></label>
|
||||
<input type="text" class="form-control" id="new_add_endpoint_allowed_ip" value="{{ endpoint_allowed_ip }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="new_add_MTU">MTU</label>
|
||||
<input type="text" class="form-control" id="new_add_MTU" value="{{ mtu }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="new_add_keep_alive">Persistent keepalive</label>
|
||||
<input type="text" class="form-control" id="new_add_keep_alive" value="{{ keep_alive }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="enable_preshare_key" name="enable_preshare_key" value="enable_psk">
|
||||
<label class="form-check-label" for="enable_preshare_key">Use Pre-shared Key</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="save_peer" conf_id={{conf_data['name']}}>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="configuration_delete_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Are you sure to delete this configuration?</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="remove_configuration_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
||||
|
||||
</div>
|
||||
<p style="margin: 0">This action is not reversible. The configuration will get toggle off, and delete from database and from the configuration folder.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
||||
<button type="button" class="btn btn-danger" id="sure_delete_configuration">Yes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="delete_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Are you sure to delete this peer?</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<h6 style="margin: 0">This action is not reversible.</h6>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
||||
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}} peer_id="">Yes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="setting_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true" conf_id={{conf_data['name']}} peer_id="">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title peer_name"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="setting_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="peer_private_key_textbox" class="form-label">Private Key <code>(Required for QR Code and download)</code></label>
|
||||
<input type="password" class="form-control" id="peer_private_key_textbox" style="padding-right: 40px">
|
||||
<a class="peer_private_key_textbox_switch"><i class="bi bi-eye-fill"></i></a>
|
||||
</div>
|
||||
<div>
|
||||
<label for="peer_preshared_key_textbox" class="form-label">Pre-Shared Key</label>
|
||||
<input type="text" class="form-control" id="peer_preshared_key_textbox">
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_name_textbox" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="peer_name_textbox" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_allowed_ip_textbox" class="form-label">Allowed IPs <code>(Required)</code></label>
|
||||
<input type="text" class="form-control" id="peer_allowed_ip_textbox">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_DNS_textbox" class="form-label">DNS <code>(Required)</code></label>
|
||||
<input type="text" class="form-control" id="peer_DNS_textbox">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_endpoint_allowed_ips" class="form-label">Endpoint Allowed IPs <code>(Required)</code></label>
|
||||
<input type="text" class="form-control" id="peer_endpoint_allowed_ips">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_mtu" class="form-label">MTU</label>
|
||||
<input type="text" class="form-control" id="peer_mtu">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-3">
|
||||
<label for="peer_keep_alive" class="form-label">Persistent Keepalive</label>
|
||||
<input type="text" class="form-control" id="peer_keep_alive">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="save_peer_setting" data-conf-id="{{conf_data['name']}}" data-peer-id="">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="available_ip_modal" data-backdrop="static" data-keyboard="false">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Select available IP</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="selected_ip" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
||||
<small class="text-muted"><strong>SELECTED IP (CLICK TO REMOVE)</strong></small>
|
||||
<div id="selected_ip_list"></div>
|
||||
</div>
|
||||
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
||||
<div class="list-group"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="confirm_ip">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="delete_bulk_modal" data-backdrop="static" data-keyboard="false">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Select Peers to Delete</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="bulk_remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert" style="margin: 1rem">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="selected_peers" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
||||
<small class="text-muted"><strong>SELECTED PEERS (CLICK TO REMOVE)</strong></small>
|
||||
<div id="selected_peer_list"></div>
|
||||
</div>
|
||||
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
||||
<div class="list-group"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="text-danger" id="select_all_delete_bulk_peers" style="cursor: pointer; margin-right: auto;"><small><strong>SELECT ALL</strong></small></a>
|
||||
<button type="button" class="btn btn-danger" id="confirm_delete_bulk_peers" disabled data-conf="{{conf_data['name']}}">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="qrcode_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">QR Code</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<img id="qrcode_img" style="width: 100%">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-fixed top-0 right-0 p-3 toastContainer" style="z-index: 5; right: 0; top: 50px;"></div>
|
||||
{% include "tools.html" %}
|
||||
</body>
|
||||
{% include "footer.html" %}
|
||||
<script src="{{ url_for('static',filename='js/configuration.js') }}"></script>
|
||||
<script src="{{ url_for('static',filename='js/wireguard.min.js') }}"></script>
|
||||
<script>
|
||||
configurations.setConfigurationName("{{ conf_data['name'] }}");
|
||||
configurations.setActiveConfigurationName();
|
||||
configurations.loadPeers($('#search_peer_textbox').val());
|
||||
</script>
|
||||
</html>
|
||||
2
WG-Dash/src/templates/footer.html
Normal file
2
WG-Dash/src/templates/footer.html
Normal file
@ -0,0 +1,2 @@
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" 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>
|
||||
184
WG-Dash/src/templates/get_conf.html
Normal file
184
WG-Dash/src/templates/get_conf.html
Normal file
@ -0,0 +1,184 @@
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
||||
<div class="info mt-4">
|
||||
{% if conf_data['listen_port'] == "" and conf_data['status'] == "stopped" %}
|
||||
<div class="alert alert-warning" role="alert">Peer QR Code and configuration file download required a specified <strong>Listen Port</strong>.</div>
|
||||
{% endif %}
|
||||
{% if conf_data['conf_address'] == "N/A" %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Configuration <strong>Address</strong> not be specified to have peer connect to it.
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>ZONE</strong></small>
|
||||
<h1 class="mb-3"><samp>{{conf_data['name']}}</samp></h1>
|
||||
</div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>ACTION</strong></small><br>
|
||||
{% if conf_data['checked'] == "checked" %}
|
||||
<a href="#" id="{{conf_data['name']}}" {{conf_data['checked']}} class="switch text-primary"><i class="bi bi-toggle2-on"></i> ON</a>
|
||||
{% else %}
|
||||
<a href="#" id="{{conf_data['name']}}" {{conf_data['checked']}} class="switch text-secondary"><i class="bi bi-toggle2-off"></i> OFF</a>
|
||||
{% endif %}
|
||||
<div class="spinner-border text-primary" role="status" style="display: none; margin-top: 10px">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>STATUS</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{conf_data['status']}}<span class="dot dot-{{conf_data['status']}}"></span></h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<small class="text-muted"><strong>CONNECTED PEERS</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{conf_data['running_peer']}}</h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL DATA USAGE</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][0]}} GB</h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL RECEIVED</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][1]}} GB</h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>TOTAL SENT</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{conf_data['total_data_usage'][2]}} GB</h6>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted">
|
||||
<strong>PUBLIC KEY</strong>
|
||||
<strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong>
|
||||
</small>
|
||||
<h6><samp class="key">{{conf_data['public_key']}}</samp></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>LISTEN PORT</strong></small>
|
||||
<h6 style="text-transform: uppercase;"><samp>
|
||||
{% if conf_data['listen_port'] == "" %}
|
||||
N/A
|
||||
{% else %}
|
||||
{{conf_data['listen_port']}}
|
||||
{% endif %}
|
||||
</samp></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>ADDRESS</strong></small>
|
||||
<h6 style="text-transform: uppercase;"><samp>{{conf_data['conf_address']}}</samp></h6>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="button-div mb-3">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label for="sort_by_dropdown"><small class="text-muted">Sort Peers By</small></label>
|
||||
<select class="form-control" id="sort_by_dropdown">
|
||||
<option value="status" {% if sort_tag == "status" %} {{ "selected" }} {% endif %}>Status</option>
|
||||
<option value="name" {% if sort_tag == "name" %} {{ "selected" }} {% endif %}>Name</option>
|
||||
<option value="allowed_ip" {% if sort_tag == "allowed_ip" %} {{ "selected" }} {% endif %}>Allowed IP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label><small class="text-muted">Refresh Interval</small></label><br>
|
||||
<div class="btn-group" role="group" style="width: 100%">
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary btn-group-label refresh"><i class="bi bi-arrow-repeat"></i></button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval {% if dashboard_refresh_interval == 5000 %} {{ "active" }} {% endif %}" refresh-interval="5000">5s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval {% if dashboard_refresh_interval == 10000 %} {{ "active" }} {% endif %}" refresh-interval="10000">10s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval {% if dashboard_refresh_interval == 30000 %} {{ "active" }} {% endif %}" refresh-interval="30000">30s</button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval {% if dashboard_refresh_interval == 60000 %} {{ "active" }} {% endif %}" refresh-interval="60000">1m</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label><small class="text-muted">Display Mode</small></label><br>
|
||||
<div class="btn-group" role="group" style="width: 100%">
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode {% if peer_display_mode == "grid" %} {{ "active" }} {% endif %}" display-mode="grid"><i class="bi bi-grid-fill" style="font-size: 1.5rem;"></i></button>
|
||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode {% if peer_display_mode == "list" %} {{ "active" }} {% endif %}" display-mode="list"><i class="bi bi-list" style="font-size: 1.5rem;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary add_btn" data-toggle="modal" data-target="#add_modal">
|
||||
<i class="bi bi-plus-circle-fill" style=""></i> Add Peer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row peer_list">
|
||||
{% if conf_data['peer_data']|length == 0 %}
|
||||
<div class="col-12" style="text-align: center; margin-top: 1.5rem"><h3 class="text-muted">Oops! No peers found ‘︿’</h3></div>
|
||||
{% endif %}
|
||||
|
||||
{% for i in conf_data['peer_data']%}
|
||||
{% if peer_display_mode == "list" %}
|
||||
<div class="col-12">
|
||||
{% else %}
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
{% endif %}
|
||||
<div class="card mb-3 card-{{i['status']}}">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<h4>
|
||||
{% if not i['name']%}
|
||||
{{ "Untitled" }}
|
||||
{% else %}
|
||||
{{i['name']}}
|
||||
{% endif %}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col-6">
|
||||
<small class="text-muted"><strong>STATUS</strong></small>
|
||||
<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 class="col-6 peer_data_group" style="text-align: right">
|
||||
<small class="text-muted"><strong>TRANSFER</strong></small>
|
||||
<p class="text-primary" style="text-transform: uppercase; margin-bottom: 0;"><small><i class="bi bi-arrow-down-right"></i> {{i['total_receive']}} GB</small></p>
|
||||
<p class="text-success" style="text-transform: uppercase; margin-bottom: 0"><small><i class="bi bi-arrow-up-right"></i> {{i['total_sent']}} GB</small></p>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted" style="display: flex">
|
||||
<strong>PEER</strong>
|
||||
<strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong></small>
|
||||
<h6><samp class="ml-auto key">{{i['id']}}</samp></h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>ALLOWED IP</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{i['allowed_ip']}}</h6>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>LATEST HANDSHAKE</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{i['latest_handshake']}}</h6>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col-sm">
|
||||
<small class="text-muted"><strong>END POINT</strong></small>
|
||||
<h6 style="text-transform: uppercase;">{{i['endpoint']}}</h6>
|
||||
</div>
|
||||
<div class="w-100"></div>
|
||||
<div class="col-sm"><hr><div class="button-group" style="display:flex"><button type="button" class="btn btn-outline-primary btn-setting-peer btn-control" id="{{i['id']}}" data-toggle="modal"><i class="bi bi-gear-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'] %}
|
||||
<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/{{ 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>
|
||||
</button>
|
||||
<a href="/download/{{ conf_data['name'] }}?id={{ i['id']|urlencode }}" class="btn btn-outline-info btn-download-peer btn-control">
|
||||
<i class="bi bi-download"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%endfor%}
|
||||
</div>
|
||||
</main>
|
||||
25
WG-Dash/src/templates/header.html
Normal file
25
WG-Dash/src/templates/header.html
Normal file
@ -0,0 +1,25 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>{{ title }} | WireGate</title>
|
||||
<link rel="manifest" href="{{ url_for('static',filename='json/manifest.json') }}">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="application-name" content="WireGate">
|
||||
<meta name="apple-mobile-web-app-title" content="WireGate">
|
||||
<meta name="msapplication-starturl" content="/">
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="{{ url_for('static',filename='img/192x192ios.png') }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="icon" href="{{ url_for('static',filename='img/logo.png') }}"/>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
|
||||
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='css/dashboard.min.css') }}">
|
||||
<!-- THEME APPLY HERE -->
|
||||
{% if session["theme"] == "dark" %}
|
||||
<link rel= "stylesheet" type= "text/css" href="{{ url_for('static',filename='css/theme/dark.min.css') }}" id="darkThemeCSS">
|
||||
{% endif %}
|
||||
<!-- THEME APPLY HERE -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
|
||||
</head>
|
||||
|
||||
77
WG-Dash/src/templates/index.html
Normal file
77
WG-Dash/src/templates/index.html
Normal file
@ -0,0 +1,77 @@
|
||||
<!-- index.html - < WGDashboard > - Copyright(C) 2021 Donald Zou [https://github.com/donaldzou]-->
|
||||
<html lang="en">
|
||||
{% with %}
|
||||
{% set title="Home" %}
|
||||
{% include "header.html"%}
|
||||
{% endwith %}
|
||||
|
||||
<body>
|
||||
{% include "navbar.html" %}
|
||||
<div class="container-fluid">
|
||||
{% include "sidebar.html" %}
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mb-4">
|
||||
<div style="display: flex; flex-direction: row; align-items: center;">
|
||||
<h1 class="pb-4 mt-4">Home</h1>
|
||||
</div>
|
||||
<!-- {% if msg != "" %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
Configuration toggle failed. Please check the following error message:
|
||||
</div>
|
||||
<pre class="index-alert"><code>{{ msg }}</code></pre>
|
||||
{% endif %} -->
|
||||
<div class="index-alert alert alert-danger d-none" role="alert">
|
||||
Configuration toggle failed. Please check the following error message:
|
||||
</div>
|
||||
<pre class="index-alert index-alert-full d-none"><code></code></pre>
|
||||
|
||||
{% if conf == [] %}
|
||||
<p class="text-muted">You don't have any WireGuard configurations yet. Please check the configuration folder or change it in "Settings". By default the folder is "/etc/wireguard".</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% for i in conf%}
|
||||
<div class="card mt-3 conf_card" data-conf-id="{{i['conf']}}">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col card-col">
|
||||
<small class="text-muted"><strong>ZONE</strong></small>
|
||||
<a href="/configuration/{{i['conf']}}" class="conf_link">
|
||||
<h6 class="card-title" style="margin:0 !important;"><samp>{{i['conf']}}</samp></h6>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col card-col">
|
||||
<small class="text-muted"><strong>STATUS</strong></small>
|
||||
<h6 style="text-transform: uppercase; margin:0 !important;"><span>{{i['status']}}</span><span class="dot dot-{{i['status']}}"></span></h6>
|
||||
</div>
|
||||
<div class="col-sm card-col">
|
||||
<small class="text-muted"><strong>PUBLIC KEY</strong></small>
|
||||
<h6 style="margin:0 !important;"><samp>{{i['public_key']}}</samp></h6>
|
||||
</div>
|
||||
<div class="col-sm index-switch">
|
||||
<div class="switch-test">
|
||||
<input type="checkbox" class="toggle--switch" id="{{i['conf']}}-switch" {{i['checked']}} data-conf-id="{{i['conf']}}">
|
||||
<label for="{{i['conf']}}-switch" class="toggleLabel"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-message"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{%endfor%}
|
||||
</main>
|
||||
</div>
|
||||
<div class="position-fixed top-0 right-0 p-3 toastContainer" style="z-index: 5; right: 0; top: 50px;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% 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/index.min.js') }}"></script>
|
||||
|
||||
</html>
|
||||
10
WG-Dash/src/templates/navbar.html
Normal file
10
WG-Dash/src/templates/navbar.html
Normal file
@ -0,0 +1,10 @@
|
||||
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="/">WireGate</a>
|
||||
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse"
|
||||
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</nav>
|
||||
<div class="progress" style="height: 3px; position: fixed; width: 100%; z-index: 10000; background-color: transparent">
|
||||
<div class="progress-bar" role="progressbar" style="z-index: 10000; width: 0%"></div>
|
||||
</div>
|
||||
1
WG-Dash/src/templates/qrcode.html
Normal file
1
WG-Dash/src/templates/qrcode.html
Normal file
@ -0,0 +1 @@
|
||||
{{ qrcode(i) }}
|
||||
179
WG-Dash/src/templates/settings.html
Normal file
179
WG-Dash/src/templates/settings.html
Normal file
@ -0,0 +1,179 @@
|
||||
<html>
|
||||
{% with %}
|
||||
{% set title="Settings" %}
|
||||
{% include "header.html" %}
|
||||
{% endwith %}
|
||||
<body>
|
||||
{% include "navbar.html" %}
|
||||
<div class="container-fluid">
|
||||
{% include "sidebar.html" %}
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<div class="setting-container mt-4">
|
||||
{% if message != "" %}
|
||||
<div class="alert alert-{{ status }}" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<h1 class="">Settings</h1>
|
||||
<hr>
|
||||
<div class="card mb-3">
|
||||
<h6 class="card-header">Dashboard Theme</h6>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<button class='btn btn-outline-primary theme-switch-btn {% if session["theme"] == "light" %} {{ "active" }} {% endif %}' data-theme="light">
|
||||
<i class="bi bi-sun-fill"></i>
|
||||
Light
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class='btn btn-outline-primary theme-switch-btn {% if session["theme"] == "dark" %} {{ "active" }} {% endif %}' data-theme="dark">
|
||||
<i class="bi bi-moon-fill"></i>
|
||||
Dark
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{% if required_auth == "true" %}
|
||||
<div class="card mb-3">
|
||||
<h6 class="card-header">Peer Default Settings</h6>
|
||||
<div class="card-body">
|
||||
<form action="/update_peer_default_config" method="post">
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label for="peer_global_DNS">DNS</label>
|
||||
<input type="text" class="form-control mb-4" id="peer_global_DNS"
|
||||
name="peer_global_DNS"
|
||||
value="{{ peer_global_DNS }}" required>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="peer_endpoint_allowed_ip">Peer Endpoint Allowed IPs</label>
|
||||
<input type="text" class="form-control mb-4" id="peer_endpoint_allowed_ip"
|
||||
name="peer_endpoint_allowed_ip"
|
||||
value="{{ peer_endpoint_allowed_ip }}" required>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="peer_mtu">MTU</label>
|
||||
<input type="text" class="form-control mb-4" id="peer_mtu"
|
||||
name="peer_mtu"
|
||||
value="{{ peer_mtu }}">
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="peer_keep_alive">Persistent Keepalive</label>
|
||||
<input type="text" class="form-control mb-4" id="peer_keep_alive"
|
||||
name="peer_keep_alive"
|
||||
value="{{ peer_keepalive }}">
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<label for="peer_remote_endpoint"><strong>Peer Remote Endpoint (This will be change globally, and will be apply to all peer's QR code and configuration file.)</strong></label>
|
||||
<input type="text" class="form-control mb-4" id="peer_remote_endpoint"
|
||||
name="peer_remote_endpoint"
|
||||
value="{{ peer_remote_endpoint }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-success" type="submit">Update Peer Default Settings</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="card mb-3">
|
||||
<h6 class="card-header">WireGuard Configuration Path</h6>
|
||||
<div class="card-body">
|
||||
<form action="/update_wg_conf_path" method="post" class="update_wg_conf_path">
|
||||
<div class="form-group">
|
||||
<label for="wg_conf_path">Path</label>
|
||||
<input type="text" class="form-control mb-2" id="wg_conf_path" name="wg_conf_path"
|
||||
value="{{ wg_conf_path }}">
|
||||
<p class="text-muted">Remember to remove <code>/</code> at the end of your path. e.g <code>/etc/wireguard</code>
|
||||
</p>
|
||||
<button class="btn btn-danger change_path">Update Path & Restart Dashboard</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<h6 class="card-header">Account</h6>
|
||||
<div class="card-body">
|
||||
<form action="/update_acct" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control mb-4" id="username" name="username"
|
||||
value="{{ session['username'] }}" required>
|
||||
<button type="submit" class="btn btn-danger">Update Account</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<h6 class="card-header">Security</h6>
|
||||
<div class="card-body">
|
||||
<form action="/update_pwd" method="post">
|
||||
<div class="form-group">
|
||||
<label for="currentpass">Current Password</label>
|
||||
<input type="password" class="form-control mb-2" id="currentpass" name="currentpass">
|
||||
<label for="newpass">New Password</label>
|
||||
<input type="password" class="form-control mb-2" id="newpass" name="newpass">
|
||||
<label for="repnewpass">Repeat New Password</label>
|
||||
<input type="password" class="form-control mb-4" id="repnewpass" name="repnewpass">
|
||||
<button type="submit" class="btn btn-danger">Update Password</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card">
|
||||
<h6 class="card-header">Dashboard Configuration</h6>
|
||||
<div class="card-body">
|
||||
<form action="/update_app_ip_port" method="post" class="update_app_ip_port">
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<label for="app_ip">Dashboard IP</label>
|
||||
<input type="text" class="form-control mb-2" id="app_ip" name="app_ip" value="{{ app_ip }}">
|
||||
<p><small class="text-danger mb-4">0.0.0.0 means it can be access by anyone with your server
|
||||
IP Address.</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-danger confirm_modal" data-toggle="modal"
|
||||
data-target="#confirmModal">Update Configuration & Restart Dashboard
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="confirmModal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Confirm Dashboard Configuration</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<small>Dashboard Original IP</small>
|
||||
<p>{{ app_ip }}</p>
|
||||
<small style="font-weight: bold" class="text-bold">Dashboard New IP</small>
|
||||
<p class="app_new_ip text-bold text-danger" style="font-weight: bold"></p>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary cancel_restart" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger confirm_restart">Confirm & Restart Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "tools.html" %}
|
||||
<div class="position-fixed top-0 right-0 p-3 toastContainer" style="z-index: 5; right: 0; top: 50px;"></div>
|
||||
</body>
|
||||
{% include "footer.html" %}
|
||||
<script src="{{ url_for('static',filename='js/settings.js') }}"></script>
|
||||
|
||||
</html>
|
||||
66
WG-Dash/src/templates/sidebar.html
Normal file
66
WG-Dash/src/templates/sidebar.html
Normal file
@ -0,0 +1,66 @@
|
||||
<div class="row">
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||
<div class="sidebar-sticky pt-3">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link sb-home-url" href="/">Home</a></li>
|
||||
{% if "username" in session %}
|
||||
<li class="nav-item"><a class="nav-link sb-settings-url" href="/settings">Settings</a></li>
|
||||
{% endif %}
|
||||
{% if session['update'] == "true" %}
|
||||
<li class="nav-item sb-update-li">
|
||||
<a class="nav-link sb-update-url" href="https://github.com/donaldzou/WGDashboard#-how-to-update-the-dashboard">New Update Available!<span class="dot dot-running"></span></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<hr>
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<span>Zones</span>
|
||||
</h6>
|
||||
<ul class="nav flex-column">
|
||||
{% for i in conf%}
|
||||
<li class="nav-item"><a class="nav-link nav-conf-link sb-{{i['conf']}}-url" href="/configuration/{{i['conf']}}" data-conf-id="{{i['conf']}}"><samp>{{i['conf']}}</samp></a></li>
|
||||
{%endfor%}
|
||||
</ul>
|
||||
<hr>
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<span>Tools</span>
|
||||
</h6>
|
||||
<ul class="nav flex-column">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" data-toggle="modal" data-target="#ping_modal" href="#">Ping</a></li>
|
||||
<li class="nav-item"><a class="nav-link" data-toggle="modal" data-target="#traceroute_modal" href="#">Traceroute</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<hr>
|
||||
{% if "username" in session %}
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link text-danger" href="/signout" style="font-weight: bold">Sign Out</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a href="https://hub.docker.com/repository/docker/noxcis/wg-dashboard/general"><small class="nav-link text-muted">{{ session['dashboard_version'] }}</small></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.7.1.min.js"
|
||||
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Add click event listener to links in the "Zones" section
|
||||
$('.nav-conf-link').on('click', function(event) {
|
||||
event.preventDefault(); // Prevent default behavior (e.g., navigating to the href)
|
||||
|
||||
// Get the href attribute of the clicked link
|
||||
var url = $(this).attr('href');
|
||||
|
||||
// Redirect to the specified URL
|
||||
window.location.href = url;
|
||||
});
|
||||
});
|
||||
</script
|
||||
87
WG-Dash/src/templates/signin.html
Normal file
87
WG-Dash/src/templates/signin.html
Normal file
@ -0,0 +1,87 @@
|
||||
<html>
|
||||
{% with title="Sign In"%}
|
||||
{% include "header.html"%}
|
||||
{% endwith %}
|
||||
<style>
|
||||
.login-container-fluid{
|
||||
display: flex;
|
||||
height: calc( 100% - 240px );
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
{% include "navbar.html" %}
|
||||
<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>
|
||||
<h5 class="text-center">to WireGate</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" 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></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></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>
|
||||
</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>
|
||||
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){
|
||||
loginButton.html("Sign In");
|
||||
check = false;
|
||||
$(req[i]).addClass("is-invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (check){
|
||||
$(this).html("Signing In...").attr("disabled", "disabled");
|
||||
$.ajax({
|
||||
url: "/auth",
|
||||
method: "POST",
|
||||
headers:{"Content-Type": "application/json"},
|
||||
data: JSON.stringify({
|
||||
"username": $("#username").val(),
|
||||
"password": $("#password").val()
|
||||
})
|
||||
}).done(function(res){
|
||||
if (res.status === true){
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (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").fadeIn();
|
||||
loginButton.html("Sign In").removeAttr("disabled");
|
||||
$("input[required]").addClass("is-invalid");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
121
WG-Dash/src/templates/tools.html
Normal file
121
WG-Dash/src/templates/tools.html
Normal file
@ -0,0 +1,121 @@
|
||||
<div class="modal fade" id="ping_modal" data-backdrop="static" data-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Ping</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="mb-3">
|
||||
<small>Configuration</small>
|
||||
<select class="form-control mt-2 conf_dropdown">
|
||||
<option value="none" selected="selected" disabled>Select Configuration</option>
|
||||
{% for i in conf%}
|
||||
<option value="{{ i['conf'] }}">{{ i['conf'] }}</option>
|
||||
{%endfor%}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="mb-3">
|
||||
<small>IP</small>
|
||||
<select class="form-control mt-2 ip_dropdown">
|
||||
<option value="none" selected="selected" disabled>Choose an IP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="mb-3">
|
||||
<small>Ping Count</small>
|
||||
<input type="number" class="form-control mt-2 ping_count" min=1 value=4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="ping_result">
|
||||
<table class="table">
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary send_ping" disabled>Ping</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="traceroute_modal" data-backdrop="static" data-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Traceroute</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="mb-3">
|
||||
<small>Configuration</small>
|
||||
<select class="form-control mt-2 conf_dropdown">
|
||||
<option value="none" selected="selected" disabled>Select Configuration</option>
|
||||
{% for i in conf%}
|
||||
<option value="{{ i['conf'] }}">{{ i['conf'] }}</option>
|
||||
{%endfor%}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="mb-3">
|
||||
<small>IP</small>
|
||||
<select class="form-control mt-2 ip_dropdown">
|
||||
<option value="none" selected="selected" disabled>Choose an IP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary send_traceroute" disabled>Traceroute</button>
|
||||
<hr>
|
||||
<div class="traceroute_result">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Hop</th>
|
||||
<th scope="col">IP</th>
|
||||
<th scope="col">Avg RTT</th>
|
||||
<th scope="col">Min RTT</th>
|
||||
<th scope="col">Max RTT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="update_modal" data-backdrop="static" data-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">How to update dashboard</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre><code>$ sudo sh wgd.sh stop</code><br><code>$ sudo sh wgd.sh update</code><br><code>$ sudo sh wgd.sh start</code></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
113
WG-Dash/src/util.py
Normal file
113
WG-Dash/src/util.py
Normal file
@ -0,0 +1,113 @@
|
||||
import re
|
||||
import subprocess
|
||||
import dashboard
|
||||
"""
|
||||
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))
|
||||
|
||||
|
||||
def deletePeers(config_name, delete_keys, cur, db):
|
||||
sql_command = []
|
||||
wg_command = ["wg", "set", config_name]
|
||||
for delete_key in delete_keys:
|
||||
if delete_key not in dashboard.get_conf_peer_key(config_name):
|
||||
return "This key does not exist"
|
||||
sql_command.append("DELETE FROM " + config_name + " WHERE id = '" + delete_key + "';")
|
||||
wg_command.append("peer")
|
||||
wg_command.append(delete_key)
|
||||
wg_command.append("remove")
|
||||
try:
|
||||
print("deleting...")
|
||||
remove_wg = subprocess.check_output(" ".join(wg_command),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
save_wg = subprocess.check_output(f"wg-quick save {config_name}", shell=True, stderr=subprocess.STDOUT)
|
||||
cur.executescript(' '.join(sql_command))
|
||||
db.commit()
|
||||
except subprocess.CalledProcessError as exc:
|
||||
return exc.output.strip()
|
||||
return "true"
|
||||
|
||||
def checkJSONAllParameter(required, data):
|
||||
if len(data) == 0:
|
||||
return False
|
||||
for i in required:
|
||||
if i not in list(data.keys()) or len(data[i]) == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
220
WG-Dash/src/wgd.sh
Normal file
220
WG-Dash/src/wgd.sh
Normal file
@ -0,0 +1,220 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
start_wgd () {
|
||||
echo -e "Start Dashboard--------------------------------------------------------------------------------\n"
|
||||
echo ""
|
||||
echo ""
|
||||
uwsgi --ini wiregate.ini
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
}
|
||||
|
||||
|
||||
|
||||
newconf_wgd () {
|
||||
newconf_wgd0
|
||||
newconf_wgd1
|
||||
newconf_wgd2
|
||||
newconf_wgd3
|
||||
newconf_wgd4
|
||||
newconf_wgd5
|
||||
}
|
||||
|
||||
|
||||
|
||||
newconf_wgd0() {
|
||||
local port_wg0=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
|
||||
cat <<EOF >"/etc/wireguard/ADMINS.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 10.0.0.1/24
|
||||
ListenPort = $port_wg0
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/Admins/wg0-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/Admins/wg0-dwn.sh
|
||||
|
||||
EOF
|
||||
if [ ! -f "/master-key/master.conf" ]; then
|
||||
make_master_config # Only call make_master_config if master.conf doesn't exist
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
newconf_wgd1() {
|
||||
local port_wg1=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
local port_wg1=$((port_wg1 + 1))
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
cat <<EOF >"/etc/wireguard/MEMEBERS.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 192.168.10.1/24
|
||||
ListenPort = $port_wg1
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/Members/wg1-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/Members/wg1-dwn.sh
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
newconf_wgd2() {
|
||||
local port_wg2=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
local port_wg2=$((port_wg2 + 2))
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
cat <<EOF >"/etc/wireguard/LANP2P.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 172.16.0.1/24
|
||||
ListenPort = $port_wg2
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/LAN-only-users/wg2-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/LAN-only-users/wg2-dwn.sh
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
newconf_wgd3() {
|
||||
local port_wg3=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
local port_wg3=$((port_wg3 + 3))
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
cat <<EOF >"/etc/wireguard/GUESTS.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 192.168.20.1/24
|
||||
ListenPort = $port_wg3
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/Guest/wg3-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/Guest/wg3-dwn.sh
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
newconf_wgd4() {
|
||||
local port_wg4=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
local port_wg4=$((port_wg4 + 4))
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
cat <<EOF >"/etc/wireguard/IPV6ADMINS.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 192.168.30.1/24
|
||||
Address = 2001:db8:30:1::/64
|
||||
ListenPort = $port_wg4
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/IPV6/wg0-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/IPV6/wg0-dwn.sh
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
newconf_wgd5() {
|
||||
local port_wg5=$WG_DASH_PORT_RANGE_STARTPORT
|
||||
local port_wg5=$((port_wg5 + 5))
|
||||
private_key=$(wg genkey)
|
||||
public_key=$(echo "$private_key" | wg pubkey)
|
||||
|
||||
cat <<EOF >"/etc/wireguard/IPV6MEMBERS.conf"
|
||||
[Interface]
|
||||
PrivateKey = $private_key
|
||||
Address = 192.168.40.1/24
|
||||
Address = 2001:db8:40:1::/64
|
||||
ListenPort = $port_wg5
|
||||
SaveConfig = true
|
||||
PostUp = /home/app/FIREWALLS/IPV6/wg1-nat.sh
|
||||
PreDown = /home/app/FIREWALLS/IPV6/wg1-dwn.sh
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
make_master_config() {
|
||||
local svr_config="/etc/wireguard/ADMINS.conf"
|
||||
# Check if the specified config file exists
|
||||
if [ ! -f "$svr_config" ]; then
|
||||
echo "Error: Config file $svr_config not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
#Function to generate a new peer's public key
|
||||
generate_public_key() {
|
||||
local private_key="$1"
|
||||
echo "$private_key" | wg pubkey
|
||||
}
|
||||
|
||||
# Function to generate a new preshared key
|
||||
generate_preshared_key() {
|
||||
wg genpsk
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Generate the new peer's public key, preshared key, and allowed IP
|
||||
wg_private_key=$(wg genkey)
|
||||
peer_public_key=$(generate_public_key "$wg_private_key")
|
||||
preshared_key=$(generate_preshared_key)
|
||||
|
||||
# Add the peer to the WireGuard config file with the preshared key
|
||||
echo -e "\n[Peer]" >> "$svr_config"
|
||||
echo "PublicKey = $peer_public_key" >> "$svr_config"
|
||||
echo "PresharedKey = $preshared_key" >> "$svr_config"
|
||||
echo "AllowedIPs = 10.0.0.254/32" >> "$svr_config"
|
||||
|
||||
|
||||
server_public_key=$(grep -E '^PrivateKey' "$svr_config" | awk '{print $NF}')
|
||||
svrpublic_key=$(echo "$server_public_key" | wg pubkey)
|
||||
|
||||
|
||||
# Generate the client config file
|
||||
cat <<EOF >"/home/app/master-key/master.conf"
|
||||
[Interface]
|
||||
PrivateKey = $wg_private_key
|
||||
Address = 10.0.0.254/32
|
||||
DNS = 10.2.0.100,10.2.0.100
|
||||
MTU = 1420
|
||||
|
||||
[Peer]
|
||||
PublicKey = $svrpublic_key
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = $WG_DASH_SERVER_IP:$WG_DASH_PORT_RANGE_STARTPORT
|
||||
PersistentKeepalive = 21
|
||||
PresharedKey = $preshared_key
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if [ "$#" != 1 ];
|
||||
then
|
||||
help
|
||||
|
||||
elif [ "$1" = "install" ]; then
|
||||
install_wgd
|
||||
elif [ "$1" = "debug" ]; then
|
||||
start_wgd_debug
|
||||
elif [ "$1" = "start" ]; then
|
||||
start_wgd
|
||||
elif [ "$1" = "newconfig" ]; then
|
||||
newconf_wgd
|
||||
else
|
||||
help
|
||||
|
||||
fi
|
||||
44
WG-Dash/src/wiregate.ini
Normal file
44
WG-Dash/src/wiregate.ini
Normal file
@ -0,0 +1,44 @@
|
||||
[uwsgi]
|
||||
plugin = python3
|
||||
module = dashboard:app
|
||||
pythonpath = /usr
|
||||
|
||||
|
||||
socket = :10086
|
||||
chmod-socket = 660
|
||||
master = true
|
||||
single-interpreter = true
|
||||
vacuum = true
|
||||
die-on-term = true
|
||||
need-app = true
|
||||
|
||||
|
||||
enable-threads = true
|
||||
processes = 2 # Set to 1 to limit the number of processes
|
||||
threads = 4 # Adjust based on the CPU and application requirements
|
||||
workers = 5 # Adjust based on the CPU and application requirements
|
||||
|
||||
|
||||
disable-logging = false
|
||||
log-4xx = true
|
||||
log-5xx = true
|
||||
|
||||
|
||||
max-requests = 500 # Adjust based on the available memory
|
||||
max-worker-lifetime = 1800 # Adjust based on the available memory
|
||||
reload-on-rss = 1024 # Adjust based on the available memory
|
||||
worker-reload-mercy = 5
|
||||
buffer-size = 6000 # Adjust based on response sizes
|
||||
|
||||
|
||||
cheaper = 2
|
||||
cheaper-initial = 2 # Adjust based on the available memory
|
||||
cheaper-overload = 30
|
||||
cheaper-step = 2
|
||||
cheaper-busyness-multiplier = 30
|
||||
cheaper-busyness-min = 20
|
||||
cheaper-busyness-max = 70
|
||||
cheaper-busyness-backlog-alert = 8
|
||||
cheaper-busyness-backlog-step = 2
|
||||
|
||||
#logto = /dev/null
|
||||
7
build.sh
7
build.sh
@ -2,14 +2,11 @@
|
||||
|
||||
api_host=$API_HOST
|
||||
|
||||
if [[ "$HEROKU_APP_NAME" =~ "-pr-" ]]
|
||||
then
|
||||
api_host=""
|
||||
fi
|
||||
|
||||
|
||||
echo "building client..."
|
||||
cd client
|
||||
yarn --production=false
|
||||
yarn --production=true
|
||||
yarn build
|
||||
cd ../
|
||||
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
TZ=UTC
|
||||
VITE_API_HOST=localhost
|
||||
VITE_API_PROTOCOL=http
|
||||
VITE_API_PORT=3001
|
||||
VITE_API_PORT=80
|
||||
VITE_COMMIT_SHA=some_sha
|
||||
|
||||
MODE=production
|
||||
# To display darkwire version
|
||||
VITE_COMMIT_SHA=some_sha
|
||||
|
||||
|
||||
@ -5,19 +5,19 @@ let port;
|
||||
|
||||
switch (import.meta.env.MODE) {
|
||||
case 'staging':
|
||||
host = import.meta.env.VITE_API_HOST;
|
||||
protocol = import.meta.env.VITE_API_PROTOCOL || 'https';
|
||||
port = import.meta.env.VITE_API_PORT || 443;
|
||||
host = import.meta.env.VITE_API_HOST || 'localhost';
|
||||
protocol = import.meta.env.VITE_API_PROTOCOL || 'http';
|
||||
port = import.meta.env.VITE_API_PORT || 80;
|
||||
break;
|
||||
case 'production':
|
||||
host = import.meta.env.VITE_API_HOST;
|
||||
protocol = import.meta.env.VITE_API_PROTOCOL || 'https';
|
||||
port = import.meta.env.VITE_API_PORT || 443;
|
||||
host = import.meta.env.VITE_API_HOST || 'localhost';
|
||||
protocol = import.meta.env.VITE_API_PROTOCOL || 'http';
|
||||
port = import.meta.env.VITE_API_PORT || 80;
|
||||
break;
|
||||
default:
|
||||
host = import.meta.env.VITE_API_HOST || 'localhost';
|
||||
protocol = import.meta.env.VITE_API_PROTOCOL || 'http';
|
||||
port = import.meta.env.VITE_API_PORT || 3001;
|
||||
port = import.meta.env.VITE_API_PORT || 80;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
73
dev-docker-compose.yml
Normal file
73
dev-docker-compose.yml
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
version: "3"
|
||||
|
||||
networks:
|
||||
private_network:
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 10.2.0.0/24
|
||||
|
||||
|
||||
services:
|
||||
darkwire.io:
|
||||
build:
|
||||
context: .
|
||||
environment:
|
||||
- TZ=UTC
|
||||
- VITE_API_PORT=4242
|
||||
- VITE_API_HOST=127.0.0.1
|
||||
- VITE_API_PROTOCOL=http
|
||||
- VITE_COMMIT_SHA=some_sha
|
||||
- VITE_MAX_FILE_SIZE=4
|
||||
- MAILGUN_API_KEY=api-key
|
||||
- MAILGUN_DOMAIN=darkwire.io
|
||||
- ABUSE_TO_EMAIL_ADDRESS=abuse@darkwire.io
|
||||
- ABUSE_FROM_EMAIL_ADDRESS=Darkwire <no-reply@darkwire.io>
|
||||
- CLIENT_DIST_DIRECTORY='client/dist'
|
||||
- ROOM_HASH_SECRET='some-uuid'
|
||||
- SITE_URL=https://darkwire.io
|
||||
- STORE_BACKEND=memory
|
||||
#- STORE_HOST=$STORE_HOST
|
||||
|
||||
ports:
|
||||
- 80:4242
|
||||
networks:
|
||||
private_network:
|
||||
ipv4_address: 10.2.0.4
|
||||
|
||||
wiregate:
|
||||
build: ./WG-Dash
|
||||
#image: noxcis/wg-dashboard:kraken
|
||||
container_name: wiregate
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./Global-Configs/Wiregate-Database:/home/app/db
|
||||
- ./Global-Configs/Master-Key:/home/app/master-key
|
||||
environment:
|
||||
- WG_DASH_USER=admin
|
||||
- WG_DASH_PASS=admin
|
||||
- WG_DASH_SECRET_KEY=some-super-secret_key
|
||||
- WG_DASH_SERVER_IP=0.0.0.0
|
||||
- WG_DASH_DNS=1.1.1.1, 8.8.8.8
|
||||
- WG_DASH_PEER_ENDPOINT_ALLOWED_IP=0.0.0.0/0
|
||||
- WG_DASH_KEEP_ALIVE=21
|
||||
- WG_DASH_MTU=1420
|
||||
- WG_DASH_PORT_RANGE_STARTPORT=443
|
||||
ports:
|
||||
- "443-448:443-448/udp"
|
||||
- 8000:80/tcp
|
||||
sysctls:
|
||||
- net.ipv4.ip_forward=1
|
||||
- net.ipv6.conf.all.forwarding=1
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
networks:
|
||||
private_network:
|
||||
ipv4_address: 10.2.0.3
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ services:
|
||||
environment:
|
||||
- TZ=UTC
|
||||
- VITE_API_PORT=80
|
||||
- VITE_API_HOST=localhost
|
||||
- VITE_API_HOST=127.0.0.1
|
||||
- VITE_API_PROTOCOL=http
|
||||
- VITE_COMMIT_SHA=some_sha
|
||||
- VITE_MAX_FILE_SIZE=4
|
||||
|
||||
@ -17,7 +17,7 @@ import getStore from './store/index.js';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const env = process.env.NODE_ENV || 'development';
|
||||
const env = process.env.NODE_ENV || 'production';
|
||||
|
||||
const app = new Koa();
|
||||
const PORT = process.env.VITE_API_PORT;
|
||||
@ -31,10 +31,10 @@ const siteURL = process.env.SITE_URL;
|
||||
|
||||
const store = getStore();
|
||||
|
||||
if ((siteURL || env === 'development') && !isReviewApp) {
|
||||
if ((siteURL || env === 'production') && !isReviewApp) {
|
||||
app.use(
|
||||
cors({
|
||||
origin: env === 'development' ? '*' : siteURL,
|
||||
origin: env === 'production' ? '*' : siteURL,
|
||||
allowMethods: ['GET', 'HEAD', 'POST'],
|
||||
credentials: true,
|
||||
}),
|
||||
@ -66,7 +66,7 @@ router.post('/abuse/:roomId', koaBody, async ctx => {
|
||||
app.use(router.routes());
|
||||
|
||||
const apiHost = process.env.API_HOST;
|
||||
const cspDefaultSrc = `'self'${apiHost ? ` https://${apiHost} wss://${apiHost}` : ''}`;
|
||||
const cspDefaultSrc = `'self'${apiHost ? ` http://${apiHost} wss://${apiHost}` : ''}`;
|
||||
|
||||
function setStaticFileHeaders(ctx) {
|
||||
ctx.set({
|
||||
@ -99,7 +99,7 @@ if (clientDistDirectory) {
|
||||
});
|
||||
}
|
||||
|
||||
const protocol = (process.env.PROTOCOL || 'http') === 'http' ? http : https;
|
||||
const protocol = (process.env.PROTOCOL || 'http') === 'http' ? http : http;
|
||||
|
||||
const httpServer = protocol.createServer(app.callback());
|
||||
|
||||
|
||||
6
start.sh
6
start.sh
@ -4,6 +4,11 @@
|
||||
set_env() {
|
||||
set -e
|
||||
|
||||
echo "
|
||||
|
||||
" > /etc/nginx/http.d/default.conf
|
||||
|
||||
|
||||
|
||||
echo "
|
||||
TZ=UTC
|
||||
@ -11,6 +16,7 @@ VITE_API_HOST=$VITE_API_HOST
|
||||
VITE_API_PROTOCOL=$VITE_API_PROTOCOL
|
||||
VITE_API_PORT=$VITE_API_PORT
|
||||
VITE_COMMIT_SHA=$VITE_COMMIT_SHA
|
||||
MODE=production
|
||||
|
||||
# To display darkwire version
|
||||
VITE_COMMIT_SHA=$VITE_COMMIT_SHA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user