Skip to content

Releases: jbarwick/Gatesentry

v2.0.0-alpha.15

19 Feb 00:21

Choose a tag to compare

v2.0.0-alpha.15 Pre-release
Pre-release

Architecture Shift: Global → Per-User Rule-Based Filtering

The most significant change in v2 is moving away from global filter lists toward a fully rule-based filtering system.

In v1, proxy rules could already be defined for a user, and the rule system provided per-user targeting — that foundation was solid. However, the primary filtering mechanisms — blocked sites, exception lists, keyword filters, and DNS blocklists — operated as global pipelines that applied to everyone on the network identically. The per-user rules and the global filters were essentially two separate systems. Additionally, rules in v1 were strictly block rules — they could only deny access, not explicitly grant it.

In v2, those global filtering pipelines have been consolidated into the per-user rule system. There are no longer separate global blocked-site lists or global keyword filters running outside of rules. Instead, every filtering decision flows through the rule pipeline:

  • Everything is a rule now — Blocked domains, URL patterns, content-type filtering, and keyword scanning are all configured as properties of individual rules rather than global lists. What was previously a global "blocked sites" list becomes a rule referencing a Domain List with action "block."
  • Rules are match + action, not just block lists — Rules are no longer strictly "block" rules. Each rule is a matching rule with a configurable action: Allow or Block. Combined with priority ordering (lower number = higher priority, first match wins), this enables patterns that weren't possible before. For example, a high-priority "Allow" rule can grant a specific user access to educational-site.com even when a lower-priority "Block" rule blocks the entire category for everyone else. Exception lists become simply higher-priority Allow rules.
  • Per-user filtering becomes natural — Since all filtering is rule-scoped, targeting specific users is just a field on the rule. A "kids" rule can block adult content while an "adults" rule allows it. An empty user list means "all users."
  • DNS filtering is now optional — Domain blocking no longer requires the DNS server. All filtering can be handled entirely by proxy rules. DNS blocking is still available for users who want network-wide domain-level filtering, but it's no longer the only mechanism.
  • Reusable Domain Lists — Both DNS filtering and proxy rules share the same DomainListManager and in-memory index. A single curated list (StevenBlack, Hagezi, etc.) can be referenced by multiple rules and by DNS simultaneously.

8-Step Rule Pipeline

Each proxy request is evaluated through a well-defined pipeline, rule by rule in priority order. The first rule that fully matches is applied — subsequent rules are skipped:

  1. Rule status — Enabled/disabled, active hours schedule
  2. User match — Does the requesting user match the rule's user list?
  3. Domain match — Hostname checked against domain patterns (glob wildcards) and domain lists (by list ID)
  4. MITM resolution — Per-rule MITM setting: enable, disable, or default (fall back to global setting). Determines whether steps 5–7 can inspect HTTPS traffic.
  5. URL regex — Match against the full request URL (requires MITM for HTTPS)
  6. Content-type — Match against response Content-Type header (requires MITM for HTTPS)
  7. Keyword filter — Scan response body for blocked keywords with score watermark (requires MITM for HTTPS)
  8. ActionAllow or Block

If no rule matches after evaluating all rules, the request is allowed (default-allow). Because Allow rules participate in the same priority-ordered pipeline as Block rules, administrators can build layered policies: a broad Block rule at priority 100 blocking a category, with targeted Allow exceptions at priority 10 for specific users or domains.

Domain List System

A new DomainListManager provides CRUD operations, an O(1) in-memory index (map[domain] → set of list IDs), and support for both local lists and URL-sourced blocklists (StevenBlack, Hagezi, AdGuard, Firebog, etc.). DNS and proxy filtering share the same index. Includes automatic migration from the old blocklist format. Full API endpoints and a management UI at /domainlists.

Device Discovery (Foundation)

A new device discovery system using mDNS/Bonjour browsing and passive DNS observation lays the groundwork for per-device filtering in a future release. Devices are identified, tracked, and exposed via API. The data model and record store are in place (with 30+ tests), and the DNS handler already performs passive discovery. The next step would be allowing rules to target devices in addition to users.

Server-Side Rule Tester

Two new API endpoints (POST /api/test/rule-match, POST /api/test/domain-lookup) simulate the full 8-step pipeline against a rule definition without affecting live traffic. The rule editor UI has a built-in tester panel with optional live fetch to verify that a rule behaves as expected before saving.

