Firewall oddity

If I have three IPv6 firewall rules, that each accept or drop after checking for UDP dst-port 1-9999, UDP dst-port ! 1-9999 and just UDP, I would expect the last rule to never match, because a port is either in that range or not in that range, so either rule one or two should match and end processing. The third rule (and no other) does match when a UDP packet for dst-port 55555 arrives. I.e., the second rule should match because 55555 is not in 1-9999, but the packet falls through to rule three which doesn’t check the dst-port. What am I missing?

Why don’t you post exact rules as configured (/ipv6 firewall filter export)?

The three rules are:

add action=drop chain=forward dst-address-list=test dst-port=1-9999 protocol=udp
add action=accept chain=forward dst-address-list=test dst-port=!1-9999 protocol=udp
add action=accept chain=forward dst-address-list=test protocol=udp

The ​address list is a single IPv6 address. It should be impossible for a packet to be accepted by the third rule. No matter what, one of the first two rules should match or the third rule shouldn’t match either. Nevertheless, I do see the counter of the third rule go up when a packet for a high dst-port arrives.​ The packet with the high dst-port is an RTP packet. All service-port helpers (/ip firewall service-port) are disabled.

I can’t find exact reference, but it seems that exclamation isn’t always used in same sense. Sometimes it negates whole setup and sometimes only part of it, not sure how behaves with range (from Manual:IP/Firewall/Filter):


CLI Disctinctive

There is a bit different interpretation in each section with the similar configuration.
For example, with the following configuration line you will match packets where tcp-flags does not have SYN, but has ACK flags:

/ip firewall filter add chain=forward protocol=tcp tcp-flags=!syn,ack

>
> But with this configuration you will match all connections which state is not NEW or RELATED.
>
> ```text
/ip firewall filter add action=accept chain=forward connection-state=!new,related

Both configure similarly.

That’s not it. I just used the inversion to make sure I cover all ports with the first two rules. The result is the same if I positively check for 10000-65535 in the second rule. The packet with the high port doesn’t match that rule and falls through to the third rule, where it matches. It doesn’t even match the second rule if I check for the exact dst-port of that packet.

I think it’s a connection tracking / SIP helper problem. I can’t reproduce it with just ordinary UDP packets that have no prior relation to some other connection. It reliably occurs if the UDP packet is an RTP packet coming in for a SIP “connection”. I don’t understand how that could make a difference. The IPv4 service-port helpers are all disabled, there are no service-port helpers in the IPv6 category, and there is no NAT in IPv6 anyway.

Enable some logging on the 3e rule so you can get more info on what makes the counter go up ?

I’ve done that. It just tells me that it’s a UDP packet with the right properties to be caught by the second rule. That’s why I wrote the second rule as the inverse of the first rule: It really should not be possible for a packet to make it past the first and second rule and still match the third rule.

The first rule is (a and b), the second rule is (a and not b) and the third rule is (a). But ((a and b) or (a and not b)) is just (a), so anything that matches the third rule should have matched the first rule or the second rule.

Edit:
Ok, this is weird. The source and destination port that the third rule logs appear to come from the first four bytes of the IPv6 packet (IP version, traffic class, flow label). The start of the IPv6 packet is the only place these numbers appear in a packet capture, and a UDP packet with those ports is nowhere to be seen. The packet with that IP version, traffic class and flow label actually isn’t an RTP packet. That flow is the SIP “connection”, which starts with a fragment.

Stick with IPV4, its way betta :wink:

If you can sell me a couple public IPv4 addresses for less than the cost of a replacement router which handles IPv6 properly, I’m all ears. As it is, I can only recommend against using Mikrotik gear if IPv6 is a requirement.

That said, after some more testing it looks like the router doesn’t reassemble IPv6 fragments. Connection tracking is on (the SIP connection shows up as a tracked connection), but I still see fragments in the firewall, and they are logged with bogus information. According to the documentation, fragments should not appear if connection tracking is enabled. Would be great if Mikrotik could comment on this.

You’ll have to ask them at support@mikrotik.com, you’ll have better chance to get a comment.