A comprehensive parental control package for pfSense that helps parents manage and limit their children's internet access time.
Package ID: KACI-Parental_Control
Version: 1.4.61 (Production)
Author: Mukesh Kesharwani (Keekar)
Status: Production Ready
License: GPL 3.0 or later
Repository: https://keekar2022.github.io/KACI-Parental_Control/
Β© 2026 Keekar
# Step 1: Configure repository
mkdir -p /usr/local/etc/pkg/repos
cat > /usr/local/etc/pkg/repos/kaci.conf << 'EOF'
kaci: {
url: "https://keekar2022.github.io/KACI-Parental_Control/packages/freebsd/${ABI}/latest",
mirror_type: "NONE",
signature_type: "fingerprints",
fingerprints: "/usr/local/etc/pkg/fingerprints/kaci",
enabled: yes,
priority: 10
}
EOF
# Step 2: Download and install GPG fingerprint for package verification
mkdir -p /usr/local/etc/pkg/fingerprints/kaci
fetch -o /usr/local/etc/pkg/fingerprints/kaci/trusted \
https://keekar2022.github.io/KACI-Parental_Control/fingerprints/kaci/trusted
# Step 3: Install package
pkg update
pkg install -y kaci-parental-controlBenefits:
β
GPG-signed packages - Cryptographically verified authenticity
β
Binary distribution - Source code protected
β
Automatic updates - Seamless package upgrades
β
GitHub-hosted - Reliable, fast delivery
β
Professional package management - Standard FreeBSD pkg tools
Repository: https://keekar2022.github.io/KACI-Parental_Control/
GPG Fingerprint: 7F066616F4E6AFA912A6B418E511980F2F261ED5
./INSTALL.sh <pfsense_ip_address>
# Example: ./INSTALL.sh 192.168.1.1Requirements:
- pfSense 2.7.0+ with SSH enabled
- Network access to pfSense
- Basic SSH/command-line knowledge
Dependencies (auto-checked and installed):
sudo(security/sudo v1.9.16p2+)cron(sysutils/cron v0.3.8_6+)
Migration: If you have an existing legacy installation, see Migration Guide
- Child Profiles - Create separate profiles for each child
- Shared Time Limits - Time limits apply across ALL devices in a profile
- Profile Icons - Visual identification with emojis
- DHCP/ARP Auto-Discovery - Easily select devices from your network
- Daily Time Limits - Set maximum internet time per day (e.g., 2 hours)
- Weekly Time Limits - Set cumulative weekly limits
- Weekend Bonus - Grant extra time on weekends
- Automatic Reset - Counters reset at midnight (configurable)
- Bypass-Proof - Time is shared across all devices, can't switch devices to get more time
- Bedtime Blocking - Block internet during sleep hours (e.g., 21:00-07:00)
- School Hours - Block during school time (weekdays 08:00-15:00)
- Custom Schedules - Define any custom blocked periods per profile
- Flexible Scheduling - Supports day ranges (Mon-Fri) and specific days
- Auto-Discovery - Select devices from DHCP/ARP table dropdown
- MAC Address Tracking - Reliable device identification
- Multiple Devices Per Profile - Each child can have phone, tablet, laptop, etc.
- Real-time Status - See which devices are online, blocked, or have time remaining
- Strict Mode - Block all internet traffic (recommended)
- Moderate Mode - Block only web browsing (HTTP/HTTPS)
- DNS Mode - DNS-based filtering (easier to bypass, not recommended)
- Automatic Redirect - Blocked devices see a beautiful block page instead of silent blocking
- No Authentication - Block page works without pfSense login
- Modern UI - Responsive design with gradient colors and icons
- Device Information - Shows device name, IP, profile, usage, and reason for blocking
- Parent Override - Password-protected temporary access feature
- Real-time Info - Displays when access will be restored
- Live Dashboard - Real-time device status and usage
- Usage Tracking - Time used today and remaining time
- OpenTelemetry Logging - Structured JSON logs for SIEM integration
- Activity Logging - Comprehensive logs at
/var/log/parental_control.jsonl - SIEM Ready - Compatible with Splunk, Elasticsearch, Grafana Loki, Graylog
cd /Users/mkesharw/Documents/Pfsense-ext/Parental_Control
./INSTALL.sh 192.168.64.10 # Your pfSense IPIn pfSense web interface:
- Go to Services > Parental Control
- Check Enable Parental Control
- Set Enforcement Mode: Strict
- Set Grace Period: 5 minutes
- Click Save
- Go to Devices tab
- Click + Add
- Configure:
- Child Name: Emma
- Device Name: iPad
- MAC Address: aa:bb:cc:dd:ee:ff (find in device settings)
- Daily Time Limit: 120 (2 hours)
- Weekend Bonus: 60 (extra hour on weekends)
- Add a schedule (optional):
- Name: Bedtime
- Days: Mon,Tue,Wed,Thu,Sun (school nights)
- Start Time: 21:00
- End Time: 07:00
- Click Save
- Go to Status tab to see real-time device status
- View logs:
ssh admin@192.168.64.10 "tail -f /var/log/parental_control.jsonl"
Device: Child's iPad
Daily Limit: 120 minutes (2 hours)
Weekend Bonus: 60 minutes (1 extra hour Sat/Sun)
Schedule 1 - Bedtime:
Days: Sun,Mon,Tue,Wed,Thu
Time: 21:00 - 07:00
Schedule 2 - School Hours:
Days: Mon,Tue,Wed,Thu,Fri
Time: 08:00 - 15:00
Result:
- 2 hours internet per weekday, 3 hours on weekends
- No internet during bedtime (school nights)
- No internet during school hours
Device: Gaming Console
Daily Limit: 180 minutes (3 hours)
Schedule - Weekdays Blocked:
Days: Mon,Tue,Wed,Thu,Fri
Time: 00:00 - 23:59
Result: Only accessible on weekends, 3 hours per day
Device: Laptop
Daily Limit: 240 minutes (4 hours)
Weekend Bonus: 120 minutes (2 extra hours)
Result: 4 hours/day weekdays, 6 hours/day weekends, available anytime
Set warning time before blocking (5-15 minutes recommended):
- Device still has access during grace period
- Allows user to save work
Enable DNS-based content filtering:
- Go to Settings > Advanced
- Check Enable Content Filtering
- Select DNS provider:
- OpenDNS FamilyShield - Blocks adult content
- Cloudflare for Families - Blocks malware + adult content
- Custom - Specify your own DNS servers
Create device entries for each child:
Child 1 (Age 8):
- iPad: 90 min/day, bedtime 20:00-07:00
- Nintendo: Weekend only, 120 min/day
Child 2 (Age 14):
- Phone: 180 min/day, bedtime 22:00-07:00
- Laptop: 240 min/day, no bedtime
| File | Purpose | Lines |
|---|---|---|
parental_control.inc |
Core PHP logic and enforcement engine | ~3,100 |
parental_control.xml |
Main package definition and pfSense hooks | ~200 |
info.xml |
Package metadata for pfSense registry | ~50 |
VERSION |
Single source of truth for version number | ~5 |
| File | Purpose |
|---|---|
parental_control_profiles.php |
Profile management UI (create/edit/delete profiles) |
parental_control_schedules.php |
Schedule management UI (bedtime, no-internet times) |
parental_control_status.php |
Real-time status dashboard with device usage |
parental_control_blocked.php |
Block page shown to users (authenticated) |
parental_control_captive.php |
Captive portal block page (non-authenticated) |
parental_control_api.php |
RESTful API for external integrations |
parental_control_health.php |
Health check endpoint for monitoring |
| File | Purpose |
|---|---|
parental_control_diagnostic.php |
Comprehensive diagnostic tool for troubleshooting |
parental_control_analyzer.sh |
Log analyzer and statistics generator |
parental_control_captive.sh |
RC script for captive portal web server |
| File | Purpose |
|---|---|
INSTALL.sh |
Automated installation/update script (SSH-based) |
UNINSTALL.sh |
Complete package removal script |
bump_version.sh |
Version management automation script |
| Location | Contents |
|---|---|
README.md |
This file - overview and quick start |
docs/USER_GUIDE.md |
Complete user guide with changelog |
docs/TECHNICAL_REFERENCE.md |
API, architecture, development guide |
docs/GETTING_STARTED.md |
Installation and setup walkthrough |
docs/BEST_PRACTICES_KACI.md |
Lessons learned from the project |
- Core Package: ~3,500 lines of PHP code
- Web UI: ~2,000 lines across 7 PHP pages
- Scripts: ~1,500 lines of shell scripts
- Documentation: ~8,000 lines across 4 comprehensive guides
- Disk Space: ~500KB total installed size
- Tracks devices by MAC address
- Monitors ARP table for device presence
- Detects when device connects to network
- Cron job runs every minute
- Checks device connections via ARP
- Increments usage counter if device is online
- Enforces block when limit reached
- Checks current time against configured schedules
- Blocks device during scheduled periods
- Independent of time limit counters
- Creates pfSense firewall rules dynamically
- Rules block based on source MAC/IP
- Updates rules via
filter_configure()API - Rules persist until time/schedule allows access
- Settings stored in pfSense
/cf/conf/config.xml - Uses
<installedpackages><parental_control>section - Survives reboots
- Backed up with pfSense config backups
# SSH to pfSense (replace YOUR-FIREWALL-IP)
ssh admin@YOUR-FIREWALL-IP
# Check files are present
ls -la /usr/local/pkg/parental_control*
# Check system log
tail -50 /var/log/system.log | grep parental
# Try reinstalling (from your local machine)
cd /path/to/KACI-Parental_Control
./INSTALL.sh YOUR-FIREWALL-IPSee User Guide for complete troubleshooting steps including:
- Checking enforcement mode
- Verifying MAC addresses
- Inspecting firewall rules
- Viewing and analyzing logs
- Check cron job:
crontab -lshould show parental_control entry - Check device is online: Go to Status tab in UI
- View logs: Look for "Device X is online" messages
- Verify ARP: Device must appear in ARP table
- Check grace period: Device has X minutes grace period after limit
- Check device IP/MAC: Might be using different IP/MAC
- Check rules order: Parental control rules should be at top
- Reapply config: Edit device and save again to regenerate rules
- Package automatically starts
- Cron jobs recreated
- Firewall rules reapplied
- Usage counters preserved
- pfSense: 2.7.0 or later
- FreeBSD: 13.0+ (included with pfSense 2.7+)
- PHP: 8.1+ (included with pfSense)
- Disk Space: ~100KB for package files
- Memory: Minimal (~5MB runtime)
/usr/local/pkg/parental_control.xml # Main UI
/usr/local/pkg/parental_control_devices.xml # Device UI
/usr/local/pkg/parental_control.inc # Core logic
/usr/local/www/parental_control_status.php # Status page
/usr/local/share/pfSense-pkg-parental_control/info.xml # Metadata
/cf/conf/config.xml # Configuration storage
/var/log/parental_control.jsonl # Activity log
Runs every minute: */1 * * * *
Executes: /usr/local/bin/php -f /usr/local/pkg/parental_control.inc -- cron
Core Functions (in parental_control.inc):
parental_control_validate_form()- Validates user inputparental_control_sync_package()- Applies configuration changesparental_control_cron_job()- Main enforcement logic (runs every minute)parental_control_get_device_status()- Gets real-time device statusparental_control_log()- Writes to log file
pfSense Integration:
filter_configure()- Reloads firewall rulesmwexec()- Executes system commandswrite_config()- Saves configurationget_arp_table()- Gets connected devices
The package automatically checks for updates every 15 minutes and upgrades when available.
# Check for updates
pkg update
pkg upgrade -n kaci-parental-control
# Perform upgrade
pkg upgrade kaci-parental-control
# Verify new version
pkg info kaci-parental-controlTo update after making changes:
# Edit files locally
vim parental_control.inc # or other files
# Test syntax (PHP files only)
php -l parental_control.inc
# Reinstall on pfSense (replace YOUR-FIREWALL-IP)
./INSTALL.sh YOUR-FIREWALL-IP
# Check pfSense web UI
# Verify changes took effectConsider migrating to PKG manager: See Migration Guide
Complete documentation in 3 comprehensive guides:
- π Getting Started - Installation, Quick Start, and Overview
- π User Guide - Configuration, Troubleshooting, and Maintenance
- π¬ Technical Reference - API, Architecture, and Development
See also:
- Changelog - Complete version history (in User Guide)
- Documentation Index - Navigate all documentation
- Release Notes - What's new in v1.0.0 (in User Guide)
# Replace YOUR-FIREWALL-IP with your actual pfSense IP address
# View logs in real-time
ssh admin@YOUR-FIREWALL-IP "tail -f /var/log/parental_control.jsonl"
# Check cron job
ssh admin@YOUR-FIREWALL-IP "crontab -l | grep parental"
# View ARP table (find device MACs)
ssh admin@YOUR-FIREWALL-IP "arp -an"
# Check firewall rules
ssh admin@YOUR-FIREWALL-IP "pfctl -sr | grep parental"
# Reinstall package
./INSTALL.sh YOUR-FIREWALL-IPFormat: OpenTelemetry-compliant JSON Lines (JSONL)
Location: /var/log/parental_control.jsonl
Structure: One complete JSON object per line (not a JSON array)
Why JSONL?
- β
Stream-friendly (
tail -fworks) - β Memory-efficient (process line-by-line)
- β Easy to append
- β SIEM standard format
Log Contents:
- Device connections/disconnections
- Time limit enforcement
- Schedule blocks/unblocks
- Configuration changes
- Errors and warnings
Example Log Entry:
{
"Timestamp": "2025-12-24T21:00:00.000000Z",
"SeverityText": "INFO",
"Body": "Created block rule for Emma - iPad: Bedtime schedule",
"Attributes": {
"event.action": "block_rule_created",
"child.name": "Emma",
"device.name": "iPad",
"device.mac": "aa:bb:cc:dd:ee:ff",
"rule.reason": "Bedtime schedule"
}
}Query Logs:
# Replace YOUR-FIREWALL-IP with your actual pfSense IP address
# View logs prettified
ssh admin@YOUR-FIREWALL-IP "cat /var/log/parental_control.jsonl | jq '.'"
# Filter by child (replace "Emma" with your child's name)
ssh admin@YOUR-FIREWALL-IP "cat /var/log/parental_control.jsonl | jq 'select(.Attributes.\"child.name\" == \"Emma\")'"
# Get error logs only
ssh admin@YOUR-FIREWALL-IP "cat /var/log/parental_control.jsonl | jq 'select(.SeverityText == \"ERROR\")'"SIEM Integration:
The package uses OpenTelemetry-compliant JSONL format for logs:
- Compatible with Splunk, Elasticsearch, Grafana Loki, Graylog
- Stream-friendly format (works with
tail -f) - One JSON object per line for efficient parsing
- See User Guide for advanced logging options
Package: KACI Parental Control for pfSense
Version: 1.4.61 (Production)
Status: Production Ready
Compatibility: pfSense 2.7.0+ (FreeBSD 14+)
License: GPL 3.0 or later
Repository: https://keekar2022.github.io/KACI-Parental_Control/
Need help? See our comprehensive Documentation for installation, configuration, and troubleshooting guides.