Real-Time Stats and Logs via SSE

The stats page now uses Server-Sent Events for near-real-time updates, replacing the previous 5-second polling approach. DNS request events are emitted from the handler and streamed to the browser as they happen.

Proxy Hardening

  • Streaming 3-path content router (small buffer / scan / stream-through) with configurable GS_MAX_SCAN_SIZE_MB
  • Graceful shutdown with in-flight request draining
  • Proxy loop detection (Via header + X-GateSentry-Loop + XFF depth limit)
  • SSRF protection blocking proxy requests to the admin UI
  • HTTPS block page delivery (MITM-signed error page for blocked HTTPS requests)
  • WebSocket tunnel support
  • TRACE method blocking, response header sanitization

DNS Improvements

  • Sharded response cache with configurable TTL and negative caching
  • TCP query support (large responses > 512 bytes)
  • RFC 2136 dynamic DNS update handler
  • WPAD/PAC auto-configuration endpoints
  • IPv6 listener support
  • All settings configurable via environment variables

UI Overhaul

  • Complete Svelte/Carbon rewrite of the rule form matching the 8-step pipeline layout
  • New Domain Lists management page (/domainlists)
  • DNS page with allow/block domain list assignment sections
  • Configurable base path support for reverse proxy deployments
  • Docker deployment support with docker-compose.yml and publish script

Test Coverage

  • 19 rule-tester endpoint unit tests, 19 domain list unit tests
  • Comprehensive proxy deep test script (scripts/proxy_deep_tests.sh) covering MITM, content filtering, keyword scanning, loop detection, and more

Breaking Changes from v1

  • Admin UI default port: 107868080 (configurable via GS_ADMIN_PORT)
  • Rule struct expanded: domain_patterns, domain_lists, mitm_action, url_regex_patterns, blocked_content_types, keyword_filter_enabled, active_hours, users
  • Settings keys added: dns_domain_lists, dns_whitelist_domain_lists
  • Old global blockedDomains map replaced by shared DomainListIndex

How to Try It

git remote add jbarwick https://github.com/jbarwick/Gatesentry.git
git fetch jbarwick v2
git checkout jbarwick/v2
./build.sh && cd bin && ../run.sh
# Admin UI at http://localhost:8080

v1.20.6.3: fix: SSE zombie goroutine leak causing CPU/RAM spiral

19 Feb 00:12

Choose a tag to compare

fix: SSE zombie goroutine leak causing CPU/RAM spiral

The DNS events SSE handler (GET /api/dns/events) had no mechanism to
detect silently disconnected TCP connections. When a browser tab closed
without a clean TCP FIN (laptop sleep, network drop, browser crash),
the handler goroutine blocked forever on the channel select — becoming
a zombie. Each browser reconnect spawned a new goroutine while old ones
accumulated, causing 250%+ CPU and excessive RAM usage.

Fix:

  • Add 30-second heartbeat writer (SSE comment) that detects dead
    connections via write error, allowing the goroutine to exit
  • Add 4-hour max duration timer that forces a clean reconnect,
    preventing indefinite goroutine lifetime
  • Backported from v2 branch

Version bump to 1.20.6.3

v1.20.6.2 - DNS Cache Performance & Test Coverage

10 Feb 14:08

Choose a tag to compare

DNS Cache & Testing Infrastructure Improvements

Version: 1.20.6.2
Date: February 11, 2026

Overview

This PR delivers DNS cache performance improvements, comprehensive test coverage, and critical bug fixes that make GateSentry production-ready. Filter reload bugs have been fixed, and the test suite now covers all critical functionality.

Key Features

1. DNS Cache Infrastructure

Cache Hit Rate Improvements

  • Implemented per-minute cache statistics recording to BuntDB
  • Added real-time SSE event streaming for live cache monitoring
  • New /api/dns/cache/stats/history endpoint for historical data
  • Cache snapshots persist across restarts (24-hour retention)

Live Monitoring Dashboard

  • New DNS Cache tab in Stats view with real-time updates
  • Visualizations: hit rate, entries, evictions, expired entries
  • Rolling 1-hour metrics with per-minute granularity
  • Stacked area chart showing hits vs misses over time

Technical Implementation:

  • recorder.go: Periodic snapshot writer (1-minute intervals)
  • Per-minute counters reset after each snapshot
  • Sliding window query support (1h, 24h, 7d views)
  • Zero extra file handles (reuses existing BuntDB instance)

