Glocker is a Linux-based distraction blocking system written in Go. It blocks distracting websites and applications using multiple enforcement mechanisms to make bypassing difficult. The tool runs as a privileged setuid systemd service and uses Unix sockets for IPC.
Glocker is a Go application organized into modular packages under internal/:
glocker/
├── main.go # Entry point, CLI flags, daemon startup
├── cmd/ # Additional binaries
│ ├── glocker/ # Main daemon
│ ├── glocklock/ # Screen locker utility
│ └── glockpeek/ # Log analysis tool
├── internal/ # Application packages
│ ├── cli/ # Command processors
│ ├── config/ # Configuration loading (YAML)
│ ├── enforcement/ # Core blocking logic
│ ├── install/ # Installation/uninstallation
│ ├── ipc/ # Unix socket server
│ ├── monitoring/ # Background monitoring tasks
│ ├── notify/ # Email notifications
│ ├── state/ # Thread-safe global state
│ ├── utils/ # Shared utilities
│ └── web/ # HTTP server for extension
├── extensions/firefox/ # Browser extension
├── conf/conf.yaml # Sample configuration (~60MB)
└── extras/glocker.service # Systemd service definition
Glocker uses multiple independent monitors that work together to enforce blocking:
What it does: Modifies /etc/hosts to redirect blocked domains to 127.0.0.1
How it works:
- Writes blocked domains below
### GLOCKER START ###. - Sets file immutable using
chattr +i(when enabled) - Updates every 60 seconds (configurable via
enforce_interval_seconds) - Handles 800,000+ domains efficiently (memory optimization clears list after initial write)
Time windows: Can block domains only during specific times/days
domains:
- name: "twitter.com"
always_block: false
time_windows:
- start: "09:00"
end: "17:00"
days: ["Mon", "Tue", "Wed", "Thu", "Fri"]What it does: Uses iptables to block domains at network level
How it works:
- Resolves domains to IPs and adds DROP rules
- More aggressive than hosts file (can't be bypassed by direct IP access)
- Disabled by default due to complexity
- Enable with
enable_firewall: true
What it does: Catches attempts to access blocked sites via HTTP/HTTPS
How it works:
- Runs HTTP server on port 80 and HTTPS on port 443
- When browser tries to access blocked domain (redirected by hosts file), server intercepts
- Records violation to database
- Executes configured command (e.g., play alert sound)
- Sends accountability email if enabled
- Shows blocking reason (always blocked, time-based, etc.)
Configuration:
web_tracking:
enabled: true
command: "mpg123 /path/to/alert.mp3" # Optional: command to run on blockWhat it does: Content monitoring for keywords and URL patterns in browsers
How it works:
- Firefox extension (in
extensions/firefox/) monitors page URLs and content - Fetches keyword lists from
http://127.0.0.1/keywordsAPI - Scans page content for forbidden keywords
- Reports violations to
http://127.0.0.1/reportAPI - Works with glocker's violation tracking system
Configuration:
extension_keywords:
url_keywords: ["gambling", "casino", "poker"]
content_keywords: ["bet", "jackpot"]
whitelist:
- "stackoverflow.com"
- "github.com"What it does: Kills specified programs during configured time windows
How it works:
- Checks every 5 seconds (configurable) for forbidden process names
- Kills processes using
killallwhen found during active time window - Useful for blocking browsers, chat apps, games during work hours
Configuration:
forbidden_programs:
enabled: true
check_interval_seconds: 5
programs:
- name: "chromium"
time_windows:
- start: "20:00"
end: "05:00"
days: ["Mon", "Tue", "Wed", "Thu", "Fri"]
- name: "mullvadbrowser" # Always blocked (no time windows)What it does: Counts violations and triggers action when threshold exceeded
How it works:
- Counts violations (web access attempts, content keyword matches) in time window
- Executes command when threshold reached (e.g., lock screen)
- Resets counter after time window expires
- Can be used to escalate enforcement
Configuration:
violation_tracking:
enabled: true
max_violations: 5
time_window_minutes: 60
command: "sudo -u noufal DISPLAY=:1 glocklock -duration 5m"
lock_duration: "5m" # For glocklockWhat it does: Restricts sudo access during blocking periods
How it works:
- Swaps between "allowed" and "blocked" sudoers lines based on time windows
- Prevents user from running
sudoto bypass protections - Can whitelist specific commands (e.g., suspend, package management)
Configuration:
sudoers:
enabled: true
user: "noufal"
allowed_sudoers_line: "noufal ALL=(ALL) NOPASSWD:ALL"
blocked_sudoers_line: "noufal ALL=(ALL) NOPASSWD: /usr/bin/apt, /sbin/modprobe"
time_allowed:
- start: "10:00"
end: "16:00"
days: ["Mon", "Tue", "Wed", "Thu", "Fri"]What it does: Monitors critical files for modifications and restores them
How it works:
- Calculates checksums of
/etc/hosts, glocker binary, systemd service - Checks every 30 seconds (configurable)
- Re-applies protections if tampering detected
- Executes alarm command (e.g., play sound, send notification)
Configuration:
enable_self_healing: true
tamper_detection:
enabled: true
check_interval_seconds: 30
alarm_command: "mpg123 /path/to/alarm.mp3"What it does: Emergency enforcement via system suspension
How it works:
- Suspends system using
pm-suspendorrtcwake - Monitors for early wake (via logind D-Bus signals)
- Re-suspends system if woken before timer expires
- Requires accountability partner to disable panic mode
- Nuclear option for moments of extreme distraction
Usage:
# Suspend for 30 minutes (re-suspends on early wake)
glocker -panic 30Configuration:
panic_command: "sudo pm-suspend" User attempts to access blocked site
|
v
┌──────────────────────────────────────────────────────┐
| DNS/Hosts Resolution |
| /etc/hosts redirects blocked.com → 127.0.0.1 |
└──────────────────────────────────────────────────────┘
|
v
┌──────────────────────────────────────────────────────┐
| HTTP Request to 127.0.0.1:80/443 |
| Web tracking server intercepts request |
└──────────────────────────────────────────────────────┘
|
v
┌──────────────────────────────────────────────────────┐
| Violation Recording |
| • Increment violation counter |
| • Log to database with timestamp |
| • Execute web_tracking.command (alert sound) |
| • Send to accountability partner (if enabled) |
└──────────────────────────────────────────────────────┘
|
v
┌──────────────────────────────────────────────────────┐
| Check Violation Threshold |
| If count >= max_violations in time_window: |
| Execute violation_tracking.command (lock screen) |
└──────────────────────────────────────────────────────┘
|
v
┌──────────────────────────────────────────────────────┐
| Show Blocking Page |
| Redirect to: http://127.0.0.1/blocked?domain=... |
| Display blocking reason and time remaining |
└──────────────────────────────────────────────────────┘
Meanwhile, in parallel:
• Browser Extension monitors page content for keywords
• Forbidden Programs monitor kills blocked apps
• Sudoers control restricts sudo during work hours
• Tamper detection ensures protections stay active
systemd launches glocker
|
v
┌──────────────────┐
│ main.go │
│ -daemon flag │
└──────────────────┘
|
v
┌──────────────────────────────────────┐
│ Load config from YAML │
│ (/etc/glocker/config.yaml) │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Start Unix socket server │
│ (/tmp/glocker.sock) │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Launch background goroutines: │
│ • Tamper detection monitor │
│ • Forbidden programs monitor │
│ • Violation tracking monitor │
│ • Panic mode monitor │
│ • Web tracking HTTP/HTTPS servers │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Main enforcement loop (60s cycle): │
│ • Update /etc/hosts file │
│ • Update firewall rules │
│ • Update sudoers restrictions │
│ • Evaluate time windows │
│ • Apply file immutability │
└──────────────────────────────────────┘
User runs: glocker -status
|
v
┌──────────────────────────────────────┐
│ Connect to /tmp/glocker.sock │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Send command: "status" │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Daemon processes request │
│ (internal/ipc/server.go) │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Generate response │
│ (internal/cli/commands.go) │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Send response back to client │
└──────────────────────────────────────┘
|
v
┌──────────────────────────────────────┐
│ Client displays formatted output │
└──────────────────────────────────────┘
Communication between CLI and daemon uses Unix socket with simple text protocol:
Format: "action:payload\n"
Examples:
status\n- Request runtime statusreload\n- Reload configurationunblock:youtube.com,reddit.com:work\n- Temporarily unblock domainsblock:facebook.com\n- Permanently block domainpanic:30\n- Enter panic mode for 30 minutes
Responses: Multi-line text ending with "END\n"
Glocker is installed as a setuid root binary:
- Allows non-root users to run commands via socket
- Daemon runs with elevated privileges to modify
/etc/hosts, iptables, sudoers - Binary made immutable with
chattr +ito prevent tampering
To handle 800,000+ domains:
- Full domain list loaded during initial enforcement
- List written to
/etc/hosts - Domain list cleared from memory after initial write to save RAM
- Only time-window domains (typically <10) kept cached
- On config reload, domains are loaded from disk temporarily
Web tracking needs domain info but domains are cleared from memory:
- First violation: Loads domain from config file (~3-4s)
- Subsequent violations: Uses cached domain info (~0.2s, 15-20x faster)
- Cache cleared on config reload
- Only accessed domains are cached (memory efficient)
// Ported from internal/utils/time.go
func IsInTimeWindow(current, start, end string) bool {
if start <= end {
// Normal window: 09:00 to 17:00
return current >= start && current <= end
} else {
// Midnight-crossing: 22:00 to 05:00
return current >= start || current <= end
}
}# Make /etc/hosts immutable (requires root)
chattr +i /etc/hosts
# Remove immutability to update
chattr -i /etc/hosts
# Check immutable status
lsattr /etc/hosts# Standard entries
127.0.0.1 localhost
::1 localhost
### GLOCKER START ###
127.0.0.1 blocked-domain1.com
127.0.0.1 www.blocked-domain1.com
::1 blocked-domain1.com
::1 www.blocked-domain1.com
127.0.0.1 blocked-domain2.com
...
# User's custom entries below (preserved)
Firefox Extension (background.js)
|
v
GET http://127.0.0.1/keywords
|
v
{"url_keywords": [...], "content_keywords": [...]}
|
v
Extension monitors page URLs and content
|
v
POST http://127.0.0.1/report
{"trigger": "url_keyword_match", "url": "...", "domain": "..."}
|
v
Glocker records violation
// internal/monitoring/violations.go
func RecordViolation(cfg *config.Config, violationType, domain, url string) {
// 1. Add to in-memory list
violations = append(violations, Violation{
Type: violationType,
Domain: domain,
URL: url,
Timestamp: time.Now(),
})
// 2. Log to file
logViolation(cfg, violation)
// 3. Check threshold
recentCount := countRecentViolations(cfg.ViolationTracking.TimeWindowMinutes)
if recentCount >= cfg.ViolationTracking.MaxViolations {
// 4. Execute command (e.g., lock screen)
executeViolationCommand(cfg)
}
}github.com/mailgun/mailgun-go/v4- Email notifications via Mailgungopkg.in/yaml.v3- YAML configuration parsing
iptables/ip6tables- Firewall enforcement (optional)systemd- Service managementchattr/lsattr- File immutability- Firefox with extension support (for content monitoring)
/etc/glocker/config.yaml- Main configuration/tmp/glocker.sock- Unix socket for IPC/var/log/glocker-reports.log- Content monitoring logs/var/log/glocker-unblocks.log- Unblock request logs/usr/local/bin/glocker- Installed binary (setuid root)/etc/systemd/system/glocker.service- Systemd service file
When enabled:
- Monitors critical file checksums (binary, /etc/hosts, systemd service)
- Re-applies protections if tampering detected
- Triggers alarm command on tampering
- Setuid root binary with immutable flag (
chattr +i) - Immutable /etc/hosts during blocking
- Sudoers restrictions prevent privilege escalation
- Mindful delay (configurable, default 60s) before uninstall completes
- Sends email notifications via Mailgun when blocks are bypassed
- Logs all unblock attempts with reasons
- Daily violation reports (configurable)