https://github.com/linakis/luci-app-mullvad
A LuCI web application for OpenWrt that provides a user-friendly interface to manage Mullvad WireGuard VPN server selection and monitor connection status.
https://github.com/linakis/luci-app-mullvad
Last synced: 5 months ago
JSON representation
A LuCI web application for OpenWrt that provides a user-friendly interface to manage Mullvad WireGuard VPN server selection and monitor connection status.
- Host: GitHub
- URL: https://github.com/linakis/luci-app-mullvad
- Owner: linakis
- Created: 2025-12-20T06:43:05.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-11T10:12:52.000Z (5 months ago)
- Last Synced: 2026-01-11T14:25:15.081Z (5 months ago)
- Language: JavaScript
- Size: 444 KB
- Stars: 0
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# LuCI Mullvad WireGuard Manager
A LuCI web application for OpenWrt that provides a user-friendly interface to manage Mullvad WireGuard VPN server selection and monitor connection status.

## 📦 Installation
### Download Pre-built Package
**[Download the latest release](https://github.com/linakis/luci-app-mullvad/releases/latest)** - Ready-to-install IPK package for all OpenWrt routers.
### Quick Installation
Install dependencies and the package on your router:
```bash
# Install dependencies
opkg update
opkg install luci-base luci-proto-wireguard wireguard-tools curl jsonfilter
# Download and install the package
cd /tmp
wget https://github.com/linakis/luci-app-mullvad/releases/latest/download/luci-app-mullvad_1.0.0_all.ipk
opkg install luci-app-mullvad_1.0.0_all.ipk
# Restart services
/etc/init.d/rpcd restart && /etc/init.d/uhttpd restart
```
Then access the application at **Services → Mullvad WireGuard** in your router's LuCI interface.
## Features
- **Server Selection**: Browse and select from all available Mullvad WireGuard servers
- **Connection Status**: Real-time display of connection status, handshake time, and transfer statistics
- **Server List Caching**: Optional local caching with configurable TTL to reduce API calls
- **Manual Refresh**: Update server list on-demand from Mullvad's API
- **Safe Configuration**: Changes are staged and require explicit confirmation before applying
- **Status Monitoring**: Shows current endpoint, last handshake, and data transfer metrics
- **Auto-Detection**: Automatically detects your WireGuard interface name on first run
## Prerequisites
### Required Packages
- `luci-base`
- `luci-proto-wireguard`
- `wireguard-tools`
- `curl`
- `jsonfilter`
### Existing WireGuard Configuration
This app assumes you already have a working Mullvad WireGuard configuration in `/etc/config/network` with:
- A WireGuard interface (the app will auto-detect it, or defaults to `MullvadWG`)
- An associated peer section
- Your Mullvad account's private key configured
The app will update the peer's public key and endpoint when switching servers.
### Setting Up Mullvad WireGuard (If Not Already Configured)
If you haven't set up Mullvad WireGuard on OpenWrt yet, follow the official guides:
**Official Mullvad Guides:**
- [WireGuard on a Router](https://mullvad.net/en/help/running-wireguard-router/) - Complete WireGuard setup for routers including OpenWrt
- [OpenWrt Routers and Mullvad VPN](https://mullvad.net/en/help/openwrt-routers-and-mullvad-vpn) - General OpenWrt guide (OpenVPN-focused but has useful background)
**Quick Setup Summary:**
1. Install packages: `luci-proto-wireguard`, `wireguard-tools`
2. Generate WireGuard keys: `wg genkey | tee privatekey | wg pubkey > publickey`
3. Get your Mullvad IP address from the API with your account number and public key
4. Configure the WireGuard interface in LuCI (Network → Interfaces)
5. Install this app to easily manage server selection
## Advanced Installation
### Manual Installation (Development/Testing)
This method works without downloading packages. All files are scripts and configs that work as-is.
1. **Copy files to your router**:
```bash
scp -r luci-app-mullvad root@:/root/
```
2. **SSH into your router**:
```bash
ssh root@
```
3. **Install the application** (on the router):
```bash
cd /root/luci-app-mullvad
cp -r root/* /
cp -r htdocs/* /www/
# Make scripts executable
chmod +x /usr/bin/mullvad-fetch-servers.sh
chmod +x /usr/bin/mullvad-apply-server.sh
chmod +x /usr/bin/mullvad-get-status.sh
# Fix file permissions
chmod 644 /usr/share/rpcd/acl.d/luci-app-mullvad.json
chmod 644 /usr/share/luci/menu.d/luci-app-mullvad.json
chmod 644 /etc/config/mullvad
chmod 644 /www/luci-static/resources/view/mullvad/manager.js
# Fix directory permissions
chmod 755 /www/luci-static/resources/view/mullvad
```
4. **Initialize configuration** (on the router):
```bash
uci commit mullvad
```
5. **Restart services** (on the router):
```bash
/etc/init.d/rpcd restart
/etc/init.d/uhttpd restart
```
6. **Verify installation** (optional):
```bash
# Check that scripts are executable
ls -la /usr/bin/mullvad-*.sh
# Check that all files have correct permissions
ls -la /usr/share/rpcd/acl.d/luci-app-mullvad.json
ls -la /usr/share/luci/menu.d/luci-app-mullvad.json
ls -la /etc/config/mullvad
ls -la /www/luci-static/resources/view/mullvad/manager.js
# Test the fetch script
/usr/bin/mullvad-fetch-servers.sh
```
7. **Access the application**:
- Navigate to your router's LuCI interface (e.g., http://10.0.0.1)
- Go to **Services → Mullvad WireGuard**
## Usage
### Accessing the Interface
1. Open your router's LuCI web interface
2. Navigate to **Services → Mullvad WireGuard**
### Switching Servers
1. **View Current Status**: The status section shows your current connection state
2. **Refresh Server List** (optional): Click "Refresh Server List" to get the latest servers from Mullvad
3. **Select Server**: Choose a server from the dropdown list
- Servers are displayed in the format: **Country - City - Hostname (Provider)**
- The list is sorted alphabetically by country, then city, then hostname
- Mullvad-owned servers are labeled as "(Mullvad Owned)"
4. **Apply Server**: Click "Apply Selected Server" to switch to the new server
5. **Confirm Change**: A confirmation dialog will show the server details before applying
6. **Verify Connection**: Status will update within 30 seconds showing the new server
### Configuration Options
#### Cache Settings
- **Enable Caching**: Store server list locally to reduce API calls
- **Cache TTL**: Set how long cached data remains valid (default: 24 hours)
- **WireGuard Interface**: Specify which interface to manage (auto-detected, or defaults to `MullvadWG`)
## Configuration for Different Interface Names
The app automatically detects your WireGuard interface on first run. However, if you need to manually configure it:
### Auto-Detection (Recommended)
The app will automatically detect your WireGuard interface by:
1. Looking for interfaces with `proto=wireguard` in `/etc/config/network`
2. Checking for an associated peer section following the pattern `wireguard_`
3. Saving the detected interface name to `/etc/config/mullvad` for future use
No manual configuration needed in most cases!
### Manual Configuration
If auto-detection doesn't work or you want to specify a different interface:
1. **Check your current WireGuard interface name:**
```bash
wg show # Shows all WireGuard interfaces
uci show network | grep "proto='wireguard'" # Shows UCI config
```
2. **Set the interface name manually:**
```bash
uci set mullvad.config.wireguard_interface='YOUR_INTERFACE_NAME'
uci commit mullvad
```
3. **Restart LuCI:**
```bash
/etc/init.d/uhttpd restart
```
### Examples
For an interface named `wg0`:
```bash
uci set mullvad.config.wireguard_interface='wg0'
uci commit mullvad
```
For the Mullvad guide's recommended name `WGINTERFACE`:
```bash
uci set mullvad.config.wireguard_interface='WGINTERFACE'
uci commit mullvad
```
## Backend Scripts
### mullvad-fetch-servers.sh
Fetches the server list from Mullvad's API (`https://api.mullvad.net/app/v1/relays`) and caches it locally.
**Usage**:
```bash
/usr/bin/mullvad-fetch-servers.sh
```
**Output**: `/tmp/mullvad_servers.json`
### mullvad-apply-server.sh
Updates the WireGuard peer configuration with a new server's details.
**Usage**:
```bash
/usr/bin/mullvad-apply-server.sh
```
**Example**:
```bash
/usr/bin/mullvad-apply-server.sh gr-ath-wg-102 "server_public_key" "185.213.154.68" "51820"
```
### mullvad-get-status.sh
Retrieves current WireGuard connection status and formats it as JSON.
**Usage**:
```bash
/usr/bin/mullvad-get-status.sh
```
**Output**: JSON with connection status, endpoint, handshake time, and transfer statistics
## Configuration
### UCI Configuration File: `/etc/config/mullvad`
```
config settings 'config'
option cache_enabled '1' # Enable/disable caching
option cache_ttl '86400' # Cache TTL in seconds (24 hours)
option auto_refresh_enabled '0' # Reserved for future use
option wireguard_interface 'MullvadWG' # WireGuard interface name
option last_fetch '0' # Timestamp of last API fetch
config cache 'servers'
option data '' # Cached server list (JSON)
option timestamp '0' # Cache timestamp
```
### Network Configuration Changes
When you switch servers, the app updates `/etc/config/network`:
**Before**:
```
config wireguard_MullvadWG
option description 'se-sto-wg-101'
option public_key 'old_server_public_key'
option endpoint_host '185.65.134.66'
option endpoint_port '51820'
```
**After**:
```
config wireguard_MullvadWG
option description 'gr-ath-wg-102'
option public_key 'new_server_public_key'
option endpoint_host '185.213.154.68'
option endpoint_port '51820'
```
## Troubleshooting
### Server list won't load
1. Check internet connectivity: `ping api.mullvad.net`
2. Verify curl is installed: `opkg list-installed | grep curl`
3. Manually test API: `/usr/bin/mullvad-fetch-servers.sh`
4. Check logs: `logread | grep mullvad`
### Changes don't apply
1. Verify scripts are executable: `ls -l /usr/bin/mullvad-*.sh`
2. Check UCI permissions: `uci show mullvad`
3. Verify network configuration: `uci show network | grep -A5 MullvadWG`
4. Check WireGuard status: `wg show MullvadWG`
### Connection shows as disconnected
1. Verify WireGuard interface is up: `ifstatus MullvadWG`
2. Check recent handshake: `wg show MullvadWG latest-handshakes`
3. Test network connectivity: `ping -I MullvadWG 1.1.1.1`
4. Verify firewall rules allow WireGuard traffic
### LuCI menu doesn't show the app
1. Restart LuCI: `/etc/init.d/uhttpd restart`
2. Clear browser cache
3. Verify menu file exists: `ls /usr/share/luci/menu.d/luci-app-mullvad.json`
4. Check ACL permissions: `cat /usr/share/rpcd/acl.d/luci-app-mullvad.json`
### Permission denied errors
1. Ensure scripts are executable: `chmod +x /usr/bin/mullvad-*.sh`
2. Verify ACL file is present and valid
3. Check rpcd is running: `/etc/init.d/rpcd status`
4. Restart rpcd: `/etc/init.d/rpcd restart`
## Security Considerations
- **Private Key Protection**: Your Mullvad private key is never exposed or modified by this app
- **ACL Restrictions**: The app uses minimal permissions (UCI access for network/mullvad configs only)
- **Input Validation**: All scripts validate inputs to prevent command injection
- **HTTPS Only**: Always access LuCI over HTTPS in production environments
- **API Security**: Server list is fetched over HTTPS from Mullvad's official API
## Technical Details
### Interface Auto-Detection
On first run or when not configured, the app automatically detects your WireGuard interface:
1. **Searches for WireGuard interfaces** with `proto=wireguard` in `/etc/config/network`
2. **Validates the interface** by checking for an associated peer section (`wireguard_`)
3. **Saves the detected name** to `/etc/config/mullvad` for future use
4. **Falls back to `MullvadWG`** if auto-detection fails
This ensures compatibility with any WireGuard interface name, whether you followed Mullvad's official guide (using `WGINTERFACE`) or chose your own naming convention.
### How Server Switching Works
1. User selects a server in the UI
2. JavaScript calls backend script with server details
3. `mullvad-apply-server.sh` updates UCI network configuration
4. Script commits changes but doesn't reload network immediately
5. LuCI's save/apply mechanism triggers network reload
6. WireGuard interface reconnects to the new server
7. Status display updates with new endpoint information
### Connection Status Detection
Connection is considered active when:
- WireGuard interface is up
- Peer endpoint is configured
- Last handshake occurred within 3 minutes
### Data Flow
```
Mullvad API → fetch script → /tmp/cache → UCI config → JavaScript UI
↓
User Selection → apply script → UCI network config → network reload
↑
Auto-detect interface (first run)
```
## API Reference
### Mullvad API Endpoint
```
GET https://api.mullvad.net/app/v1/relays
```
Returns a list of all Mullvad relay servers including WireGuard configurations.
## Contributing
When modifying this application:
1. Test all changes on a development router first
2. Verify ACL permissions are minimal and appropriate
3. Ensure backward compatibility with existing configurations
4. Update this README with any new features or changes
## License
This is a custom application for managing Mullvad WireGuard configurations on OpenWrt routers.
## Version History
- **1.0.0** - Initial release
- Server selection and switching
- Connection status monitoring
- Country/city filtering
- Server list caching
- Manual refresh capability