Skip to content

Commit

Permalink
Merge branch 'wg-easy:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Dartegnian authored Jun 19, 2024
2 parents 4a15ea0 + e0775c0 commit 3a7b372
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 9 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ To automatically install & run wg-easy, simply run:
--name=wg-easy-m3 \
-e LANG=de \
-e WG_HOST=<🚨YOUR_SERVER_IP> \
-e PASSWORD=<🚨YOUR_ADMIN_PASSWORD> \
-e PASSWORD_HASH=<🚨YOUR_ADMIN_PASSWORD_HASH> \
-e PORT=51821 \
-e WG_PORT=51820 \
-v ~/.wg-easy:/etc/wireguard \
Expand All @@ -84,7 +84,7 @@ To automatically install & run wg-easy, simply run:

> 💡 Replace `YOUR_SERVER_IP` with your WAN IP, or a Dynamic DNS hostname.
>
> 💡 Replace `YOUR_ADMIN_PASSWORD` with a password to log in on the Web UI.
> 💡 Replace `YOUR_ADMIN_PASSWORD_HASH` with a bcrypt password hash to log in on the Web UI.
The Web UI will now be available on `http://0.0.0.0:51821`.

Expand All @@ -106,7 +106,8 @@ These options can be configured by setting environment variables using `-e KEY="
| - | - | - | - |
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
| `WEBUI_HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
| `PASSWORD` | - | `foobar123` | When set, requires a password when logging in to the Web UI. |
| `PASSWORD_HASH` | - | `$2y$05$Ci...` | When set, requires a password when logging in to the Web UI. |
| `PASSWORD` (deprecated) | - | `foobar123` | When set, requires a password when logging in to the Web UI. *(Not used if `PASSWORD_HASH` is set)* |
| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
Expand Down
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports.RELEASE = release;
module.exports.PORT = process.env.PORT || '51821';
module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0';
module.exports.PASSWORD = process.env.PASSWORD;
module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH;
module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
module.exports.WG_DEVICE = process.env.WG_DEVICE || 'eth0';
module.exports.WG_HOST = process.env.WG_HOST;
Expand Down
42 changes: 36 additions & 6 deletions src/lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,40 @@ const {
WEBUI_HOST,
RELEASE,
PASSWORD,
PASSWORD_HASH,
LANG,
UI_TRAFFIC_STATS,
UI_CHART_TYPE,
} = require('../config');

const requiresPassword = !!PASSWORD || !!PASSWORD_HASH;

/**
* Checks if `password` matches the PASSWORD_HASH.
*
* For backward compatibility it also allows `password` to match the clear text PASSWORD,
* but only if no PASSWORD_HASH is provided.
*
* If both enviornment variables are not set, the password is always invalid.
*
* @param {string} password String to test
* @returns {boolean} true if matching environment, otherwise false
*/
const isPasswordValid = (password) => {
if (typeof password !== 'string') {
return false;
}

if (PASSWORD_HASH) {
return bcrypt.compareSync(password, PASSWORD_HASH);
}
if (PASSWORD) {
return password === PASSWORD;
}

return false;
};

module.exports = class Server {

constructor() {
Expand Down Expand Up @@ -72,7 +101,6 @@ module.exports = class Server {

// Authentication
.get('/api/session', defineEventHandler((event) => {
const requiresPassword = !!process.env.PASSWORD;
const authenticated = requiresPassword
? !!(event.node.req.session && event.node.req.session.authenticated)
: true;
Expand All @@ -85,14 +113,16 @@ module.exports = class Server {
.post('/api/session', defineEventHandler(async (event) => {
const { password } = await readBody(event);

if (typeof password !== 'string') {
if (!requiresPassword) {
// if no password is required, the API should never be called.
// Do not automatically authenticate the user.
throw createError({
status: 401,
message: 'Missing: Password',
message: 'Invalid state',
});
}

if (password !== PASSWORD) {
if (!isPasswordValid(password)) {
throw createError({
status: 401,
message: 'Incorrect Password',
Expand All @@ -110,7 +140,7 @@ module.exports = class Server {
// WireGuard
app.use(
fromNodeMiddleware((req, res, next) => {
if (!PASSWORD || !req.url.startsWith('/api/')) {
if (!requiresPassword || !req.url.startsWith('/api/')) {
return next();
}

Expand All @@ -119,7 +149,7 @@ module.exports = class Server {
}

if (req.url.startsWith('/api/') && req.headers['authorization']) {
if (bcrypt.compareSync(req.headers['authorization'], bcrypt.hashSync(PASSWORD, 10))) {
if (isPasswordValid(req.headers['authorization'])) {
return next();
}
return res.status(401).json({
Expand Down

0 comments on commit 3a7b372

Please sign in to comment.