Upload files to "/"
Re-uploaded Failed Files
This commit is contained in:
@@ -1,119 +1,177 @@
|
|||||||
ha-parental-controls
|
# ha-parental-controls
|
||||||
|
|
||||||
A Home Assistant dashboard for per-user, per-device internet blocking via OPNsense firewall alias management. Assign devices to users by MAC address, block/unblock individually or per-user, and optionally enforce scheduled access windows.
|
A Home Assistant dashboard for per-user, per-device internet blocking via OPNsense firewall alias management. Assign devices to users by MAC address, block/unblock individually or per-user, and optionally enforce scheduled access windows.
|
||||||
|
|
||||||
How it works
|
---
|
||||||
|
|
||||||
OPNsense maintains a firewall alias called parental_blocked
|
## How it works
|
||||||
A LAN rule blocks all traffic from IPs in that alias
|
|
||||||
The HA dashboard looks up each device's current IP from device_tracker entities (provided by the OPNsense integration), then adds/removes IPs from the alias via OPNsense API
|
|
||||||
|
|
||||||
Because devices are identified by MAC address, blocks re-apply automatically when a device reconnects with a new IP (handled by a state change listener in the dashboard).
|
1. OPNsense maintains a firewall alias called `parental_blocked`
|
||||||
|
2. A LAN rule blocks all traffic from IPs in that alias
|
||||||
|
3. The HA dashboard looks up each device's current IP from `device_tracker` entities (provided by the OPNsense integration), then adds/removes IPs from the alias via OPNsense API
|
||||||
|
|
||||||
|
Because devices are identified by **MAC address**, blocks re-apply automatically when a device reconnects with a new IP (handled by a state change listener in the dashboard).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — OPNsense setup
|
||||||
|
|
||||||
|
### 1.1 Create the firewall alias
|
||||||
|
|
||||||
Step 1 — OPNsense setup
|
|
||||||
1.1 Create the firewall alias
|
|
||||||
Firewall → Aliases → +
|
Firewall → Aliases → +
|
||||||
FieldValueNameparental_blockedTypeHost(s)DescriptionParental Controls — blocked devicesContent(leave empty — managed via API)
|
|
||||||
Save, then Apply.
|
|
||||||
1.2 Create the blocking rule
|
|
||||||
Firewall → Rules → LAN → +
|
|
||||||
FieldValueActionBlockInterfaceLANDirectioninProtocolanySourceSingle host or alias → parental_blockedDestinationanyDescriptionParental Controls — block internet
|
|
||||||
Position this rule above your default allow-all LAN rule. Save and Apply.
|
|
||||||
1.3 Create an API key
|
|
||||||
System → Access → Users → (your admin user or a dedicated user) → API Keys → +
|
|
||||||
Permissions needed: Firewall: Alias (read + write)
|
|
||||||
Note the Key and Secret — you'll need them for secrets.yaml.
|
|
||||||
|
|
||||||
Step 2 — Home Assistant setup
|
| Field | Value |
|
||||||
2.1 Add secrets to /config/secrets.yaml
|
|---|---|
|
||||||
|
| Name | `parental_blocked` |
|
||||||
|
| Type | `Host(s)` |
|
||||||
|
| Description | `Parental Controls — blocked devices` |
|
||||||
|
| Content | *(leave empty — managed via API)* |
|
||||||
|
|
||||||
|
Save, then **Apply**.
|
||||||
|
|
||||||
|
### 1.2 Create the blocking rule
|
||||||
|
|
||||||
|
Firewall → Rules → LAN → +
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|---|---|
|
||||||
|
| Action | **Block** |
|
||||||
|
| Interface | LAN |
|
||||||
|
| Direction | in |
|
||||||
|
| Protocol | any |
|
||||||
|
| Source | Single host or alias → `parental_blocked` |
|
||||||
|
| Destination | any |
|
||||||
|
| Description | `Parental Controls — block internet` |
|
||||||
|
|
||||||
|
Position this rule **above** your default allow-all LAN rule. Save and Apply.
|
||||||
|
|
||||||
|
### 1.3 Create an API key
|
||||||
|
|
||||||
|
System → Access → Users → (your admin user or a dedicated user) → API Keys → +
|
||||||
|
|
||||||
|
Permissions needed: **Firewall: Alias** (read + write)
|
||||||
|
|
||||||
|
Note the **Key** and **Secret** — you'll need them for secrets.yaml.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Home Assistant setup
|
||||||
|
|
||||||
|
### 2.1 Add secrets to `/config/secrets.yaml`
|
||||||
|
|
||||||
Replace values with your actual OPNsense details:
|
Replace values with your actual OPNsense details:
|
||||||
yamlopnsense_alias_add_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/add/parental_blocked"
|
|
||||||
|
```yaml
|
||||||
|
opnsense_alias_add_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/add/parental_blocked"
|
||||||
opnsense_alias_del_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/delete/parental_blocked"
|
opnsense_alias_del_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/delete/parental_blocked"
|
||||||
opnsense_apply_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias/reconfigure"
|
opnsense_apply_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias/reconfigure"
|
||||||
|
|
||||||
# Generate with: echo -n "APIKEY:APISECRET" | base64
|
# Generate with: echo -n "APIKEY:APISECRET" | base64
|
||||||
opnsense_basic_auth: "Basic BASE64_OF_KEY_COLON_SECRET"
|
opnsense_basic_auth: "Basic BASE64_OF_KEY_COLON_SECRET"
|
||||||
|
```
|
||||||
|
|
||||||
To generate the base64 string on any Linux/macOS machine:
|
To generate the base64 string on any Linux/macOS machine:
|
||||||
bashecho -n "your_api_key:your_api_secret" | base64
|
```bash
|
||||||
2.2 Copy files into place
|
echo -n "your_api_key:your_api_secret" | base64
|
||||||
bash# From your config directory
|
```
|
||||||
|
|
||||||
|
### 2.2 Copy files into place
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your config directory
|
||||||
cp packages/parental_controls.yaml /config/packages/
|
cp packages/parental_controls.yaml /config/packages/
|
||||||
cp www/parental_controls.html /config/www/
|
cp www/parental_controls.html /config/www/
|
||||||
|
```
|
||||||
|
|
||||||
If you don't use packages yet, add this to /config/configuration.yaml:
|
> If you don't use packages yet, add this to `/config/configuration.yaml`:
|
||||||
yamlhomeassistant:
|
> ```yaml
|
||||||
packages: !include_dir_named packages
|
> homeassistant:
|
||||||
|
> packages: !include_dir_named packages
|
||||||
|
> ```
|
||||||
|
|
||||||
2.3 Add the sidebar panel
|
### 2.3 Add the sidebar panel
|
||||||
Add to /config/configuration.yaml:
|
|
||||||
yamlpanel_iframe:
|
Add to `/config/configuration.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
panel_iframe:
|
||||||
parental_controls:
|
parental_controls:
|
||||||
title: "Parental Controls"
|
title: "Parental Controls"
|
||||||
icon: mdi:shield-account
|
icon: mdi:shield-account
|
||||||
url: /local/parental_controls.html
|
url: /local/parental_controls.html
|
||||||
require_admin: true
|
require_admin: true
|
||||||
2.4 Restart Home Assistant
|
```
|
||||||
Check for errors in Settings → System → Logs. The input_text.parental_control_config entity should now exist.
|
|
||||||
|
|
||||||
Step 3 — Dashboard first run
|
### 2.4 Restart Home Assistant
|
||||||
|
|
||||||
Open the Parental Controls sidebar panel
|
Check for errors in Settings → System → Logs. The `input_text.parental_control_config` entity should now exist.
|
||||||
On first load, you'll see a setup screen. Enter:
|
|
||||||
|
|
||||||
HA URL: your HA URL (e.g. https://ha.hideawaygaming.com.au)
|
---
|
||||||
Long-Lived Token: from your HA Profile → Security → Long-Lived Access Tokens → Create Token
|
|
||||||
|
|
||||||
|
## Step 3 — Dashboard first run
|
||||||
|
|
||||||
Click Connect
|
1. Open the **Parental Controls** sidebar panel
|
||||||
|
2. On first load, you'll see a setup screen. Enter:
|
||||||
|
- **HA URL**: your HA URL (e.g. `https://ha.hideawaygaming.com.au`)
|
||||||
|
- **Long-Lived Token**: from your HA Profile → Security → Long-Lived Access Tokens → Create Token
|
||||||
|
3. Click **Connect**
|
||||||
|
|
||||||
Your credentials are saved to browser localStorage — you won't need to enter them again on the same device.
|
Your credentials are saved to browser `localStorage` — you won't need to enter them again on the same device.
|
||||||
|
|
||||||
Usage
|
---
|
||||||
Adding users
|
|
||||||
Click + Add User, give them a name and pick a colour.
|
|
||||||
Adding devices
|
|
||||||
On a user card, click + Add Device. Either:
|
|
||||||
|
|
||||||
Pick from the discovered devices list (devices seen by the OPNsense integration)
|
## Usage
|
||||||
Or enter a MAC address manually
|
|
||||||
|
|
||||||
|
### Adding users
|
||||||
|
|
||||||
Tip: Set DHCP static leases in OPNsense for kids' devices so their IPs stay consistent, though the dashboard handles IP changes automatically.
|
Click **+ Add User**, give them a name and pick a colour.
|
||||||
|
|
||||||
Blocking
|
### Adding devices
|
||||||
|
|
||||||
User toggle (top right of card): blocks/unblocks all devices for that user simultaneously
|
On a user card, click **+ Add Device**. Either:
|
||||||
Device toggle (on each device row): individual device control
|
- Pick from the **discovered devices** list (devices seen by the OPNsense integration)
|
||||||
|
- Or enter a MAC address manually
|
||||||
|
|
||||||
|
> **Tip**: Set DHCP static leases in OPNsense for kids' devices so their IPs stay consistent, though the dashboard handles IP changes automatically.
|
||||||
|
|
||||||
|
### Blocking
|
||||||
|
|
||||||
|
- **User toggle** (top right of card): blocks/unblocks all devices for that user simultaneously
|
||||||
|
- **Device toggle** (on each device row): individual device control
|
||||||
|
|
||||||
If a device is offline when you block it, the dashboard marks it blocked and will apply the firewall rule automatically when the device reconnects.
|
If a device is offline when you block it, the dashboard marks it blocked and will apply the firewall rule automatically when the device reconnects.
|
||||||
Scheduling
|
|
||||||
Expand the 🕐 Schedule section on any user card:
|
|
||||||
|
|
||||||
Enable the schedule toggle
|
### Scheduling
|
||||||
Set block and unblock times for weekdays and weekends
|
|
||||||
Times are enforced every minute while the dashboard page is open
|
|
||||||
|
|
||||||
The time range is the blocked window — e.g. 21:00 → 07:00 means blocked from 9pm until 7am (overnight ranges work correctly).
|
Expand the **🕐 Schedule** section on any user card:
|
||||||
HA-native schedule enforcement (optional)
|
|
||||||
For schedules to be enforced even when the dashboard isn't open, uncomment the automation: block at the bottom of packages/parental_controls.yaml and restart HA. Note: the YAML automation requires the from_json Jinja2 filter and HA 2023.4+.
|
|
||||||
|
|
||||||
Troubleshooting
|
1. Enable the schedule toggle
|
||||||
Block doesn't seem to apply
|
2. Set **block** and **unblock** times for weekdays and weekends
|
||||||
|
3. Times are enforced every minute while the dashboard page is open
|
||||||
|
|
||||||
Confirm the parental_blocked alias exists in OPNsense → Firewall → Aliases
|
The time range is the **blocked** window — e.g. `21:00 → 07:00` means blocked from 9pm until 7am (overnight ranges work correctly).
|
||||||
Check the blocking rule is above the default LAN allow rule
|
|
||||||
Verify your API credentials: test in a browser → https://YOUR_OPNSENSE/api/firewall/alias_util/aliases — should return JSON
|
|
||||||
|
|
||||||
Device not appearing in discovered list
|
#### HA-native schedule enforcement (optional)
|
||||||
|
|
||||||
Make sure the OPNsense integration is installed and the device has been seen recently
|
For schedules to be enforced even when the dashboard isn't open, uncomment the `automation:` block at the bottom of `packages/parental_controls.yaml` and restart HA. Note: the YAML automation requires the `from_json` Jinja2 filter and HA 2023.4+.
|
||||||
Try using a manual MAC entry instead
|
|
||||||
|
|
||||||
"Failed to save config"
|
---
|
||||||
|
|
||||||
Check HA logs for input_text.parental_control_config errors
|
## Troubleshooting
|
||||||
Ensure the package loaded correctly (no YAML errors in startup logs)
|
|
||||||
|
|
||||||
Dashboard won't connect
|
**Block doesn't seem to apply**
|
||||||
|
- Confirm the `parental_blocked` alias exists in OPNsense → Firewall → Aliases
|
||||||
|
- Check the blocking rule is above the default LAN allow rule
|
||||||
|
- Verify your API credentials: test in a browser → `https://YOUR_OPNSENSE/api/firewall/alias_util/aliases` — should return JSON
|
||||||
|
|
||||||
Confirm the Long-Lived Token is correct
|
**Device not appearing in discovered list**
|
||||||
If using a self-signed cert on HA, the page may have cert warnings — trust the cert first by visiting the HA URL directly
|
- Make sure the OPNsense integration is installed and the device has been seen recently
|
||||||
|
- Try using a manual MAC entry instead
|
||||||
|
|
||||||
|
**"Failed to save config"**
|
||||||
|
- Check HA logs for `input_text.parental_control_config` errors
|
||||||
|
- Ensure the package loaded correctly (no YAML errors in startup logs)
|
||||||
|
|
||||||
|
**Dashboard won't connect**
|
||||||
|
- Confirm the Long-Lived Token is correct
|
||||||
|
- If using a self-signed cert on HA, the page may have cert warnings — trust the cert first by visiting the HA URL directly
|
||||||
|
|||||||
+13
-1
@@ -1 +1,13 @@
|
|||||||
IyBBZGQgdGhlc2UgZW50cmllcyB0byB5b3VyIC9jb25maWcvc2VjcmV0cy55YW1sCiMgUmVwbGFjZSB3aXRoIHlvdXIgYWN0dWFsIE9QTnNlbnNlIGRldGFpbHMKCiMgWW91ciBPUE5zZW5zZSBhbGlhcyBBUEkgZW5kcG9pbnRzCiMgUmVwbGFjZSAib3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1IiB3aXRoIHlvdXIgT1BOc2Vuc2UgSVAgb3IgaG9zdG5hbWUKb3Buc2Vuc2VfYWxpYXNfYWRkX3VybDogImh0dHBzOi8vb3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2FwaS9maXJld2FsbC9hbGlhc191dGlsL2FkZC9wYXJlbnRhbF9ibG9ja2VkIgpvcG5zZW5zZV9hbGlhc19kZWxfdXJsOiAiaHR0cHM6Ly9vcG5zZW5zZS5oaWRlYXdheWdhbWluZy5jb20uYXUvYXBpL2ZpcmV3YWxsL2FsaWFzX3V0aWwvZGVsZXRlL3BhcmVudGFsX2Jsb2NrZWQiCm9wbnNlbnNlX2FwcGx5X3VybDogImh0dHBzOi8vb3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2FwaS9maXJld2FsbC9hbGlhcy9yZWNvbmZpZ3VyZSIKCiMgQmFzaWMgYXV0aCBoZWFkZXIg4oCUIGdlbmVyYXRlIHdpdGg6CiMgICBlY2hvIC1uICJZT1VSX0FQSV9LRVk6WU9VUl9BUElfU0VDUkVUIiB8IGJhc2U2NAojIFRoZW4gcGFzdGUgdGhlIHJlc3VsdCBpbiBwbGFjZSBvZiB0aGUgcGxhY2Vob2xkZXIgYmVsb3c6Cm9wbnNlbnNlX2Jhc2ljX2F1dGg6ICJCYXNpYyBSRVBMQUNFX1dJVEhfQkFTRTY0X09GX0FQSUtFWV9DT0xPTl9BUElTRUNSRVQiCg==
|
# Add these entries to your /config/secrets.yaml
|
||||||
|
# Replace with your actual OPNsense details
|
||||||
|
|
||||||
|
# Your OPNsense alias API endpoints
|
||||||
|
# Replace "opnsense.hideawaygaming.com.au" with your OPNsense IP or hostname
|
||||||
|
opnsense_alias_add_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias_util/add/parental_blocked"
|
||||||
|
opnsense_alias_del_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias_util/delete/parental_blocked"
|
||||||
|
opnsense_apply_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias/reconfigure"
|
||||||
|
|
||||||
|
# Basic auth header — generate with:
|
||||||
|
# echo -n "YOUR_API_KEY:YOUR_API_SECRET" | base64
|
||||||
|
# Then paste the result in place of the placeholder below:
|
||||||
|
opnsense_basic_auth: "Basic REPLACE_WITH_BASE64_OF_APIKEY_COLON_APISECRET"
|
||||||
|
|||||||
Reference in New Issue
Block a user