I tried to find ways to do a wildcard based whitelist for HTTPS traffic, but I ended up getting results for only HTTP connections that were based on the transparent proxy setup. The proxy doesn't work for HTTPS connections and I could not find any more relevant sources on how to manage to do what I needed to do. The firewall address-lists work only for specific hosts that can be directly resolved, while I needed to allow wildcard domains to comply with the specification. So, here is my take on how to whitelist only the specific HTTPS hosts while fully supporting wildcard matching.
Pros:
- An actual wildcard matching support for HTTPS
- Should not be too resource intensive for established connections
- Does exactly what is needed in the perspective of the end user (everything but whitelisted things are blocked)
- It doesn't protect from targeted data exfiltration as some packets have to be let through to facilitate the SNI matching (this bit could probably be made better)
- Bit of a hack, and might be hard to wrap your head around. You have been warned.
Please contribute any ideas on how to make this better & more secure.
Code: Select all
/ip firewall filter
add action=drop chain=forward comment="Drop invalid connections" connection-state=invalid protocol=tcp
add action=accept chain=forward comment="Accept Established & related connections but HTTPS" connection-state=established,related packet-mark=no-mark
add action=accept chain=forward comment="Allow established HTTPS connections flagged as good by FW" connection-state=established,related packet-mark=allow-https
add action=jump chain=forward comment="Catch marked HTTPS packets for SNI inspection" jump-target=forward-https packet-mark=https
add action=reject chain=forward comment="Reset HTTPS connections that were not allowed" packet-mark=bad-https protocol=tcp reject-with=tcp-reset
# Following is the list of tls hosts allowed
add action=add-dst-to-address-list address-list=allow-https address-list-timeout=5s chain=forward-https comment="Allow Google" protocol=tcp tls-host=*.google.com
add action=add-dst-to-address-list address-list=allow-https address-list-timeout=5s chain=forward-https comment="Allow Google" protocol=tcp tls-host=*.googleusercontent.com
add action=add-dst-to-address-list address-list=allow-https address-list-timeout=5s chain=forward-https comment="Allow Google" protocol=tcp tls-host=*.gstatic.com
# We will have to allow the rest of the packets through at this stage from this matcher chain
add action=accept chain=forward-https port=443 protocol=tcp
/ip firewall mangle
add action=mark-connection chain=prerouting comment="Mark checked & allowed HTTPS connections" dst-address-list=allow-https dst-port=443 new-connection-mark=allow-https passthrough=yes protocol=tcp
add action=mark-packet chain=prerouting comment="Mark packets that are part of allowed HTTPS connections" connection-mark=allow-https new-packet-mark=allow-https passthrough=no
# Next we match the new HTTPS connections & mark packets that were not yet cleared by the matcher in the forward-https chain
add action=mark-connection chain=prerouting comment="Mark HTTPS connections" connection-state=new dst-port=443 new-connection-mark=https protocol=tcp
add action=mark-packet chain=prerouting comment="Mark HTTPS packets based on connection mark and only allow few through per connection" connection-mark=https dst-limit=1/1m,6,addresses-and-dst-port/1m new-packet-mark=https passthrough=no
# The rest of the HTTPS traffic must get flagged evil and shall not pass. The connections will be reset by the rule in fw filter.
add action=mark-connection chain=prerouting comment="Mark HTTPS connections bad after few packets have passed, if it was not marked good by previous rules" dst-port=443 log=yes log-prefix=BAD-HTTPS \
new-connection-mark=bad-https protocol=tcp
add action=mark-packet chain=prerouting comment="Mark HTTPS packets bad by the bad-https connection mark" connection-mark=bad-https new-packet-mark=bad-https passthrough=no
So there. The basic idea goes like this:
- Match all new HTTPS connections and mark the connection
- Mark packets that are part of a specific connection until a limit is reached
- Match those marked packets in the filter for desired tls-hosts
- Add the IP addresses of the matched tls-hosts to an address list
- Use the address list to override the previous connection mark with a mark that tells that the connection is good
- Mark packets of the good connections
- Allow the good packets through for established connections
- The connections that didn't get flagged by the tls-host filter will reach the packet count limit and pass the rule
- The next rule is for marking a connection as bad https connection
- Mark packets bad based on the connection mark
- Reset the connections on filter based on packet mark
I hope this helps out someone, and that I didn't forget to paste any relevant lines.
~Jassu