"IF this, THEN IF ALSO that, THEN ALLOW ...".
But. If we want the knocks to be able to be simple (TCP SYN, so it could be triggered by a web browser), then we run a modest risk of a bad guy's high-intensity port scan triggering our Knock, to wit:
Bad guy fast TCP port scans us, luckily in the same sequence as our Port Knock (i.e. we require ports 7000 and then 6000 in that order, and bad guy happens to scan in descending order, or happens to scan TWICE in ascending order). That could successfully "knock".
So I'd like to add an intermediate anti-accidental-knock filter rule.
It might look something like this:
;;; default configuration: allow already established connections to continue
chain=input action=accept connection-state=established,related log=no log-prefix=""
;;; port knocking step 1 - knock TCP on port 7000
chain=input action=add-src-to-address-list protocol=tcp address-list=KnockKnock:7000 address-list-timeout=1m dst-port=7000 log=no
;;; port knocking step 2 - knock TCP on port 6000 - get added to KnockedSuccessfully list
chain=input action=add-src-to-address-list protocol=tcp src-address-list=KnockKnock:7000 address-list=KnockedSuccessfully address-list-timeout=1m dst-port=6000 log=yes
;;; port knocking intermediate block - if ON the KnockKnock:7000 list and NOT already on the KnockedSuccessfully list and touch any OTHER port then temporarily blacklist
chain=input action=add-src-to-address-list protocol=tcp src-address-list=KnockKnock:7000,!KnockedSuccessfully address-list=BadKnocks address-list-timeout=1m dst-port=!7000,6000 log=yes
;;; and finally the necessary allow-if-knocked-successfully rule
chain=input action=accept src-address-list=KnockedSuccessfully,!BadKnocks log=yes
This does not seem to be working, I suspect because what I'm trying to do with the compound matches isn't the right syntax:
src-address-list=KnockKnock:7000,!KnockedSuccessfully src-address-list=KnockedSuccessfully,!BadKnocks dst-port=!7000,6000
and to match any dst-port which is NEITHER 7000 nor 6000 in the third case.
The MikroTik (RB951Ui-2HnD, RouterOS and firmware 6.43.14) accepts the /ip firewall filter ... command entries, but apparently they don't mean what I want them to.
What I see is IP addresses being added to the KnockKnock:7000 address-list, but neither do properly knocked connection requests get through, nor does anything ever end up on either the BadKnocks or KnockedSuccessfully address-lists.
(If I take out the whole idea of BadKnocks, then a typical knock configuration, TCP:7000 followed by TCP:6000, works just fine on my MikroTik router).
So, what's the right syntax to specify "on this src-address-list but not on this other src-address-list" and "not either of these two dst-ports"?