# RouterOS Suricata TZSP - built-in rules. # # SID 1000001 is reserved for the deterministic pipeline self-test. It only # matches the marker emitted by scripts/send_test_tzsp.py, so normal ICMP/ping # traffic cannot trigger it. The application also ignores this SID in the # incident database by default. alert icmp any any -> any any (msg:"LOCAL TEST TZSP PIPELINE MARKER"; itype:8; content:"routeros-suricata-tzsp-selftest"; nocase; classtype:misc-activity; priority:3; sid:1000001; rev:3;) # Conservative production baseline. ET/Open is baked into the image as the # vendor ruleset; these local rules add a few rate-based detections that are # useful on a mirrored RouterOS edge without alerting on single packets. # Repeated external SSH connection attempts against HOME_NET. alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"LOCAL PROD repeated SSH connection attempts"; flags:S; flow:stateless; threshold: type both, track by_src, count 10, seconds 60; classtype:attempted-admin; priority:1; sid:1000101; rev:1;) # Repeated external RDP connection attempts against HOME_NET. alert tcp $EXTERNAL_NET any -> $HOME_NET 3389 (msg:"LOCAL PROD repeated RDP connection attempts"; flags:S; flow:stateless; threshold: type both, track by_src, count 8, seconds 60; classtype:attempted-admin; priority:1; sid:1000102; rev:1;) # Repeated access attempts to RouterOS WinBox from outside HOME_NET. alert tcp $EXTERNAL_NET any -> $HOME_NET 8291 (msg:"LOCAL PROD repeated RouterOS WinBox connection attempts"; flags:S; flow:stateless; threshold: type both, track by_src, count 8, seconds 60; classtype:attempted-admin; priority:1; sid:1000103; rev:1;) # High-rate SYN activity against HOME_NET. The threshold intentionally requires # a burst to avoid treating ordinary connection setup as a scan. alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"LOCAL PROD possible TCP SYN scan"; flags:S; flow:stateless; threshold: type both, track by_src, count 40, seconds 10; classtype:attempted-recon; priority:2; sid:1000104; rev:1;) # High-rate ICMP echo requests from one external source. alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"LOCAL PROD possible ICMP sweep"; itype:8; threshold: type both, track by_src, count 20, seconds 10; classtype:attempted-recon; priority:2; sid:1000105; rev:1;) # Direct inbound SMB from outside HOME_NET. Rate-limited because some networks # intentionally expose SMB over controlled tunnels or provider networks. alert tcp $EXTERNAL_NET any -> $HOME_NET [139,445] (msg:"LOCAL PROD inbound SMB from external network"; flags:S; flow:stateless; threshold: type limit, track by_src, count 1, seconds 300; classtype:policy-violation; priority:2; sid:1000106; rev:1;) # Very long first DNS labels can be a tunnelling/exfiltration signal. A single # source can create at most one alert every five minutes for this local rule. alert dns $HOME_NET any -> any 53 (msg:"LOCAL PROD unusually long DNS query label"; dns.query; pcre:"/^[A-Za-z0-9_-]{48,}\./"; threshold: type limit, track by_src, count 1, seconds 300; classtype:bad-unknown; priority:2; sid:1000107; rev:1;) # Cleartext Telnet leaving HOME_NET. One alert per source every ten minutes. alert tcp $HOME_NET any -> $EXTERNAL_NET 23 (msg:"LOCAL PROD outbound Telnet session"; flow:established,to_server; threshold: type limit, track by_src, count 1, seconds 600; classtype:policy-violation; priority:2; sid:1000108; rev:1;) # Repeated NXDOMAIN replies to a HOME_NET client. This can indicate DGA-style # beaconing, typo storms or broken/malicious name generation. The threshold is # intentionally high enough to avoid alerting on isolated failed lookups. alert dns any any -> $HOME_NET any (msg:"LOCAL PROD repeated DNS NXDOMAIN responses"; dns.rcode:NXDOMAIN; threshold: type both, track by_dst, count 30, seconds 60; classtype:bad-unknown; priority:2; sid:1000109; rev:1;) # High-rate DNS queries from one HOME_NET source. Combined with the long-label # rule this adds a rate signal for tunnelling, DGA and resolver abuse. alert dns $HOME_NET any -> any 53 (msg:"LOCAL PROD high-rate DNS query activity"; dns.query; pcre:"/.+/"; threshold: type both, track by_src, count 120, seconds 60; classtype:bad-unknown; priority:2; sid:1000110; rev:1;) # SMB should normally stay inside trusted networks or explicit tunnels. Direct # Internet SMB is a strong policy signal and is rate-limited per source. alert tcp $HOME_NET any -> $EXTERNAL_NET 445 (msg:"LOCAL PROD outbound SMB to external network"; flags:S; flow:stateless; threshold: type limit, track by_src, count 1, seconds 600; classtype:policy-violation; priority:1; sid:1000111; rev:1;) # Direct SMTP from endpoints is frequently associated with compromised hosts. # Mail relays can suppress this SID or scope it with threshold.config. alert tcp $HOME_NET any -> $EXTERNAL_NET 25 (msg:"LOCAL PROD direct outbound SMTP"; flags:S; flow:stateless; threshold: type limit, track by_src, count 1, seconds 600; classtype:policy-violation; priority:2; sid:1000112; rev:1;) # Cleartext FTP leaving HOME_NET. Kept as a policy alert rather than an automatic # block because legacy infrastructure may still require it. alert tcp $HOME_NET any -> $EXTERNAL_NET 21 (msg:"LOCAL PROD outbound cleartext FTP"; flags:S; flow:to_server,stateless; threshold: type limit, track by_src, count 1, seconds 600; classtype:policy-violation; priority:2; sid:1000113; rev:2;) # Common database/search service ports should not normally be reachable directly # from the Internet. This detects exposure/probing without alerting on every SYN. alert tcp $EXTERNAL_NET any -> $HOME_NET [3306,5432,6379,9200,27017] (msg:"LOCAL PROD external access to database service"; flags:S; flow:stateless; threshold: type limit, track by_src, count 1, seconds 300; classtype:attempted-admin; priority:1; sid:1000114; rev:1;) # Burst of administrative/lateral-movement connection attempts inside HOME_NET. # Normal single RDP/SMB sessions do not trigger this rule. alert tcp $HOME_NET any -> $HOME_NET [445,3389] (msg:"LOCAL PROD possible internal lateral movement burst"; flags:S; flow:stateless; threshold: type both, track by_src, count 40, seconds 30; classtype:attempted-admin; priority:1; sid:1000115; rev:1;) # Multi-stage state tracking with Suricata 8 xbits. A scan burst marks the # source for ten minutes; a later hit on an administrative service becomes a # higher-confidence correlated alert instead of treating both events in isolation. alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"LOCAL NDR mark external scanner"; flags:S; flow:stateless; threshold: type threshold, track by_src, count 30, seconds 10; xbits:set,ms_ext_scanner,track ip_src,expire 600; noalert; sid:1000120; rev:1;) alert tcp $EXTERNAL_NET any -> $HOME_NET [22,445,3389,8291] (msg:"LOCAL NDR scan followed by administrative service access"; flags:S; flow:stateless; xbits:isset,ms_ext_scanner,track ip_src; threshold: type limit, track by_src, count 1, seconds 300; classtype:attempted-admin; priority:1; sid:1000121; rev:1;) # The same idea for east-west traffic. This is deliberately burst-based so a # normal single SMB/RDP/SSH connection does not mark a workstation. alert tcp $HOME_NET any -> $HOME_NET any (msg:"LOCAL NDR mark internal lateral probe"; flags:S; flow:stateless; threshold: type threshold, track by_src, count 35, seconds 20; xbits:set,ms_lateral_probe,track ip_src,expire 900; noalert; sid:1000122; rev:1;) alert tcp $HOME_NET any -> $HOME_NET [22,445,3389,5985,5986,8291] (msg:"LOCAL NDR lateral probe followed by administrative access"; flags:S; flow:stateless; xbits:isset,ms_lateral_probe,track ip_src; threshold: type limit, track by_src, count 1, seconds 300; classtype:attempted-admin; priority:1; sid:1000123; rev:1;) # RouterOS API/API-SSL should normally be restricted to trusted administration # networks. Repeated Internet connection attempts are a MikroTik-specific # management-plane signal similar to WinBox probing. alert tcp $EXTERNAL_NET any -> $HOME_NET [8728,8729] (msg:"LOCAL PROD repeated RouterOS API connection attempts"; flags:S; flow:stateless; threshold: type both, track by_src, count 8, seconds 60; classtype:attempted-admin; priority:1; sid:1000116; rev:1;)