FWIW, here is how I built my port-knock chain, to impose that each packet has to be in sequence and correct. If not, the src-ip is added to the k-fail list, which prevents another try for 30 seconds by the jump rule (no need for the limit that was in the OP):
8 ;;; Port knock test
chain=input action=jump jump-target=port-knock src-address-list=!k-fail
The first knock gets the src-ip into the k-1 list for 10 seconds, the second knock into k-2, etc until k-4, where the ip is added for one hour.
I use the portknock app of Greg Sowell for the knocks. However I have noticed that when mixing tcp and udp knocks on my high latency satellite connection, they often arrive out of sequence at the target interface. So I modified his code to allow me to increase the delay between the knocks (increasing the delay too much is also a problem though, because the knocks then get mixed up with the automatic tcp retransmissions of the operating system, which happen when the syn packets are left unreplied to).
Anyway, here is the code for the port-knock chain. It's a long chain, but very few packets go through it thanks to the 30 seconds ban of the k-fail list. There may be ways to achieve the same more elegantly. (Chain starts at item #3 because I have logging rules in 1-2-3 for testing).
3 ;;; if src-addr is on k-4 list, return
chain=port-knock action=return src-address-list=k-4
4 ;;; if src-addr is on k-3 list and dst-port is udp 12345, add src-addr to k-4 list
chain=port-knock action=add-src-to-address-list protocol=udp src-address-list=k-3 address-list=k-4 address-list-timeout=1h dst-port=12345
5 ;;; ---- if src-addr is on k-4 list, return
chain=port-knock action=return src-address-list=k-4
6 ;;; ---- if src-addr is on k-3 list, add src-addr to k-fail
chain=port-knock action=add-src-to-address-list src-address-list=k-3 address-list=k-fail address-list-timeout=30s
7 ;;; ---- if src-addr is on k-fail list, return
chain=port-knock action=return src-address-list=k-fail
8 ;;; if src-addr is on k-2 list and dst-port is udp 54321, add src-addr to k-3 list
chain=port-knock action=add-src-to-address-list protocol=udp src-address-list=k-2 address-list=k-3 address-list-timeout=10s dst-port=54321
9 ;;; ---- if src-addr is on k-3 list, return
chain=port-knock action=return src-address-list=k-3
10 ;;; ---- if src-addr is on k-2 list, add src-addr to k-fail
chain=port-knock action=add-src-to-address-list src-address-list=k-2 address-list=k-fail address-list-timeout=30s
11 ;;; ---- if src-addr is on k-fail list, return
chain=port-knock action=return src-address-list=k-fail
12 ;;; if src-addr is on k-1 list and dst-port is tcp 13579, add src-addr to k-2 list
chain=port-knock action=add-src-to-address-list protocol=tcp src-address-list=k-1 address-list=k-2 address-list-timeout=10s dst-port=13579
13 ;;; ---- if src-addr is on k-2 list, return
chain=port-knock action=return src-address-list=k-2
14 ;;; ---- if src-addr is on k-1 list, add src-addr to k-fail
chain=port-knock action=add-src-to-address-list src-address-list=k-1 address-list=k-fail address-list-timeout=30s
15 ;;; ---- if src-addr is on k-fail list, return
chain=port-knock action=return src-address-list=k-fail
16 ;;; if dst-port is tcp 24680, add src-addr to k-1 list
chain=port-knock action=add-src-to-address-list protocol=tcp address-list=k-1 address-list-timeout=10s dst-port=24680
17 ;;; ---- if src-addr is not on k-1 list, add src-addr to k-fail
chain=port-knock action=add-src-to-address-list src-address-list=!k-1 address-list=k-fail address-list-timeout=30s