Issue with Layer7 Protocol and Address List in RouterOS v7.16

Hello everyone,

I’m facing an issue with Layer7 Protocol in RouterOS v7.16. Here’s what I’ve set up:
Firewall Rule

Flags: X - disabled, I - invalid; D - dynamic 
 0    chain=forward action=add-dst-to-address-list layer7-protocol=youtube address-list=CAD 
      address-list-timeout=1d log=yes log-prefix="YOUTUBE.COM"

Layer7 Protocol
The regex name is “youtube”, and the content is:
regex

youtube\.com|youtu\.be|googlevideo\.com

Problem

  • When a client accesses YouTube, nothing is stored in the address list (CAD).
    There are no log entries related to this rule.
    The bytes and packets counters remain 0 for the rule.

Can someone please help me figure out why this is not working?

Hi there, I suspect your l7 rule is too low. Can you export your fw rules and post here. (Don’t forget the code tags!)

Hi,

Thank you for your reply! Here’s the export of my firewall rules as requested:

 /ip firewall filter export
# 2024-12-11 12:30:18 by RouterOS 7.16
# software id = MD5W-A12Z
#
# model = RB750r2
# serial number = 63BD05A8B07F
/ip firewall filter
add action=add-dst-to-address-list address-list=CAD address-list-timeout=1d chain=forward \
    dst-address=!10.10.10.0/24 layer7-protocol=1 src-address=10.10.10.0/24
add action=add-dst-to-address-list address-list=CAD address-list-timeout=1d chain=forward \
    dst-address=!10.10.10.0/24 layer7-protocol=youtube src-address=10.10.10.0/24

Almost definitely the two rules you showed are not full firewall config. Or is it?

Regarding L7: almost everything now days works over encrypted communications (httpS) and almost every server/client combination supports TLS v1.3. In TLS v1.3 also SNI is encrypted, hence L7 regex rule in ROS can not match.

Essentially, L7 rules are these days useless in most use cases.

Oh waw … you have a minimalistic rulebase.

BTW what is the l7 list called “1”?

As mkx said, a lot goes over encrypted connections so things may or may not work the way you expect.

Let me know if you would like assistance in implementing any of these alternatives or if you need further clarification. I appreciate your help and feedback!

Hi,

Thank you for the insight! I’ve created a simple rule that covers all situations for now, and later I will refine it to be more specific. This is just a test configuration to check the overall setup.

Thanks again for your help!

this is the full configuration

# 2024-12-11 13:12:06 by RouterOS 7.16
# software id = MD5W-A12Z
#
# model = RB750r2
# serial number = 63BD05A8B07F
/interface bridge
add name=OpenVPN-bridge
/interface ethernet
set [ find default-name=ether1 ] name=ether1-WAN
set [ find default-name=ether2 ] name=ether2-LAN
set [ find default-name=ether3 ] disabled=yes
set [ find default-name=ether4 ] disabled=yes
set [ find default-name=ether5 ] disabled=yes
/interface wireguard
add comment="WG-Teh to CANA Tunnel" listen-port=443 mtu=1420 name=\
    WG-Teh
/ip firewall layer7-protocol
add name=Skype regexp=\
    "^.+(skype|skype.com|msgr.skype.com|ui.skype.com).*\$\r\
    \n"
add name=OpenAI regexp=\
    "^.+(openai\\.com|chat\\.openai\\.com|api\\.openai\\.com).*\$\r\
    \n"
add name=Amazon regexp="^.+(amazonaws\\.com|aws\\.amazon\\.com|cloudfront\\.ne\
    t|s3\\.amazonaws\\.com).*\$\r\
    \n\r\
    \n"
add name="google analytics" regexp="google-analytics\\.com|analytics\\.google\
    \\.com|googletagmanager\\.com\r\
    \n"
