AWS Network Firewall Stateful (Suricata) rules not working - Pass TLS only

use-case: Only allow TLS traffic outbound to internet (port 443) to specific domain, prevent any other traffic for any protocol on port 443, meaning protocols that don’t use TLS. This could be FTP, Telnet, HTTP (without ‘S’), RCP etc.

configured rules
pass tls $HOME_NET any → $EXTERNAL_NET 443 (tls.sni; dotprefix; content:“.amazonaws.com”; nocase; endswith; msg:“matching TLS allowlisted FQDNs”; priority:1; flow:to_server, established; sid:1; rev:1;)

drop tls $HOME_NET any → $EXTERNAL_NET 443 (msg:“TLS not matching any allowlisted FQDNs”; priority:1; flow:to_server, established; sid:2; rev:1;)

drop tcp $HOME_NET any → $EXTERNAL_NET 443 (msg:“TCP not matching any allowlisted FQDNs”; priority:2; flow:to_server, established; sid:3; rev:1;)

behavior - TLS to allowed domain works, TLS to non-allowed domains is blocked. telnet works to any public IP on 443

expected behavior - TLS to allowed domain works, TLS to non-allowed domains is blocked. TCP 443 using any non-TLS higher protocol should be blocked

Please help if this is possible to be configured in Suricata and how ?

Hi @firewall !
Welcome to our forum. :slight_smile:

I don’t have a setup to test but could you please try modifying your third rule to include app-layer-protocol:!tls; and see if that helps your case? ref: 8.35. Generic App Layer Keywords — Suricata 7.0.1-dev documentation

@sbhardwaj - Tried the above, same results. Telnet still works. Any other way this can be done ?

While I can’t test directly on AWS, this works for me locally:

pass tls any any -> any any (msg:"PASS TLS on port 443"; tls.sni; dotprefix; content:"suricata.io"; flow:to_server,established; sid:1000000;)
drop tcp any any -> any 443 (msg:"DROP NON TLS on port 443"; flow:to_server,established; sid:1000001;)

How did you test?

I can use curl, Chrome, etc to get to https://suricata.io, or https://forum.suricata.io. I can-not however telnet to anything over port 443. My test was nc -l 443 running on a remote host and trying to telnet/nc to it. The connection does get etablished, but no data sent from the client is received by the server.

@ish - I tested just with telnet to a public IP on port 443 (did not test data part), is there a way in Suricata to block this standalone TCP handshake too, while only allowing TCP that is part of TLS ?

No, that is not possible with Suricata. The TCP session needs to be established before the TLS session starts its establishment process.