Understanding tls.sni rules

Apologies for what I have little doubt is a Suricata-newbie issue, but I’m trying to understand how I can control https traffic to specific domains. So to test, I have a single rule: -
drop tls $HOME_NET any → $EXTERNAL_NET any (msg:“drop google”; tls.sni; dotprefix; content:".google.com"; nocase; endswith; sid:1; rev:1;)

…which should allow everything through, except a TLS handshake to *.google.com, correct? Except this doesn’t seem to work and all traffic is allowed through, including curls to www.google.com. In fact if I try dropping all tls (i.e. with a drop tls rule without tls.sni keyword) it doesn’t block either.

I’m running Suricata 5.0.6 on Centos 8, running in inline IPS mode. I have confidence that traffic is directed correctly to the engine, because I can successfully control traffic through Suricata at the TCP or UDP level.

Any help, gratefully received.

Ok, I appear to have solved this. If anyone’s interested I changed my suricata config to use nfq mode: accept as opposed to repeat

When set to repeat it didn’t look like suricata was doing any parsing beyond the tcp level. The reason for this is opaque to me I have to admit, but if anyone stumbles across a similar issue, then I suppose this may help.

Hi, mr.Prys
I’ve same this issue if you have found out any solution pls, suggest me.
I’ve written suricata rule set as following

pass tls [10.122.xxx.64/27,10.122.xxx.128/27] any → $EXTERNAL_NET 443 (tls.sni; dotprefix; content:“.amazonaws.com”; nocase; endswith; msg:“TLS Allowlisted access to sts.amazonaws.com”; flow:to_server, established; sid:1; rev:1;)

drop tcp [10.122.xxx.64/27,10.122.xxx.128/27] any → $EXTERNAL_NET any (msg:“Not matching any TLS allowlisted FQDNs”; flow:to_server, established; sid:2; rev:1;)

I wanna to allow only “sts.amazonaws.com =.amazonaws.com by https (tls)” only otherwise i will be droped it all.
pls, recommended me with Thanks.

Hi Akira0098,

I am not an expert on Suricata rules by any means so please read my reply and ‘handle with care’!

From what I can see, the issue you will have is that your TCP drop rule will drop everything at the TCP level, so you’re TLS.SNI rule will never be processed.

What I think you can do is first drop all TCP traffic apart from port 443:-

drop tcp $HOME_NET any -> $EXTERNAL_NET ![443] (msg:"default drop"; sid:1; rev:1;)

Then default drop everything at the TLS-level

drop tls $HOME_NET any -> $EXTERNAL_NET any (msg:"default tls drop"; sid:2; rev:1;)

And finally, then allow the domains you specify: -

pass tls $HOME_NET any -> $EXTERNAL_NET any (msg:"allow this domain"; tls.sni; dotprefix; content:".amazonaws.com"; nocase; endswith; sid:4; rev:1;)

I realise this will actually allow all non-TLS traffic on port 443 to any destination, but I’m not sure how you would work around that other than by being specific about destination IP addresses at the TCP-level. I realise that with cloud api such as Amazon’s STS that could means allowing traffic to a wide range of CIDRs. That could be coded and update automatically based on rss-feeds and so on.

Hope this helps

Prys

Hi K.Prys,
Thank you for you help. I will try it.