add name=youtube regexp="youtube\\.com|youtu\\.be|googlevideo\\.com"
add name=test regexp="google\\.com"
add name=1 regexp=\
    "^.*(google-analytics\\.com|analytics\\.google\\.com).*\$\r\
    \n"
/routing table
add disabled=no fib name=viaVPN
/ip settings
set rp-filter=loose
/interface ovpn-server server
set auth=sha1,md5 certificate=*1 cipher=\
    blowfish128,aes128-cbc,aes192-cbc,aes256-cbc default-profile=\
    default-encryption
/interface wireguard peers
add allowed-address=172.16.2.0/30,10.0.1.0/30,10.0.0.0/24,0.0.0.0/0 comment=\
    "Teh WireGuard Peer" endpoint-address=11.111.11.11 endpoint-port=443 \
    interface=WG-Teh name=WGPeer persistent-keepalive=10s public-key=\
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
/ip address
add address=192.168.1.2/30 comment=WAN interface=ether1-WAN network=\
    192.168.1.0
add address=172.16.2.2/30 comment=WG-Tunnel interface=WG-Teh network=\
    172.16.2.0
add address=10.10.10.2/24 interface=ether2-LAN network=10.10.10.0
/ip dns
set servers=10.10.10.8
/ip firewall address-list
add address=e.e.e.e list=CAD
add address=d.d.d.d list=CAD
add address=c.c.c.c list=CAD
add address=b.b.b.b list=CAD
add address=a.a.a.a list=CAD
add address=8.8.8.8 list=CAD
add address=x.x.x.x list=IR
add address=y.y.y.y list=IR
add address=z.z.z.z list=IR

/ip firewall filter
add action=add-dst-to-address-list address-list=CAD address-list-timeout=1d \
    chain=forward dst-address=!10.10.10.0/24 layer7-protocol=1 src-address=\
    10.10.10.0/24
add action=add-dst-to-address-list address-list=CAD address-list-timeout=1d \
    chain=forward dst-address=!10.10.10.0/24 layer7-protocol=youtube \
    src-address=10.10.10.0/24
/ip firewall mangle
add action=accept chain=prerouting dst-address=10.0.1.0/24 src-address=\
    10.10.10.0/24
add action=mark-routing chain=prerouting dst-address=!10.10.10.0/24 \
    dst-address-list=!IR new-routing-mark=viaVPN passthrough=yes src-address=\
    10.10.10.0/24
add action=mark-routing chain=prerouting disabled=yes dst-address=\
    !10.10.10.0/24 dst-address-list=CAD new-routing-mark=viaVPN passthrough=\
    yes src-address=10.10.10.0/24
/ip firewall nat
add action=masquerade chain=srcnat out-interface=WG-Teh routing-mark=\
    viaVPN
add action=masquerade chain=srcnat out-interface=ether1-WAN routing-mark=main
/ip firewall service-port
set ftp disabled=yes
set tftp disabled=yes
set sip disabled=yes
/ip route
add comment="Default Gateway" disabled=no distance=1 dst-address=0.0.0.0/0 \
    gateway=192.168.1.1 routing-table=main scope=30 suppress-hw-offload=no \
    target-scope=10
add disabled=no dst-address=10.0.0.0/24 gateway=WG-Teh routing-table=main \
    suppress-hw-offload=no
add disabled=no distance=1 dst-address=10.0.1.0/30 gateway=WG-Teh \
    routing-table=main scope=30 suppress-hw-offload=no target-scope=10
add disabled=no dst-address=11.111.11.11/32 gateway=192.168.1.1 \
    routing-table=main suppress-hw-offload=no
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG-Teh \
    routing-table=viaVPN scope=30 suppress-hw-offload=no target-scope=10
add disabled=yes distance=1 dst-address=208.67.220.220/32 gateway=172.16.2.1 \
    routing-table=main scope=30 suppress-hw-offload=no target-scope=10
