import datetime
import io
import tarfile
+import zlib
from . import util
from .i18n import _
"""
Export domains as a set of rules for Suricata
"""
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # Cache any used SIDs
+ self._used_sids = set()
+
@abc.abstractproperty
- def sid_offset(self):
+ def sid_prefix(self):
"""
The value that is being added to any SIDs
"""
for domain in self.list.domains:
args = {
"list" : "%s" % self.list,
- "domain" : domain.name,
- "sid" : domain.id + self.sid_offset,
+ "domain" : domain,
+ "sid" : self.compute_sid(domain),
"rev" : self.rev,
}
# Write the rule
f.write(self.rule % args)
+ def compute_sid(self, domain):
+ """
+ Implements a simple hash function for a domain.
+
+ The hash can only use up to
+ """
+ # Convert the domain into bytes()
+ domain = domain.encode()
+
+ # Compute the CRC32 checksum
+ h = zlib.crc32(domain)
+
+ # Truncate to make space for the prefix
+ h %= 0x0fffffff
+
+ # Add the prefix
+ h |= self.sid_prefix
+
+ # Check if we have a collision, if so, increment the hash by one
+ while h in self._used_sids:
+ h += 1
+
+ # Store the hash for the next collision check
+ self._used_sids.add(h)
+
+ return h
+
class SuricataDNSExporter(SuricataExporter):
"""
Exports the lists as a Suricata ruleset that filters DNS queries.
"""
- sid_offset = 1000000000
+ sid_prefix = 0x10000000
rule = (
"alert dns any any -> any any ("
"""
Exports the lists as a Suricata ruleset that filters HTTP requests.
"""
- sid_offset = 2000000000
+ sid_prefix = 0x20000000
rule = (
"alert dns any any -> any any ("
"""
Exports the lists as a Suricata ruleset that filters TLS connections.
"""
- sid_offset = 3000000000
+ sid_prefix = 0x30000000
rule = (
"alert dns any any -> any any ("
"""
Exports the lists as a Suricata ruleset that filters QUIC connections.
"""
- sid_offset = 4000000000
+ sid_prefix = 0x40000000
rule = (
"alert dns any any -> any any ("