mirror of
https://github.com/swissmakers/wireguard-manager.git
synced 2025-07-20 14:20:57 +02:00
fixing random secret problems with a call to util.GetPersistedSessionSecret()
This commit is contained in:
parent
4df175180f
commit
b1e03dda5a
75
README.md
75
README.md
@ -2,65 +2,41 @@
|
||||
|
||||
# wireguard-manager
|
||||
|
||||
A user-friendly web interface to manage [WireGuard](https://www.wireguard.com).
|
||||
WireGuard Manager is an open-source web application written in Go that simplifies the management of a WireGuard VPN server. It provides a user-friendly web interface for administering server settings, managing VPN client configurations, and handling user accounts. Additionally, the project supports email notifications (via SMTP or SendGrid), secure session management, and configuration change detection.
|
||||
|
||||
## Features
|
||||
|
||||
- Simple and intuitive UI
|
||||
- Authentication
|
||||
- Manage client information (name, email, etc.)
|
||||
- Retrieve client config via QR code, file download, or email
|
||||
- Manage WireGuard server settings, VPN client configurations, and user accounts through an intuitive web interface.
|
||||
- Create, update, and delete VPN clients. Automatically generate client configurations and QR codes.
|
||||
- Send client configuration files via email using either SMTP or SendGrid.
|
||||
- Secure Session Management: Sessions are managed using Gorilla Sessions with a persisted session secret stored in the JSON DB, ensuring that session cookies remain valid across restarts.
|
||||
- Configuration Change Detection: Polls for configuration changes and prompts the admin to apply new configurations via an “Apply Config” button.
|
||||
- A dark mode user interface with responsive design for an improved user experience.
|
||||
|
||||

|
||||
|
||||
> **Note:** The default login username/password is `admin/wmanager`. Please change it in your environment for production.
|
||||

|
||||
|
||||
> **Note:** The default login username/password is `admin/swissmakers`. Please change it in your environment for production.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Quick Start](#quick-start)
|
||||
- [Using the Binary](#using-the-binary)
|
||||
- [Using Docker Compose](#using-docker-compose)
|
||||
2. [Installation Example on CentOS/RHEL 9 (Manual Setup)](#installation-example-on-centosrhel-9-manual-setup)
|
||||
1. [Installation Example on CentOS/RHEL 9 (Manual Setup)](#installation-example-on-centosrhel-9-manual-setup)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Steps](#steps)
|
||||
3. [Environment Variables](#environment-variables)
|
||||
2. [Environment Variables](#environment-variables)
|
||||
- [Defaults for Server Configuration](#defaults-for-server-configuration)
|
||||
- [Defaults for New Clients](#defaults-for-new-clients)
|
||||
- [Docker-Only Variables](#docker-only-variables)
|
||||
4. [Auto-Restarting WireGuard](#auto-restarting-wireguard)
|
||||
3. [Auto-Restarting WireGuard](#auto-restarting-wireguard)
|
||||
- [Using systemd](#using-systemd)
|
||||
- [Using OpenRC](#using-openrc)
|
||||
- [Using Docker](#using-docker)
|
||||
5. [Build From Source](#build-from-source)
|
||||
4. [Build From Source](#build-from-source)
|
||||
- [Build Docker Image](#build-docker-image)
|
||||
- [Build Binary File](#build-binary-file)
|
||||
6. [License](#license)
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using the Binary
|
||||
|
||||
1. **Download** the latest release from the [GitHub Releases](https://github.com/swissmakers/wireguard-manager/releases).
|
||||
2. **Make it executable** and run it:
|
||||
```bash
|
||||
chmod +x wireguard-manager
|
||||
./wireguard-manager
|
||||
```
|
||||
3. **Access the web interface** in your browser. By default, it listens on `:80` (or as defined by `BIND_ADDRESS`).
|
||||
|
||||
### Using Docker Compose
|
||||
|
||||
1. Check out the [examples/docker-compose](examples/docker-compose) folder for sample Compose files.
|
||||
2. **Adjust** the environment variables and ports in your chosen `docker-compose.yml` as needed.
|
||||
3. **Start** the containers:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
4. **Access** the web interface in your browser at `http://<your-docker-host>:<port>`.
|
||||
5. [License](#license)
|
||||
|
||||
---
|
||||
|
||||
@ -98,10 +74,15 @@ Below is a step-by-step guide demonstrating how to set up `wireguard-manager` **
|
||||
npm
|
||||
```
|
||||
|
||||
4. **(Optional) Install specific Golang RPMs**:
|
||||
If your environment needs a newer version of Go than provided by default, you can grab the RPMs (example shown below). Adjust version links as necessary:
|
||||
4. **Clone `wireguard-manager` repository**:
|
||||
```bash
|
||||
mkdir -p ~/dev/go-rpms && cd ~/dev/go-rpms
|
||||
git clone https://github.com/swissmakers/wireguard-manager.git /opt/wireguard-manager
|
||||
```
|
||||
|
||||
5. **(Optional) Install specific Golang RPMs**:
|
||||
If your environment needs a newer version of Go than provided by default, you can grab the RPMs (example shown below) or use the already downloaded ones inside "./dev/go-rpm" folder inside this project.
|
||||
```bash
|
||||
mkdir -p ./dev/go-rpms && cd ./dev/go-rpms
|
||||
wget https://rpmfind.net/linux/centos-stream/9-stream/AppStream/x86_64/os/Packages/golang-race-1.23.2-1.el9.x86_64.rpm
|
||||
wget https://rpmfind.net/linux/centos-stream/9-stream/AppStream/x86_64/os/Packages/golang-bin-1.23.2-1.el9.x86_64.rpm
|
||||
wget https://rpmfind.net/linux/centos-stream/9-stream/AppStream/x86_64/os/Packages/golang-src-1.23.2-1.el9.noarch.rpm
|
||||
@ -109,11 +90,6 @@ Below is a step-by-step guide demonstrating how to set up `wireguard-manager` **
|
||||
dnf install -y ./*.rpm
|
||||
```
|
||||
|
||||
5. **Clone `wireguard-manager` repository**:
|
||||
```bash
|
||||
git clone https://github.com/swissmakers/wireguard-manager.git /opt/wireguard-manager
|
||||
```
|
||||
|
||||
6. **Create a dedicated WireGuard user and config**:
|
||||
```bash
|
||||
useradd -m -r -s /bin/false -d /var/lib/wireguard wireguard
|
||||
@ -141,11 +117,11 @@ Below is a step-by-step guide demonstrating how to set up `wireguard-manager` **
|
||||
WGM_USERNAME="admin"
|
||||
WGM_PASSWORD="**********************************"
|
||||
WGM_ENDPOINT_ADDRESS="vpn.example.com"
|
||||
WGM_DNS="1.1.1.1"
|
||||
WGM_DNS="8.8.8.8"
|
||||
WGM_MTU="1450"
|
||||
WGM_PERSISTENT_KEEPALIVE="15"
|
||||
WGM_CONFIG_FILE_PATH="/etc/wireguard/wg0.conf"
|
||||
WGM_LOG_LEVEL="DEBUG"
|
||||
# WGM_LOG_LEVEL="DEBUG"
|
||||
# WG_CONF_TEMPLATE=
|
||||
EMAIL_FROM_ADDRESS=noreply@example.com
|
||||
EMAIL_FROM_NAME=noreply
|
||||
@ -327,6 +303,7 @@ wireguard-manager generates and updates the `wg0.conf` (or your chosen interface
|
||||
|
||||
- **Enable and start** the path + service:
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable wgm.{path,service}
|
||||
systemctl start wgm.{path,service}
|
||||
```
|
||||
|
10
main.go
10
main.go
@ -46,10 +46,9 @@ var (
|
||||
flagSendgridApiKey string
|
||||
flagEmailFrom string
|
||||
flagEmailFromName = "WireGuard Manager"
|
||||
// IMPORTANT: If no SESSION_SECRET is provided via environment or file,
|
||||
// a random secret is generated which will change on every restart.
|
||||
// For production, be sure to supply a fixed value.
|
||||
flagSessionSecret = util.RandomString(32)
|
||||
// IMPORTANT: Instead of generating a new random secret on each run,
|
||||
// we now persist the secret in our JSON DB if no SESSION_SECRET is provided.
|
||||
flagSessionSecret = util.GetPersistedSessionSecret()
|
||||
flagSessionMaxDuration = 90
|
||||
flagWgConfTemplate string
|
||||
flagBasePath string
|
||||
@ -108,6 +107,7 @@ func init() {
|
||||
flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrFile("SENDGRID_API_KEY_FILE", flagSendgridApiKey), "File containing your sendgrid api key.")
|
||||
}
|
||||
|
||||
// Use the persisted session secret as default.
|
||||
if sessionSecretLookup != "" {
|
||||
flag.StringVar(&flagSessionSecret, "session-secret", sessionSecretLookup, "The key used to encrypt session cookies.")
|
||||
} else {
|
||||
@ -131,7 +131,7 @@ func init() {
|
||||
util.SendgridApiKey = flagSendgridApiKey
|
||||
util.EmailFrom = flagEmailFrom
|
||||
util.EmailFromName = flagEmailFromName
|
||||
// Use a stable session secret if provided; otherwise a new random value is generated each run.
|
||||
// Use a stable session secret.
|
||||
util.SessionSecret = sha512.Sum512([]byte(flagSessionSecret))
|
||||
// DEBUG: Log the session secret hash for verification (remove in production)
|
||||
log.Debugf("Using session secret (SHA512 hash): %x", util.SessionSecret)
|
||||
|
BIN
screenshots/WireGuardManager.jpg
Normal file
BIN
screenshots/WireGuardManager.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 MiB |
38
util/util.go
38
util/util.go
@ -735,3 +735,41 @@ func filterEmpty(strs []string) []string {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// GetPersistedSessionSecret retrieves a stable session secret from the JSON DB.
|
||||
// It first checks if the SESSION_SECRET environment variable is set. If not,
|
||||
// it attempts to read the secret from the "config" collection (key "session_secret")
|
||||
// in the JSON DB (located in "./db"). If no secret is stored, it generates a new one,
|
||||
// saves it to the JSON DB, and returns it.
|
||||
func GetPersistedSessionSecret() string {
|
||||
// First, check if the environment variable is set.
|
||||
if secret := LookupEnvOrString("SESSION_SECRET", ""); secret != "" {
|
||||
// Trim any accidental whitespace.
|
||||
return strings.TrimSpace(secret)
|
||||
}
|
||||
|
||||
// Open the Scribble DB at "./db".
|
||||
db, err := scribble.New("./db", nil)
|
||||
if err != nil {
|
||||
log.Errorf("Error opening json db for session secret: %v", err)
|
||||
// Fallback: generate a random secret.
|
||||
return RandomString(32)
|
||||
}
|
||||
|
||||
// Attempt to read the session secret from the "config" collection with key "session_secret".
|
||||
var storedSecret string
|
||||
err = db.Read("config", "session_secret", &storedSecret)
|
||||
if err == nil && strings.TrimSpace(storedSecret) != "" {
|
||||
return strings.TrimSpace(storedSecret)
|
||||
}
|
||||
|
||||
// No valid secret was found, so generate a new one.
|
||||
newSecret := RandomString(32)
|
||||
// Save the new secret in the JSON DB.
|
||||
err = db.Write("config", "session_secret", newSecret)
|
||||
if err != nil {
|
||||
log.Errorf("Error saving session secret to json db: %v", err)
|
||||
// Even if saving fails, return the generated secret.
|
||||
}
|
||||
return newSecret
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user