/ip service
set telnet disabled=yes
set ftp disabled=yes
set www disabled=yes
set api disabled=yes
set winbox address=",11.111.11.11/32,10.10.10.0/24,10.0.0.0/24\
    ,172.16.2.0/30,192.168.1.0/30," port=8291
set api-ssl disabled=yes
/system clock
set time-zone-autodetect=no time-zone-name=Asia/Teh
/system identity
set name="Teh - R2"
/system note
set show-at-login=no
/system scheduler
add interval=1d name=UpdateIRListSchedule on-event=UpdateIRList policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
    start-date=2024-11-29 start-time=03:28:50
/system script
add comment="Read IR IP List" dont-require-permissions=yes name=UpdateIRList \
    owner=admin policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\
    local url \"https://www.iwik.org/ipcountry/mikrotik/IR\";\r\
    \n:local fileName \"IR.rsc\";\r\
    \n:do {\r\
    \n    :log info (\"Fetching updated IP list from \" . \$url . \"...\");\r\
    \n    /tool fetch url=\$url mode=https dst-path=\$fileName;\r\
    \n    \r\
    \n    :log info \"Successfully fetched the updated IP list. Clearing old e\
    ntries...\";\r\
    \n    /ip firewall address-list remove [find list=IR];\r\
    \n    \r\
    \n    :log info \"Importing new IP address list...\";\r\
    \n    /import file-name=\$fileName;\r\
    \n    \r\
    \n    :log info \"IP address list updated successfully.\";\r\
    \n} on-error={\r\
    \n    :log warning (\"Failed to fetch the updated IP list from \" . \$url \
    . \". No changes made to the address list.\");\r\
    \n}"
add dont-require-permissions=yes name=VPNIPAddress owner=admin policy=\
    read,write,test,sensitive source="# Define variables\r\
    \n:local addressList \"CAD\"\r\
    \n:local domains {\"youtube.com\"; \"youtu.be\"; \"googlevideo.com\"}\r\
    \n\r\
    \n# Loop through each domain in the list\r\
    \n:foreach domain in=\$domains do={\r\
    \n    # Find DNS cache entries matching the domain\r\
    \n    :local resolvedIPs [/ip dns cache all find name~\$domain]\r\
    \n    :if ([:len \$resolvedIPs] > 0) do={\r\
    \n        :foreach ip in=\$resolvedIPs do={\r\
    \n            :local ipAddress [/ip dns cache get \$ip address]\r\
    \n            # Add IP to address list if it exists\r\
    \n            :if ([:len \$ipAddress] > 0) do={\r\
    \n                /ip firewall address-list add list=\$addressList address\
    =\$ipAddress comment=\$domain timeout=1d\r\
    \n            }\r\
    \n        }\r\
    \n    }\r\
    \n}\r\
    \n"

It should match http://youtube.com but not a lot more.

If you want to match the names in the certs, you need to have the rules the other way around as well as the server sends its cert. And it will not match DNS requests.

As I already wrote: if those domain names are not sent from client towards server in plain text, then L7 matcher won’t be able to match them. You can verify if this is indeed a problem by doing a wireshark recording (on client machine would be fine) and check initial few packets, sent from client towards server … SNI will probably be mentioned in 3rd packet in that direction (initial packet with SYN flag and no payload, second packet with ACK flag and no payload and third one starts with SSL/TLS setup and this one includes SNI) … there’s one packet in opposite direction (with SYN and ACK flags, no payload, as response to first SYN packet).

There’s another way but it doesn’t necessarily yield results: adding those FQDNs to address list. Router will resolve them into IP addresses (and will adhere to TTL), but it might resolve them differently than client if client don’t use router as resolver (DHCP server settings). It will also fail if clients use their own DoH (increasing number of web browsers implement them) because this means that clients won’t use router as resolver, no matter what are DHCP server settings or even local settings on client computers (if address, etc.). is set statically.

AFAIK not even protocol (http), only host name, e.g. youtube.com

Meant the rule should match if he goes to http://… as the Host header will be both visible and from client to server.