]> git.ipfire.org Git - dbl.git/commitdiff
exporters: Implement exporting Suricata rules
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Jan 2026 15:05:46 +0000 (15:05 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Jan 2026 15:05:46 +0000 (15:05 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/dnsbl/exporters.py
src/dnsbl/lists.py
src/scripts/dnsbl.in

index ef54366113aa2173090a9fd9475b72aad89526c4..90268022d11310653fd0f2ac357daf3e3143efee 100644 (file)
@@ -400,3 +400,117 @@ class CombinedSquidGuardExporter(object):
                        for list in self.lists:
                                exporter = SquidGuardExporter(self.backend, list)
                                exporter._write_list(tarball)
+
+
+class SuricataExporter(TextExporter):
+       """
+               Export domains as a set of rules for Suricata
+       """
+       @abc.abstractproperty
+       def sid_offset(self):
+               """
+                       The value that is being added to any SIDs
+               """
+               raise NotImplementedError
+
+       @abc.abstractproperty
+       def rule(self):
+               """
+                       The rule string
+               """
+               raise NotImplementedError
+
+       # Default rule revision
+       rev = 1
+
+       def export(self, f):
+               # Write the header
+               self.write_header(f)
+
+               # Write all domains
+               for domain in self.list.domains:
+                       args = {
+                               "list"   : "%s" % self.list,
+                               "domain" : domain.name,
+                               "sid"    : domain.id + self.sid_offset,
+                               "rev"    : self.rev,
+                       }
+
+                       # Write the rule
+                       f.write(self.rule % args)
+
+
+class SuricataDNSExporter(SuricataExporter):
+       """
+               Exports the lists as a Suricata ruleset that filters DNS queries.
+       """
+       sid_offset = 1000000000
+
+       rule = (
+               "alert dns any any -> any any ("
+               " msg:\"IPFire DNSBL [%(list)s] Blocked DNS Query for *.%(domain)s\";"
+               " dns.query; "
+               " content:\"%(domain)s\";"
+               " nocase;"
+               " endswith;"
+               " sid:%(sid)s;"
+               " rev:%(rev)s;"
+               ")\n"
+       )
+
+
+class SuricataHTTPExporter(SuricataExporter):
+       """
+               Exports the lists as a Suricata ruleset that filters HTTP requests.
+       """
+       sid_offset = 2000000000
+
+       rule = (
+               "alert dns any any -> any any ("
+               " msg:\"IPFire DNSBL [%(list)s] Blocked HTTP Request to *.%(domain)s\";"
+               " http.host;"
+               " content:\"%(domain)s\";"
+               " nocase;"
+               " endswith;"
+               " sid:%(sid)s;"
+               " rev:%(rev)s;"
+               ")\n"
+       )
+
+
+class SuricataTLSExporter(SuricataExporter):
+       """
+               Exports the lists as a Suricata ruleset that filters TLS connections.
+       """
+       sid_offset = 3000000000
+
+       rule = (
+               "alert dns any any -> any any ("
+               " msg:\"IPFire DNSBL [%(list)s] Blocked TLS SNI to *.%(domain)s\";"
+               " tls.sni;"
+               " content:\"%(domain)s\";"
+               " nocase;"
+               " endswith;"
+               " sid:%(sid)s;"
+               " rev:%(rev)s;"
+               ")\n"
+       )
+
+
+class SuricataQUICExporter(SuricataExporter):
+       """
+               Exports the lists as a Suricata ruleset that filters QUIC connections.
+       """
+       sid_offset = 4000000000
+
+       rule = (
+               "alert dns any any -> any any ("
+               " msg:\"IPFire DNSBL [%(list)s] Blocked QUIC SNI to *.%(domain)s\";"
+               " quic.sni;"
+               " content:\"%(domain)s\";"
+               " nocase;"
+               " endswith;"
+               " sid:%(sid)s;"
+               " rev:%(rev)s;"
+               ")\n"
+       )
index 3f81c4c20b5b668b0e2e34c6ecc57f65386f19d2..76b80faa2eeed20e9350f18f6596e61d84731402 100644 (file)
@@ -471,12 +471,18 @@ class List(sqlmodel.SQLModel, database.BackendMixin, table=True):
                        Exports the list
                """
                formats = {
-                       "abp"        : exporters.AdBlockPlusExporter,
-                       "domains"    : exporters.DomainsExporter,
-                       "dnsbl"      : exporters.BlocklistExporter,
-                       "hosts"      : exporters.HostsExporter,
-                       "rpz"        : exporters.RPZExporter,
-                       "squidguard" : exporters.SquidGuardExporter,
+                       "abp"           : exporters.AdBlockPlusExporter,
+                       "domains"       : exporters.DomainsExporter,
+                       "dnsbl"         : exporters.BlocklistExporter,
+                       "hosts"         : exporters.HostsExporter,
+                       "rpz"           : exporters.RPZExporter,
+                       "squidguard"    : exporters.SquidGuardExporter,
+
+                       # Suricata
+                       "suricata-dns"  : exporters.SuricataDNSExporter,
+                       "suricata-http" : exporters.SuricataHTTPExporter,
+                       "suricata-tls"  : exporters.SuricataTLSExporter,
+                       "suricata-quic" : exporters.SuricataQUICExporter,
                }
 
                # Fetch the exporter
index a5f8e6dfb6716e567dfd960079e60f6e6a1b40be..5c83db29dd1c539ef5dba6d03e71c45ef5636a83 100644 (file)
@@ -111,7 +111,8 @@ class CLI(object):
                export.add_argument("output", type=argparse.FileType("wb"),
                                help=_("The output file"))
                export.add_argument("--format", default="domains",
-                               choices=("abp", "domains", "dnsbl", "hosts", "rpz", "squidguard",),
+                               choices=("abp", "domains", "dnsbl", "hosts", "rpz", "squidguard",
+                                       "suricata-dns", "suricata-http", "suricata-tls", "suricata-quic"),
                                help=_("Output Format"))
                export.set_defaults(func=self.__export)
 
@@ -382,12 +383,18 @@ class CLI(object):
                        Exports all lists
                """
                formats = {
-                       "abp"        : "abp.txt",
-                       "domains"    : "domains.txt",
-                       "dnsbl"      : "dnsbl.zone",
-                       "hosts"      : "hosts.txt",
-                       "rpz"        : "rpz.zone",
-                       "squidguard" : "squidguard.tar.gz",
+                       "abp"           : "abp.txt",
+                       "domains"       : "domains.txt",
+                       "dnsbl"         : "dnsbl.zone",
+                       "hosts"         : "hosts.txt",
+                       "rpz"           : "rpz.zone",
+                       "squidguard"    : "squidguard.tar.gz",
+
+                       # Suricata
+                       "suricata-dns"  : "suricata-dns.rules",
+                       "suricata-http" : "suricata-http.rules",
+                       "suricata-tls"  : "suricata-tls.rules",
+                       "suricata-quic" : "suricata-quic.rules",
                }
 
                # Ensure the output directory exists