"TLS Host" option doesn't work

SYN →
← ACK SYN
ACK →
DATA →
the 4th packet contains the setup of TLS but I am not sure if that immediately contains the TLS Host or if that is even later in the exchange.

you would have to reject that packet with a TCP RST reply and also add the destination address to your address list.
that still means the other end of the connection (the server at Microsoft/Apple) has a half-open session that it has to time out.

TCP do not “send” packets like UDP.
TCP instaurate a connection between two device then send packet between devices
Only firsk 4k (?) of the connection are “visible” on layer 7 / TLS host (not 1.3+) the rest are “extabilished” connection.
The firewall with connection-tracking make the connection alive, if NAT is used, also if you change routing or NAT rules.
The next route are taken on next new TCP connection…


edit underlned part

So, here’s a new plan: Match TLS hosts and the action is to jump to a custom chain. This custom chain has rules that simply add both the source and destination to address lists. Later in the prerouting chain, have a rule that matches these address lists and marks routes as going to the VPN.

I already added the destination address to the address list, but I can’t think of a good way to send a TCP RST. Is there some feature or hack in ROS that can do this?

In a filter rule configured for protocol tcp, you can reject a packet with tcp rst.

Does this setup look good?

/ip firewall mangle
add action=jump chain=prerouting comment=*xbox*.com dst-port=80,443 jump-target=tls protocol=tcp tls-host=*xbox*.com
add action=jump chain=prerouting comment=*a-msedge.net dst-port=80,443 jump-target=tls protocol=tcp tls-host=*a-msedge.net
add action=return chain=tls comment="return packets if the hosts are already marked" dst-address-list=tls_dst_host src-address-list=tls_src_host
add action=add-src-to-address-list address-list=tls_src_host address-list-timeout=10m chain=tls
add action=add-dst-to-address-list address-list=tls_dst_host address-list-timeout=10m chain=tls
add action=mark-connection chain=tls new-connection-mark=tls_disconnect passthrough=yes
add action=return chain=tls
add action=mark-routing chain=prerouting dst-address-list=tls_dst_host new-routing-mark=vpn passthrough=no src-address-list=tls_src_host



/ip firewall filter
add action=reject chain=forward comment="reset tcp connections which have just been marked with tls" connection-mark=tls_disconnect protocol=tcp reject-with=tcp-reset

Why should I do it in three steps? If I just mark the connection then mark all the connection's packets, then that's simpler. Also, I noticed in the Mik Wiki they included connection-state=new in the rules that are similar to this. Should I include that as well?

Sorry to reply to an old thread but I found this a while back that has taken care of most of the DoH and DoT issues:

I Also block QUIC and the standard DoT port 853:

add action=drop chain=forward comment="Block QUIC" dst-port=80,443 protocol=udp
add action=drop chain=forward comment="Block DoT DNS"  dst-port=853 protocol=tcp

Here is a small config example that will only allow a host to communicate with windows update filtering on SNI and works with TLS1.2/1.3 (when SNI is not encrypted).

Note: On a CHR the Layer7 rule is enforced only on some frames and others are missed. Still trying to sort out what the issue is. But if you duplicate the mangle entry that uses the L7 rule you will see hits on both, even though passthrough=no. Other times the L7 rule needs to be renamed, before it starts working. Its all a bit odd.


##create a routing table for traffic we want to drop
/routing table
add disabled=no fib name=RT-NULL

##setup a null route
/ip route
add blackhole disabled=no distance=100 dst-address=0.0.0.0/0 gateway="" routing-table=RT-NULL scope=30 suppress-hw-offload=no target-scope=10


##regex that matches all domains used for Windows Update
/ip firewall layer7-protocol
add name=windowsUpdateSNI regexp="^.*(\\.microsoft\\.com|\\.windowsupdate\\.com|\\.windows\\.com|\\.trafficmanager\\.net|\\.msft\\.com|\\.gfx\\.ms|\\.sfx\\.ms|\\.live\\.com)([^A-Za-z0-9\\-\\.]).*\$"


##Add ips/subnets that should be SNI filtered
/ip/firewall/address-list/
add address=10.10.10.10 list=Net-Filter-SNI-Base disabled=no
add address=10.10.10.10 list=Net-Filter-SNI-1 disabled=no


##minimize the load by only applying L7 filter to packets that contain Client Hello
##Fragmentation can still make us miss the Hello, but far less than tls-host for large payloads
/ip/firewall/mangle/
add action=log chain=topDelimiter comment=Sni-Inspect disabled=yes
add action=jump chain=forward jump-target=SNI-Inspect src-address-list=Net-Filter-SNI-Base
add action=mark-packet chain=SNI-Inspect comment="Block Quic" dst-port=80,443 new-packet-mark=pktDeny passthrough=no protocol=udp
add action=jump chain=SNI-Inspect connection-state=established dst-port=443 jump-target=SNI-Inspect-1 protocol=tcp src-address-list=Net-Filter-SNI-1 tcp-flags=psh,ack
add action=mark-packet chain=SNI-Inspect-1 comment="Windows Update" layer7-protocol=windowsUpdateSNI new-packet-mark=pktAccept passthrough=no
add action=mark-connection chain=SNI-Inspect-1 comment="Default Drop" new-connection-mark=NULL-CONN passthrough=no
add action=return chain=SNI-Inspect-1
add action=return chain=SNI-Inspect
add action=log chain=bottomDelimiter comment=Sni-Inspect disabled=yes

##established default allow for established connections, should be somewhere in your mangle 
add action=accept chain=forward connection-state=established

##allow SNI hosts to establish TCP connection so TLS negotiation can start
add action=mark-packet chain=forward dst-port=443 new-packet-mark=pktAccept passthrough=no protocol=tcp src-address-list=Net-Filter-SNI-Base

##Null route all SNI that were not approved
add action=mark-routing chain=prerouting connection-mark=NULL-CONN new-routing-mark=RT-NULL passthrough=no


##setup filter to default drop traffic that is not approved
/ip firewall filter
add action=accept chain=forward connection-state=established,related
add action=accept chain=forward packet-mark=pktAccept
add action=drop chain=forward packet-mark=pktDeny
add action=drop chain=forward

I know, it is CPU intensive, but what if you use web-proxy, disable all tcp&&udp 80,443 ports in forward chain? Just a fast thinking around this, but I think this would works, whatever TLS version would be handshaking by client & server. Indeed, you must configure HTTP_PROXY on all device behind router...