2. Critical Bug Fixes

Filter Reload Bug (CRITICAL)

  • Issue: Filter updates via API were saved to disk but never reloaded
  • Root Cause: R.Init() created a new slice, breaking webserver's pointer reference
  • Fix: Modified runtime reload to clear and repopulate existing slice
  • Impact: Keywords, URL blocks, and all filter updates now work correctly
  • Files Changed: application/runtime.go

Port Configuration

  • Changed Makefile to use port 8080 (non-privileged) for testing
  • Added GS_ADMIN_PORT=8080 environment variable support
  • Fixes test failures when running without root privileges

Certificate Naming

  • Updated auto-generated certificate to use "GateSentry CA" common name
  • Fixed test expectations in both test suites
  • Consistent with new certificate auto-generation feature

3. Certificate Management

One-Click CA Generation

  • New /api/certificate/generate endpoint
  • 4096-bit RSA certificates, 10-year validity
  • Admin UI button for certificate regeneration
  • Automatic PEM saving to settings storage
  • Immediate proxy certificate reload on update

Enhanced Download Experience

  • Certificate downloads as .crt file with proper MIME type
  • Updated UI with certificate status badges (Valid/Expiring/Expired)
  • Expiry warnings when < 90 days remain
  • Comprehensive installation instructions for Windows/macOS/Linux

Files Changed:

4. WPAD/PAC Auto-Configuration

Automatic Proxy Discovery

  • WPAD DNS interception toggle (responds to wpad.* queries)
  • PAC file generation and serving at /wpad.dat and /proxy.pac
  • Admin-configurable proxy host and port
  • Auto-detection of proxy host from admin login
  • Unauthenticated PAC file access (required by WPAD spec)

PAC File Features:

  • Bypass proxy for localhost and RFC 1918 private networks
  • Bypass proxy for GateSentry admin UI itself
  • Safe fallback to DIRECT when not configured

Admin UI:

  • New WPAD settings section with configuration form
  • Live PAC file preview
  • Setup guide for automatic and manual configuration
  • Status indicators (configured/not configured)

Files Changed:

5. Comprehensive Test Coverage

New Test: Keyword Content Blocking

  • End-to-end test for HTML keyword filtering (310 lines)
  • Tests filter POST → save → reload → actual blocking
  • Proper cleanup and state restoration
  • Files: tests/keyword_content_blocking_test.go

Test Infrastructure Improvements:

  • Fixed port configuration for non-root testing
  • All 8 test suites now pass (100% pass rate)
  • External server tests properly configured
  • Certificate name expectations updated

Test Results:

✓ auth_filters_test.go - Authentication & filter API access
✓ keyword_content_blocking_test.go - End-to-end keyword blocking (NEW)
✓ proxy_filtering_test.go - URL blocking filters
✓ integration_test.go - DNS server functionality
✓ integration_test.go - Statistics & logging
✓ integration_test.go - MIME type filtering
✓ user_management_test.go - User CRUD operations
✓ setup_test.go - Certificate validation

6. Enhanced Statistics API

Time-Scale Support:

  • /api/stats/byUrl now accepts seconds and group parameters
  • Granularity options: day (7d), hour (24h), minute (1h)
  • Local-time bucket keys prevent UTC/timezone mismatches
  • Frontend can request matching data for any time scale

Real-Time Event Streaming:

  • SSE endpoint serves DNS queries and cache events
  • Event types: request, query, hit, miss, evict, expire
  • Frontend subscribes once, receives all event types
  • Automatic pruning of events older than 7 days

Chart Improvements:

  • Fixed x-axis domain to always show full time window
  • Proper handling of sparse data (shows empty buckets)
  • Sliding window for cache chart (last 60 minutes)
  • Color-coded series (green for hits, red for misses/blocks)

Files Changed:

7. Status API Enhancements

Improved Network Detection:

  • New detectLanIP() function returns first non-loopback IPv4 address
  • Falls back to wpad_proxy_host setting (preferred)
  • Last resort uses legacy bound address
  • Fixes issues with incorrect 127.0.1.1 reporting on some systems

Extended Status Response:

  • Returns separate dns_address, dns_port, proxy_port, proxy_url
  • Frontend displays "Host: X — DNS port Y, Proxy port Z"
  • Clearer separation of DNS vs proxy configuration

Files Changed:

8. CORS Middleware

