Blacked is a high-performance blacklist aggregator and query service built in Go. It efficiently collects blacklist data from various online sources, stores it using modern caching techniques, and provides blazing-fast query capabilities via both CLI and Web API interfaces.
|
Automatically fetches data from multiple blacklist sources including OISD, URLHaus, OpenPhish, and PhishTank with an extensible provider system for easy additions. |
Uses Bloom filters for ultra-fast negative lookups and BadgerDB for optimized key-value storage, ensuring millisecond-level response times. |
|
Supports multiple query types (exact URL, host, domain, path) with an intelligent cascading query strategy for comprehensive results. |
Includes Prometheus metrics endpoints and performance benchmarking tools to monitor and optimize your deployment. |
- Go 1.24 or higher
- Git
# Clone the repository
git clone https://github.com/runaho/blacked.git
cd blacked
# Download dependencies
go mod download
# Configure the application
# Either copy the example config or create a new one
cp .env.toml.example .env.toml
# Edit according to your needsBlacked is configured via a .env.toml file in the project root. You can also use a .env file or environment variables.
[APP]
environment = "development" # or "production"
log_level = "info" # debug, info, warn, error
ttl = "10m" # Time to live for cache entries default is 5m if not set everything is cached to forever
[Server]
port = 8082
host = "localhost"
[Cache]
# For persistent storage:
# badger_path = "./badger_cache"
in_memory = true # Use in-memory BadgerDB
use_bloom = true # Enable Bloom filter for faster lookups
[Provider]
# Optionally limit enabled providers
# enabled_providers = ["OISD_BIG", "URLHAUS"]
# Override default schedules if needed
# [Provider.provider_crons]
# OISD_BIG = "0 7 * * *" # Run OISD at 7 AM UTC# Start the web server and scheduler
go run . serve
# Or with the built binary
./blacked serveThe server will start on http://localhost:8082 by default (configurable in .env.toml).
Blacked includes a robust CLI for direct interaction:
# Process all providers immediately
go run . process
# Process specific providers only
go run . process --provider OISD_BIG --provider URLHAUS
# Query if a URL is blacklisted
go run main.go query --url "http://suspicious-site.com/path"
# Query with specific match type
go run main.go query --url "suspicious-site.com" --type domain
# Get query results as JSON
go run main.go query --url "http://suspicious-site.com" --json
# Get detailed help
go run main.go --helpBlacked provides a comprehensive REST API for integration:
| Endpoint | Method | Description | Example |
|---|---|---|---|
/entry |
GET | Quick check if a URL is blacklisted | /entry?url=example.com |
/entry/likely |
GET | Bloom check return 404 or 200 | /entry/likely?url=example.com |
/entry/{id} |
GET | Get details for a specific entry by ID | /entry/550e8400-e29b-41d4-a716-446655440000 |
/entry/search |
POST | Advanced search with query options | {"url": "example.com", "query_type": "domain"} |
/provider/process |
POST | Trigger provider processing | {"providers_to_process": ["URLHAUS"]} |
/benchmark/query |
POST | Benchmark query performance | {"urls": ["example.com"], "iterations": 100} |
# Check if a URL is blacklisted (fast path)
curl "http://localhost:8082/entry?url=http%3A%2F%2Fsuspicious-site.com"
# Comprehensive search
curl -X POST -H "Content-Type: application/json" \
-d '{"url": "suspicious-site.com", "query_type": "domain"}' \
http://localhost:8082/entry/search
# Trigger processing for specific providers
curl -X POST -H "Content-Type: application/json" \
-d '{"providers_to_process": ["URLHAUS", "PHISHTANK"]}' \
http://localhost:8082/provider/processAdding a new blacklist provider is straightforward:
- Create a new directory for your provider:
features/providers/myprovider/ - Implement the provider interface:
package myprovider
func NewMyProvider(settings *config.CollectorConfig, collyClient *colly.Collector) base.Provider {
const (
providerName = "MY_PROVIDER"
providerURL = "https://example.com/blacklist.txt"
cronSchedule = "0 */6 * * *" // Every 6 hours
)
// Define how to parse provider data
parseFunc := func(data io.Reader, collector entry_collector.Collector) error {
// Parse the data format specific to this provider
// Submit entries.Entry to collector
//
collector.Submit(*entry)
}
// Create and register the provider
provider := base.NewBaseProvider(
providerName,
providerURL,
settings,
collyClient,
parseFunc,
)
provider.
SetCronSchedule(cronSchedule).
Register()
return provider
}- Add your provider to
features/providers/main.go:
func getProviders(cfg *config.Config, cc *colly.Collector) Providers {
oisd.NewOISDBigProvider(&cfg.Collector, cc)
/* ... */
// Add your new provider here
/* ... */
providers := Providers(base.GetRegisteredProviders())
return providers
}docker build -t blacked:latest .
docker run -d --name blacked -p 8082:8082 \
-v $(pwd)/data:/app/data \
-v $(pwd)/.env.toml:/app/.env.toml \
blacked:latestContributions are welcome! Please feel free to submit pull requests or open issues.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a pull request
This project is licensed under the MIT License - see the LICENSE file for details.