{"id":50782696,"url":"https://github.com/arumes31/blocklist","last_synced_at":"2026-06-12T05:01:24.171Z","repository":{"id":241597158,"uuid":"807186605","full_name":"arumes31/blocklist","owner":"arumes31","description":"Hardened Go-based IP Blocklist manager with GeoIP (ASN/Country), real-time WebSocket dashboard, RBAC, and automated webhooks.","archived":false,"fork":false,"pushed_at":"2026-06-10T05:30:36.000Z","size":48928,"stargazers_count":2,"open_issues_count":36,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-10T07:21:13.327Z","etag":null,"topics":["blocklist","docker-hardened","firewall-automation","geoip","golang","prometheus","rbac","security","websockets"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arumes31.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-28T16:11:24.000Z","updated_at":"2026-06-04T14:21:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"bb0e554a-4bdb-4490-9ae0-5ad178effaea","html_url":"https://github.com/arumes31/blocklist","commit_stats":null,"previous_names":["arumes31/blocklist"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/arumes31/blocklist","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arumes31%2Fblocklist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arumes31%2Fblocklist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arumes31%2Fblocklist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arumes31%2Fblocklist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arumes31","download_url":"https://codeload.github.com/arumes31/blocklist/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arumes31%2Fblocklist/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34229624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blocklist","docker-hardened","firewall-automation","geoip","golang","prometheus","rbac","security","websockets"],"created_at":"2026-06-12T05:01:23.226Z","updated_at":"2026-06-12T05:01:24.158Z","avatar_url":"https://github.com/arumes31.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"cmd/server/static/cd/logo.png\" alt=\"Blocklist\" width=\"800\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/Go-1.26-00ADD8?logo=go\" alt=\"Go 1.26\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/Redis-required-DC382D?logo=redis\u0026logoColor=white\" alt=\"Redis required\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/Docker-hardened-2496ED?logo=docker\u0026logoColor=white\" alt=\"Docker hardened\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=githubactions\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/Security-CodeQL-blue?logo=github\" alt=\"CodeQL\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-green.svg\" alt=\"License: MIT\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# Blocklist App (Go Edition)\n\nA high-performance, security-hardened IP management platform with GeoIP enrichment, real-time updates via WebSockets, and advanced filtering capabilities.\n\n## 🔄 Project Flow\n\n```mermaid\ngraph LR\n    Sources[Firewall/WAF/App] --\u003e|Webhook| API[Blocklist API]\n    API --\u003e|Index| Redis[(Redis Cache)]\n    API --\u003e|Persist| PG[(Postgres DB)]\n    API --\u003e|Live| WS((WebSockets))\n    WS --\u003e|Update| UI[Dashboard UI]\n    Firewall[Edge Firewall] --\u003e|Fetch| API\n    \n    style Sources fill:#8b0000,stroke:#ff0000,color:#fff\n    style API fill:#333,stroke:#ff0000,color:#fff\n    style Redis fill:#333,stroke:#ff0000,color:#fff\n    style PG fill:#333,stroke:#ff0000,color:#fff\n    style WS fill:#333,stroke:#ff0000,color:#fff\n    style UI fill:#333,stroke:#ff0000,color:#fff\n    style Firewall fill:#28a745,stroke:#fff,color:#fff\n```\n\n## Key Features\n\n- **Advanced Filtering**: Server-side filtering by IP, Reason, Country, Added By, and Date Range (ISO8601).\n- **Real-time Updates**: Live dashboard updates via WebSockets, now scaled with **Redis Pub/Sub** for multi-instance support.\n- **Visual Threat Intelligence**: Dedicated **Threat Map** page with interactive mapping (Leaflet) and distribution charts (Chart.js) for instant situational awareness.\n- **Audit Trail \u0026 Optimization**: Complete history of IP actions with automated **per-IP entry limiting** (configurable) to prevent database bloat.\n- **Ephemeral \u0026 Persistent Blocks**: Support for TTL-based temporary bans and manual persistent blocks.\n- **Local Map Solution**: Integrated world GeoJSON for offline mapping without external tile provider dependencies.\n- **Reliable Webhooks**: Persistent **Task Queue** for outbound notifications with automatic retries and exponential backoff.\n- **Bulk Operations**: Multi-select interface for batch unblocking and management.\n- **Security Hardening**: DOM-based XSS mitigation with robust HTML escaping, safe toast notifications using textContent, restricted slice memory allocation size validation, session invalidation on permission changes, and mandatory 2FA setup.\n- **Continuous Analysis**: Integrated **CodeQL** and **Gosec** for automated vulnerability detection and static analysis.\n- **Excluded List \u0026 Wildcard FQDNs**: Automated protection for critical targets. Supports background resolution, wildcard patterns, and **External Dynamic Sources** (e.g. M365, AWS) with auto-refresh.\n- **Interactive API Docs**: Embedded **API Reference** via RapiDoc/Scalar at `/docs`.\n- **GeoIP Enrichment**: Automated ASN, Country, and City detection for all entries.\n- **Observability**: Prometheus metrics for latency and operations, protected by IP-based ACL.\n- **Hardened Deployment**: Non-root Docker images based on Alpine 3.21 with conditional `:latest` tagging.\n\n## 🛡️ Whitelist vs. Excluded List\n\nWhile both lists prevent an IP from being listed in the active blocklist, they serve distinct architectural purposes:\n\n### **Whitelist (Access Control)**\n*   **Purpose**: To explicitly grant access to the application itself and other **internal/protected resources**.\n*   **Scope**: Whitelisted IPs are considered \"Trusted\".\n*   **Behavior**: Prevents an IP from being blocked **AND** provides an identity/access signal for integration with other systems.\n*   **Usage**: Use this for your own office IPs, VPN gateways, or known safe customer IPs that need consistent access.\n\n### **Excluded List (Target Protection)**\n*   **Purpose**: To prevent **accidental blocking** of critical infrastructure or targets, regardless of their reputation.\n*   **Scope**: Excluded entities are \"untouchable\".\n*   **Behavior**: Only prevents the target from being blocked. It does **not** grant any special access or trust status.\n*   **Advanced Features**:\n    *   **External Dynamic Sources**: Subscribe to official IP/CIDR lists (e.g. [Microsoft 365](https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges), AWS, Cloudflare). Refreshes every 6 hours with failure fallback. Entries auto-expire after 24 hours if not refreshed.\n    *   **Proactive Alerting**: Optionally trigger **Webhook** or **Mail** alerts whenever an excluded resource is attempted to be blocked.\n    *   **FQDN Support**: Add `api.service.com` to prevent blocking any IP it currently resolves to.\n    *   **Wildcard FQDNs**: Support for `*.google.com` using Forward-Confirmed Reverse DNS (FCrDNS).\n*   **Usage**: Use this for critical third-party APIs (e.g., Stripe, AWS), search engine crawlers, or large CDN subnets where you want to ensure connectivity is never severed.\n\n## Project Structure\n- `cmd/server`: Go web server entry point, migrations, and static/template assets.\n- `internal/api`: HTTP handlers, middlewares (Auth, RBAC, Metrics), and WebSocket hub.\n- `internal/metrics`: Prometheus metrics definitions.\n- `internal/repository`: Redis and PostgreSQL data access layers.\n- `internal/service`: Core business logic (Auth, IP management, GeoIP, Webhooks, Dynamic Sources).\n\n## API Endpoints\n\n### Automated Webhooks\n- **`POST /api/v1/webhook`**: Authenticated webhook. Supports `ban`, `unban`, `unban-ip`, `whitelist`, and `selfwhitelist` actions.\n    - **Actions**:\n        - `ban`: Blocks an IP. Use `persist: true` for permanent storage.\n        - `unban` / `unban-ip`: Removes an IP from the blocklist.\n        - `whitelist`: Adds an IP to the whitelist.\n        - `selfwhitelist`: Whitelists the caller's source IP.\n    - **Parameters**: `ip`, `act`, `reason`, `persist` (bool), `ttl` (int).\n    - **Example (Block)**: `curl -X POST -H \"Authorization: Bearer YOUR_TOKEN\" -H \"Content-Type: application/json\" -d '{\"ip\":\"1.2.3.4\",\"act\":\"ban\",\"reason\":\"manual\",\"persist\":false,\"ttl\":3600}' http://localhost:5000/api/v1/webhook`\n    - **Example (Self-Whitelist)**: `curl -X POST -H \"Authorization: Bearer YOUR_TOKEN\" -H \"Content-Type: application/json\" -d '{\"act\":\"selfwhitelist\",\"reason\":\"homelab\"}' http://localhost:5000/api/v1/webhook`\n    - *Note: The `ip` parameter is required for all actions except `selfwhitelist`, where the system automatically detects your source IP via `X-Forwarded-For` or `CF-Connecting-IP`.*\n\n### Data \u0026 Stats\n*Note: Basic Authentication is supported as a fallback **ONLY** for whitelist endpoints. All other endpoints require a Bearer Token.*\n\n- **`GET /api/v1/ips`**: Paginated list of blocked IPs with advanced filters.\n- **`GET /api/v1/ips_list`**: Simple JSON array of all blocked IP addresses.\n- **`GET /api/v1/raw`**: Plain-text list of blocked IPs.\n- **`GET /api/v1/whitelists`**: Authenticated JSON list of all whitelisted IPs with metadata.\n- **`GET /api/v1/whitelists-raw`**: Authenticated plain-text, newline-separated list of whitelisted IPs.\n- **`GET /api/v1/ips/export`**: Export data in CSV or NDJSON format (Requires `export_data` permission and sudo).\n- **`GET /api/v1/stats`**: Aggregate statistics including top countries, ASNs, and reasons.\n\n## RBAC Roles\n\n| Role | Permissions |\n| :--- | :--- |\n| **Viewer** | View dashboard, search IPs, view stats, export data. |\n| **Operator** | All Viewer permissions + Block/Unblock IPs, manage Whitelist. |\n| **Admin** | All Operator permissions + Manage Admin accounts and API tokens. |\n\n## Quick Start (Development)\n\n1. **Configure Environment**: Set required variables in `.env`.\n2. **Start Dependencies**: Ensure Redis and PostgreSQL are running.\n3. **Run Migrations**: Handled automatically on server start.\n4. **Build \u0026 Run**:\n   ```bash\n   # Build Server\n   go build -o blocklist-server ./cmd/server/main.go\n   ./blocklist-server\n\n   # Build Standalone Worker (Optional)\n   go build -o blocklist-worker ./cmd/worker/main.go\n   ./blocklist-worker\n   ```\n\n## Docker Deployment\n- **Build**: `docker build -t blocklist:go .`\n- **Run**: `docker compose -f docker-compose.go.yml up -d`\n\n## Granular Permissions\n\nThe platform uses a detailed permission system for administrators:\n- **Monitoring**: `view_ips`, `view_stats`, `view_audit_logs`\n- **Enforcement**: `block_ips`, `unblock_ips`, `manage_whitelist`, `whitelist_ips`\n- **System**: `manage_webhooks`, `manage_api_tokens`, `manage_admins`, `manage_excluded`\n- **Utility**: `export_data`\n\n## Configuration\n\nThe application is configured via environment variables:\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `SECRET_KEY` | Key for session signing and encryption | `change-me` |\n| `PORT` | Listening port | `5000` |\n| `REDIS_HOST` | Redis server hostname | `localhost` |\n| `REDIS_PORT` | Redis server port | `6379` |\n| `REDIS_PASSWORD` | Redis password | (empty) |\n| `REDIS_DB` | Redis database for IP storage | `0` |\n| `POSTGRES_URL` | PostgreSQL connection string | `postgres://...` |\n| `GUIAdmin` | Primary administrator username | `admin` |\n| `GUIPassword` | Primary administrator password | (empty) |\n| `LOGWEB` | Enable verbose web logging (debug level) | `false` |\n| `BLOCKED_RANGES` | Comma-separated list of subnets to whitelist | (empty) |\n| `GEOIPUPDATE_LICENSE_KEY` | MaxMind License Key | (empty) |\n| `ENABLE_OUTBOUND_WEBHOOKS` | Master switch for outbound notifications | `false` |\n| `SMTP_HOST` | SMTP server for alerts | `\"\"` |\n| `SMTP_PORT` | SMTP port | `587` |\n| `SMTP_USER` | SMTP username | `\"\"` |\n| `SMTP_PASS` | SMTP password | `\"\"` |\n| `SMTP_FROM` | Sender address for alerts | `\"\"` |\n| `SMTP_TO` | Recipient address for alerts | `\"\"` |\n| `AUDIT_LOG_LIMIT_PER_IP` | Max audit trail entries kept per IP | `100` |\n| `LOG_RETENTION_MONTHS` | Number of months to retain logs | `6` |\n\n## Testing\nComprehensive unit, functional, and integration tests using `miniredis` and `testcontainers-go`.\n```bash\n# Run all tests\ngo test ./...\n```\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farumes31%2Fblocklist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farumes31%2Fblocklist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farumes31%2Fblocklist/lists"}