Cross-Origin Support:

  • New CORS middleware echoes Origin header
  • Allows access from multiple device hostnames
  • Required for accessing GateSentry from different addresses
    (e.g., monster-jj, monster-jj.local, 192.168.1.x, etc.)
  • Handles preflight OPTIONS requests

Files Changed:

9. Build & Runtime Improvements

Build Script Optimization:

  • build.sh now uses find -delete to preserve data files
  • Only removes binaries, keeps log databases and filter state
  • Prevents accidental data loss during rebuilds

Makefile Updates:

  • Port 8080 default for non-root development
  • GS_ADMIN_PORT environment variable support
  • Health check URL matches configured port

Script Improvements:

  • New restart.sh for graceful server restarts
  • Proper process detection and cleanup
  • Environment variable preservation

Files Changed:

10. UI Polish

Logs View:

  • DNS response types now shown with proper tags
  • Cached queries display with teal badge
  • Improved handling of DNS vs proxy events
  • Raspberry Pi SD card warning converted to inline notification

Settings View:

  • Integrated WPAD configuration section
  • Certificate management improvements
  • Better visual hierarchy and spacing

Home View:

  • Status display shows separate DNS and proxy ports
  • Clearer "starting..." state vs configured state
  • Improved server address presentation

Files Changed:

Breaking Changes

None. All changes are backward compatible.

Migration Notes

  • Existing filters and configuration will be preserved
  • Cache statistics begin accumulating after upgrade
  • Certificate regeneration is optional (existing certificates continue working)
  • WPAD is disabled by default until configured

Testing

All tests pass:

$ make test
=== RUN   TestAuthAndFilters
--- PASS: TestAuthAndFilters (2.34s)
=== RUN   TestKeywordContentBlocking
--- PASS: TestKeywordContentBlocking (8.12s)
=== RUN   TestProxyFiltering
--- PASS: TestProxyFiltering (3.45s)
=== RUN   TestDNSServer
--- PASS: TestDNSServer (1.23s)
=== RUN   TestStatisticsAndLogging
--- PASS: TestStatisticsAndLogging (2.01s)
=== RUN   TestMIMETypeFiltering
--- PASS: TestMIMETypeFiltering (1.89s)
=== RUN   TestUserManagement
--- PASS: TestUserManagement (1.67s)
=== RUN   TestCertificateValidation
--- PASS: TestCertificateValidation (0.56s)
PASS
ok      bitbucket.org/abdullah_irfan/gatesentryf/tests  21.27s

Documentation Updates

  • README.md: Unchanged (existing installation instructions remain valid)
  • CHANGELOG.md: Entry added for v1.20.6.2
  • This document (DNS_CACHE_FEATURE.md): Comprehensive feature documentation

Files Changed Summary

Backend (Go):

  • application/dns/cache/recorder.go (NEW) - Cache statistics recorder
  • application/dns/cache/recorder_test.go (NEW) - Recorder tests
  • application/runtime.go - Fixed filter reload bug
  • application/webserver/endpoints/handler_certificate.go - CA generation
  • `application/webserver/endpoints/handler_dns...
Read more

v1.20.6.1 — Device Discovery Service

09 Feb 09:33

Choose a tag to compare

What's New in v1.20.6.1

Based on upstream v1.20.6 with the following additions:

DNS Server Improvements

  • Fixed concurrent query blocking and data races
  • TCP query forwarding and truncated UDP retry over TCP
  • IPv6 resolver and listen address support
  • Environment-configurable DNS resolver (DNS_RESOLVER)

Device Discovery Service (Issue #1)

  • Passive discovery — automatically tracks devices from DNS queries
  • mDNS/Bonjour browser — discovers devices on the LAN via multicast DNS
  • RFC 2136 Dynamic DNS UPDATE — accepts dynamic DNS registrations with optional TSIG auth
  • Device data model with hostname, IP, MAC, vendor, and source tracking
  • Thread-safe record store with TTL-based expiry

Docker Deployment

  • Production-ready Dockerfile and docker-compose.yml
  • Configurable base path via GATESENTRY_BASE_PATH
  • Admin port consolidation (single port for proxy admin + web UI)

Admin UI

  • New Devices page for viewing discovered network devices
  • /api/devices REST endpoint
  • Base path support for reverse proxy deployments

Testing

  • 30+ new unit tests for device store, DNS handler, and mDNS browser
  • Cross-platform test script improvements

Upstream PRs: #135, #137