UI improvement
This commit is contained in:
parent
575edc836d
commit
9a272ee959
16 changed files with 2477 additions and 1604 deletions
|
|
@ -48,19 +48,19 @@ The suite is organized into three independent but complementary scripts, each ma
|
|||
- Manages a `.radius-secret` shared secret file (generated automatically on first `--apply` if RADIUS is enabled)
|
||||
- Configures `avahi-daemon` as an mDNS reflector to forward service discovery announcements (AirPrint, AirPlay, Chromecast, etc.) across VLANs
|
||||
|
||||
### Optional: VPN (`vpn.py`)
|
||||
### Optional: WireGuard VPN (managed by `core.py` and the dashboard)
|
||||
|
||||
- Supports any number of WireGuard interfaces defined in `core.json` (any VLAN with an interface name starting with `wg`)
|
||||
- Allocates IP addresses to remote peers automatically from the VPN VLAN subnet
|
||||
- Generates per-peer client config files ready for import into any WireGuard client, with per-peer choice of split tunnel or full tunnel routing
|
||||
- Resolves the server's public endpoint from the DDNS config or manual entry
|
||||
- Stores peer data in per-interface dotfiles (`.vpn-wg0`, etc.) alongside the scripts
|
||||
- Reports per-peer handshake times and RX/TX byte counts
|
||||
- `core.py --apply` generates the server keypair on first run, writes the server conf to `/etc/wireguard/`, and brings the interface up with `wg-quick`. Subsequent applies sync peer changes live without restarting the interface
|
||||
- Peer management is done through the router dashboard: add a peer, set its IP and tunnel mode, and the dashboard generates and downloads the ready-to-import client `.conf` file immediately — the private key is never stored
|
||||
- Peer data (name, IP, public key, enabled state) is stored directly in `core.json` alongside the rest of the network config
|
||||
- Supports per-peer choice of split-tunnel (VPN subnet only) or full-tunnel (all traffic) routing
|
||||
- Reports active peer connections, handshake times, and RX/TX byte counts on the dashboard VPN view
|
||||
|
||||
### Optional: DDNS (`ddns.py`)
|
||||
|
||||
- Detects the current public IP by rotating through multiple IP-check services
|
||||
- Updates the specified DNS providers (currently supporting No-IP and DuckDNS), supporting multiple hostnames and subdomains per provider
|
||||
- Updates the specified DNS providers (currently supporting Cloudflare, No-IP and DuckDNS), supporting multiple hostnames and subdomains per provider
|
||||
- Caches the last known IP per provider to avoid unnecessary API calls
|
||||
- Installs a `systemd` timer that runs every 5 minutes by default
|
||||
- Logs all updates and errors to `ddns.log`
|
||||
|
|
@ -80,7 +80,7 @@ These packages are required. `core.py --install` checks that they are installed
|
|||
| `chrony` | NTP server - synchronizes system clock and serves time to VLAN clients | `core.py` |
|
||||
| `freeradius` | RADIUS server for dynamic VLAN assignment via MAC auth | `core.py` |
|
||||
| `avahi-daemon` | mDNS reflector for cross-VLAN service discovery | `core.py` |
|
||||
| `wireguard-tools` | WireGuard VPN (`wg`, `wg-quick`) | `vpn.py` |
|
||||
| `wireguard-tools` | WireGuard VPN (`wg`, `wg-quick`) | `core.py` (when WireGuard VLANs are configured) |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ All configuration lives in two JSON files. Edit these to match your network befo
|
|||
|
||||
| File | Controls |
|
||||
|---|---|
|
||||
| `core.json` | VLANs, subnets, gateways, dynamic pools, static/dynamic reservations, RADIUS client flags, mDNS reflection scope, WireGuard interface and listen port, upstream DNS servers, blocklist sources, per-VLAN blocklist assignments, host overrides, banned IPs, WAN interface, port forwarding rules, port wrangling, inter-VLAN exceptions |
|
||||
| `core.json` | VLANs, subnets, gateways, dynamic pools, static/dynamic reservations, RADIUS client flags, mDNS reflection scope, WireGuard interface settings and peers, upstream DNS servers, blocklist sources, per-VLAN blocklist assignments, host overrides, banned IPs, WAN interface, port forwarding rules, port wrangling, inter-VLAN exceptions |
|
||||
| `ddns.json` | DDNS provider credentials, hostnames/subdomains, update interval, IP-check services |
|
||||
|
||||
### Dotfiles (auto-generated, do not edit)
|
||||
|
|
@ -116,7 +116,7 @@ All configuration lives in two JSON files. Edit these to match your network befo
|
|||
| File | Purpose |
|
||||
|---|---|
|
||||
| `.radius-secret` | Shared secret between FreeRADIUS and RADIUS clients (APs, switches). Generated automatically on first `--apply` when RADIUS is enabled. Root-owned intentionally. |
|
||||
| `.vpn-wg0` (etc.) | WireGuard peer data per interface. Managed by `vpn.py`. |
|
||||
| `.wg-<iface>.pub` | WireGuard server public key per interface (e.g. `.wg-wg0.pub`). Written by `core.py --apply`; read by the dashboard to embed in client config downloads. |
|
||||
| `.ddns-last-ip-*` | Cached public IP per DDNS provider. Managed by `ddns.py`. |
|
||||
| `.ddns-last-service` | Tracks IP-check service rotation. Managed by `ddns.py`. |
|
||||
|
||||
|
|
@ -144,33 +144,41 @@ Edit the `vlans` array to match your network topology. For each VLAN:
|
|||
- Set `interface` to the NIC name for VLAN 1 (e.g. `enp6s0`); sub-interfaces are named automatically (e.g. `enp6s0.10`). For WireGuard VLANs, use `wg0`, `wg1`, etc.
|
||||
- Set `radius_default` to `true` on exactly one VLAN - unknown MACs will be placed here (typically guest). All other VLANs set this to `false`.
|
||||
- Set `use_blocklists` to a list of blocklist names for this VLAN - leave empty for unfiltered DNS
|
||||
- Set `server_identities` to the IPs the router itself will hold on this VLAN. The lowest last-octet IP is auto-used as gateway, DNS, and NTP server unless overridden in `dhcp.explicit_overrides`.
|
||||
- Set `dhcp` fields: `subnet`, `subnet_mask`, pool start/end, `lease_time`, and optionally `explicit_overrides` for gateway, dns_server, or ntp_server
|
||||
- Set `server_identities` to the IPs the router itself will hold on this VLAN. The lowest last-octet IP is auto-used as gateway, DNS, and NTP server unless overridden in `dhcp_information.explicit_overrides`.
|
||||
- Set `subnet` and `subnet_mask` at the top level of the VLAN object
|
||||
- Set `dhcp_information` fields: pool start/end, `lease_time`, and optionally `explicit_overrides` for gateway, dns_server, or ntp_server
|
||||
- Add `reservations` for devices that need a known VLAN assignment by MAC address. The `ip` field is optional:
|
||||
- Omit `ip`, set it to `""`, or set it to `"dynamic"` to let DHCP assign from the pool (hostname is still set)
|
||||
- Set `ip` to a specific address outside the dynamic pool to pin the device to that IP
|
||||
- Set `radius_client: true` on any device (AP, switch) that will authenticate other devices via RADIUS
|
||||
- Add per-VLAN `port_wrangling` entries to redirect DNS or NTP requests to the local resolver
|
||||
- For WireGuard VLANs, include a `vpn_information` block instead of `dhcp` and `server_identities`:
|
||||
- For WireGuard VLANs, include a `vpn_information` block instead of `dhcp_information` and `server_identities`, and a `peers` array instead of `reservations`. Peer management (add, edit, regenerate conf, delete) is done through the dashboard:
|
||||
|
||||
```json
|
||||
{
|
||||
"vlan_id": 40,
|
||||
"name": "vpn",
|
||||
"interface": "wg0",
|
||||
"subnet": "192.168.40.0",
|
||||
"subnet_mask": "255.255.255.0",
|
||||
"radius_default": false,
|
||||
"use_blocklists": ["oisd-big"],
|
||||
"server_identities": [
|
||||
{ "description": "Router/Gateway", "ip": "192.168.40.1" }
|
||||
],
|
||||
"vpn_information": {
|
||||
"listen_port": 51820,
|
||||
"gateway": "192.168.40.1",
|
||||
"server_endpoint": "vpn.example.com",
|
||||
"domain": "local",
|
||||
"explicit_overrides": { "dns_server": "", "mtu": "" }
|
||||
"explicit_overrides": { "gateway": "", "dns_server": "", "mtu": "" }
|
||||
},
|
||||
"reservations": [],
|
||||
"peers": [],
|
||||
"port_wrangling": [...]
|
||||
}
|
||||
```
|
||||
|
||||
The gateway IP is derived from the `server_identities` entry with the lowest value in the last octet (same rule as non-WG VLANs). If `explicit_overrides.gateway` is set, it must match one of the `server_identities` IPs.
|
||||
|
||||
### Banned IPs
|
||||
|
||||
The top-level `banned_ips` array blocks inbound and outbound traffic to/from specific IPs or networks at the firewall level. This is useful for blocking known malicious hosts, entire ASNs, or geographic ranges. Entries support a flexible address syntax:
|
||||
|
|
@ -272,15 +280,26 @@ Optional (if DDNS is desired):
|
|||
sudo python3 ddns.py --start # Run an immediate IP update and install the update timer
|
||||
```
|
||||
|
||||
Optional (if VPN is desired):
|
||||
Optional (if WireGuard VPN is desired):
|
||||
|
||||
1. Add a WireGuard VLAN to `core.json` with `interface: "wg0"` (see configuration example above)
|
||||
2. Run `sudo python3 core.py --apply` — this generates the server keypair, writes `/etc/wireguard/wg0.conf`, and brings the interface up
|
||||
3. Add peers using one of the two methods below, then run `sudo python3 core.py --apply` again to sync them to the live interface
|
||||
|
||||
**With the router dashboard:**
|
||||
Open the VPN view, fill in the Server Endpoint (your public hostname or IP), and add peers — each peer triggers an immediate `.conf` file download ready to import into any WireGuard client.
|
||||
|
||||
**Without the dashboard (`create_vpn_peer.py`):**
|
||||
|
||||
```bash
|
||||
sudo python3 vpn.py --add-peer # Add a VPN peer interactively
|
||||
sudo python3 vpn.py --apply # Write WireGuard config and start the interface
|
||||
sudo python3 core.py --apply # Run again after VPN to start dnsmasq for the VPN VLAN(s)
|
||||
python3 create_vpn_peer.py --name laptop --ip 192.168.40.2
|
||||
python3 create_vpn_peer.py --name laptop --ip 192.168.40.2 --iface wg0
|
||||
python3 create_vpn_peer.py --name laptop --ip 192.168.40.2 --vlan-id 40
|
||||
python3 create_vpn_peer.py --name phone --ip 192.168.40.3 --split-tunnel
|
||||
python3 create_vpn_peer.py --name tablet --ip 192.168.40.4 --output ~/tablet.conf
|
||||
```
|
||||
|
||||
After adding VPN peers, transfer `vpn-client-<n>.conf` to the peer device by secure means, then delete it from this server.
|
||||
The script reads the specified WireGuard VLAN from `core.json`, validates the IP against the VLAN subnet, generates a keypair, appends the peer to `core.json`, and writes the client `.conf` file. If the config has exactly one WireGuard VLAN, `--iface` and `--vlan-id` are optional. Transfer the `.conf` to the peer device by secure means, then delete it from the server.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -309,19 +328,23 @@ python3 core.py --view-rules # Active nftables ruleset
|
|||
python3 core.py --view-metrics # Lifetime DNS metrics across all VLAN instances
|
||||
```
|
||||
|
||||
### vpn.py
|
||||
### create_vpn_peer.py
|
||||
|
||||
All `vpn.py` commands require `sudo`.
|
||||
Does not require `sudo`. Requires `wireguard-tools` (`wg` must be on PATH) and a prior `core.py --apply` to generate the server keypair.
|
||||
|
||||
```
|
||||
sudo python3 vpn.py --add-peer # Add a VPN peer interactively
|
||||
sudo python3 vpn.py --manage-peers # Rename, regenerate keys, or delete a peer
|
||||
sudo python3 vpn.py --apply # Write WireGuard config and start/restart the interface
|
||||
sudo python3 vpn.py --disable # Stop WireGuard on all interfaces
|
||||
sudo python3 vpn.py --status # WireGuard service and interface status
|
||||
sudo python3 vpn.py --view-peers # Per-peer handshake times and traffic stats
|
||||
python3 create_vpn_peer.py --name NAME --ip IP [--iface IFACE | --vlan-id ID] [--split-tunnel] [--output FILE]
|
||||
|
||||
--name NAME Peer name (e.g. laptop)
|
||||
--ip IP Peer IP within the VPN subnet (e.g. 192.168.40.2)
|
||||
--iface IFACE WireGuard interface to add the peer to (e.g. wg0)
|
||||
--vlan-id ID VLAN ID of the WireGuard VLAN (e.g. 40); alternative to --iface
|
||||
--split-tunnel Route only VPN subnet traffic through the tunnel (default: full tunnel)
|
||||
--output FILE Output path for the client .conf file (default: vpn-client-<name>.conf)
|
||||
```
|
||||
|
||||
`--iface` and `--vlan-id` are mutually exclusive. Both are optional when the config contains exactly one WireGuard VLAN.
|
||||
|
||||
### ddns.py
|
||||
|
||||
Only `--start` and `--disable` require `sudo` as they install/remove systemd timer files. All other commands run as a normal user.
|
||||
|
|
@ -342,6 +365,7 @@ python3 ddns.py --getip # Print current public IP and exit
|
|||
|
||||
```bash
|
||||
sudo python3 core.py --disable # Revert to network client (interactive wizard)
|
||||
sudo python3 vpn.py --disable # Stop WireGuard on all interfaces
|
||||
sudo python3 ddns.py --disable # Stop and remove DDNS timer
|
||||
```
|
||||
|
||||
WireGuard interfaces are brought down automatically by `core.py --disable`. To stop a WireGuard interface independently: `sudo wg-quick down wg0`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue