Intelligent firewall in Go
It integrates with Linux Netfilter via NFQUEUE, inspects inbound traffic in user space, and applies filtering to block malicious traffic in real-time. Once a connection is verified, Meds offloads it back to the kernel using Conntrack marks for maximum throughput.
Designed to cure your network from malicious traffic
Requirements:
- Linux with iptables + NFQUEUE + conntrack support
- Root privileges (
sudo) β required for interacting with Netfilter/Netlink
The application manages iptables and conntrack rules automatically.
Download the latest binary from Releases or build from sources.
go build -o meds ./cmd/daemonsudo MEDS_USERNAME=admin MEDS_PASSWORD=mypass ./meds
# Metrics available at: http://localhost:8000/metrics
# API available at: http://localhost:8000/swagger/index.html
# Basic Auth: admin / mypass./meds -help
Usage of ./meds:
-api-addr string
api server address (default ":8000")
-db-path string
path to database file (default "meds.db")
-log-level string
zerolog level (default "info")
-logger-queue-len uint
logger queue length (all workers) (default 2048)
-loggers-count uint
logger workers count (default 3)
-rate-limiter-burst uint
max packets at once (per ip) (default 1500)
-rate-limiter-cache-size uint
rate limiter cache size (all buckets) (default 100000)
-rate-limiter-cache-ttl duration
rate limiter cache ttl (per bucket) (default 3m0s)
-rate-limiter-rate uint
max packets per second (per ip) (default 3000)
-reader-queue-len uint
nfqueue queue length (per reader) (default 8192)
-readers-count uint
nfqueue readers count (default 12)
-update-interval duration
update frequency (default 4h0m0s)
-update-timeout duration
update timeout (per filter) (default 1m0s)
-workers-count uint
nfqueue workers count (per reader) (default 1)
π http://localhost:8000/metrics
The metrics endpoint is protected by the same BasicAuth credentials as the API.
Interactive API docs:
π http://localhost:8000/swagger/index.html
You can browse and test all API endpoints directly from your browser.
OpenAPI spec (JSON):
π http://localhost:8000/swagger/doc.json
You can import this spec into Postman, Insomnia, or Hoppscotch.
PACKET
β
βββββββββββββββββββββββΌββββββββββββββββββββββ
β KERNEL SPACE (Netfilter / Mangle) β
β βββββββββββββββββββββββββββββββββββββββββ β
β [Restore Connmark] βββΊ [Already Marked?] ββΌβββ
βββββββββββββββββββββββ¬ββββββββββββββββββββββ β
β No (Slow Path) β Yes
βββββββββββββββββββββΌββββββββββββββββββββ β (Fast Path)
β USER SPACE (Meds Firewall) β β
β βββββββββββββββββββββββββββββββββββββ β β
β 1. Global IP Whitelist β β
β 2. Rate Limiter (per source IP) β β
β 3. Global IP Blacklist β β
β 4. IP Filters β β
β 5. Geo Filters β β
β 6. ASN Filters β β
β 7. Global Domain/SNI Whitelist β β
β 8. Global Domain/SNI Blacklist β β
β 9. Domain/SNI Filters β β
β 10. TLS JA3 Filters β β
ββββββββββββββββββββ¬βββββββββββββββββββββ β
β β
ββββββββββββββββββββΌβββββββββββββββββββββ β
β DECISION ENGINE β β
β βββββββββββββββββββββββββββββββββββββ β β
β [DROP] βββΊ Discard packet β β
β [ACCEPT] βββΊ Pass once ββΌβββ β
β [MARK] βββΊ Set Connmark + ACCEPT ββΌβββ€ β
βββββββββββββββββββββββββββββββββββββββββ β β
βΌ βΌ
TRAFFIC ALLOWED
-
Hybrid Traffic Flow
Meds optimizes traffic by splitting it into two paths:- Fast Path (Kernel): packets belonging to established/trusted connections (marked via
CONNMARK) are processed entirely by the Linux kernel. - Inspection Path (User Space): new or unmarked packets are sent to Meds via NFQUEUE.
- Fast Path (Kernel): packets belonging to established/trusted connections (marked via
-
Classification pipeline
Packets are processed according to the following pipeline:- Global IP Whitelist β immediate pass for trusted source IPs
- Rate Limiter β protects system resources by limiting packet rate per source IP
- Global IP Blacklist β immediate block for malicious source IPs
- IP Filters β applies granular IP-based filtering rules
- Geo Filters β filters traffic by country of origin using ASN metadata
- ASN Filters β checks Autonomous System reputation against blacklists
- Global Domain/SNI Whitelist β permits trusted domains extracted from DNS or TLS SNI
- Global Domain/SNI Blacklist β blocks malicious domains from DNS or TLS SNI
- Domain/SNI Filters β applies granular domain-based filtering rules
- TLS JA3 Filters β detects malicious clients via TLS fingerprinting
-
Decision engine
- DROP β packet is malicious, discarded immediately
- MARK β marks the connection as trusted in the kernel via Conntrack for wire-speed handling
- ACCEPT β packet is safe, passed to kernel stack
-
Metrics & logging
Every decision is counted and exported for monitoring and alerting.
Metrics are Prometheus-compatible and can be visualized in Grafana.
All events are asynchronously logged to minimize packet processing latency.
-
NFQUEUE-based packet interception
Uses Linux Netfilter queues to copy inbound packets into user space with minimal overhead, only for the "Decision Phase" of a connection. -
Hybrid Processing (Conntrack Acceleration)
Uses Conntrack marks to offload trusted connections. Once a flow is validated in user space, it is marked in the kernel's connection tracking table. Subsequent packets of that flow stay in the kernel, achieving wire-speed performance. -
Lock-free core
Meds itself does not use any mutexes β all filtering, counters, and rate-limiters use atomic operations. -
Decoupled reader / worker / logger model
- Readers drain NFQUEUE as fast as possible
- Workers perform CPU-intensive filtering
- Logger uses zerolog with async worker-based logging
-
Fast packet parsing with gopacket
Parses traffic efficiently (lazyandno copymodes enabled). -
Efficient lookups
Uses radix tree and bart for IP/domain matching at scale. -
Rate Limiting per IP
Uses token bucket algorithm to limit burst and sustained traffic per source IP.
Protects against high-frequency floods (SYN, DNS, ICMP, or generic packet floods). -
Blacklist-based filtering
- IP blacklists: FireHOL, Spamhaus DROP, Abuse.ch
- ASN blacklists: Spamhaus ASN DROP using IPLocate.io for IP-to-ASN mapping
- Domain blacklists: StevenBlack hosts, SomeoneWhoCares hosts
-
Geo-blocking (ASN-based)
Efficiently blocks traffic from specific countries using ASN metadata from IPLocate.io:- Lightweight alternative to heavy GeoIP databases
- Dynamic configuration via API/Swagger
-
TLS SNI & JA3 filtering
Extracts and inspects TLS ClientHello data directly from TCP payload before handshake completion:- Filters by SNI (domain in TLS handshake)
- Filters by JA3 fingerprint using the Abuse.ch SSLBL JA3 database
Enables real-time blocking of malicious TLS clients such as malware beacons, scanners, or C2 frameworks.
-
HTTP API for runtime configuration
Built-in API server (powered by Gin) allows dynamically adding or removing IP, Domain, or Country entries in global white/black lists.
Auth via BasicAuth usingMEDS_USERNAME/MEDS_PASSWORD. -
Prometheus metrics export
Exposes metrics for observability:- Total packets processed
- Dropped packets (with reasons)
- Accepted packets (with reasons)
- Internal errors (with types)
Metrics are available at
/metricsvia the built-in API server, compatible with Prometheus scrape targets. -
Extensible design
Modular architecture allows adding new filters.
# HELP meds_core_connections_trusted_total Total number of trusted connections
# TYPE meds_core_connections_trusted_total counter
meds_core_connections_trusted_total{reason="trusted packet"} 2843
# HELP meds_core_packets_accepted_total Total number of accepted packets
# TYPE meds_core_packets_accepted_total counter
meds_core_packets_accepted_total{filter="empty",reason="default"} 20832
meds_core_packets_accepted_total{filter="ip",reason="WhiteList"} 668
# HELP meds_core_packets_dropped_total Total number of dropped packets
# TYPE meds_core_packets_dropped_total counter
meds_core_packets_dropped_total{filter="asn",reason="Spamhaus"} 130
meds_core_packets_dropped_total{filter="geo",reason="IPLocate"} 22
meds_core_packets_dropped_total{filter="ip",reason="FireHOL"} 7980
meds_core_packets_dropped_total{filter="rate",reason="Limiter"} 11
# HELP meds_core_packets_processed_total Total number of processed packets
# TYPE meds_core_packets_processed_total counter
meds_core_packets_processed_total 29653
Meds is released under the MIT License.
See LICENSE for details.
Pull requests and feature suggestions are welcome!
If you find a bug, please open an issue or submit a fix.
Made with β€οΈ in Go