[Feature Request] Match control flags inside the TCP header for Switch Rules (ACL)

Cisco allows the usage of `permit tcp any any established`, which allows accepting only ACK and RST control flags inside the TCP header of the packet in a stateless way, where wire-speed switching is achieved.

Mikrotik’s switch chips should definitely support this behavior, and the Switch Rule (ACL, `/interface ethernet switch rule`) functionality should have this implemented and available to be used.

Considering that Switch Rules with Layer 4 condition parameters are available in at least Marvell Prestera, I believe that this can be implemented from the hardware without losing any throughput or using the CPU, and without using `/ip firewall`.


Layer4 condition parameters:

  • dst-port

  • src-port

Some explanations from AI:

When you use the command permit tcp any any established in a standard or extended Cisco Access Control List (ACL), it sounds like the router is keeping a watchful eye on your active sessions. However, the reality underneath is much simpler—and a lot less secure.

The router isn't actually checking a connection table or remembering what traffic went out. Instead, it performs a purely stateless check on the TCP packet header.

Here is exactly what happens under the hood.

The Magic is in the TCP Flags

When a packet hits an interface with this ACL applied, the router looks directly at the control flags inside the TCP header of the packet.

It is specifically looking for one of two flags to be turned on (set to 1):

  • ACK (Acknowledgment): Indicates the packet is acknowledging data or a previous step in the handshake.

  • RST (Reset): Indicates the packet is trying to tear down a connection.

If either the ACK or RST flag is set, the router assumes the packet is part of an ongoing conversation and permits it through. If neither flag is set, the router drops it.

Why This Works (The TCP Handshake)

This clever (but basic) trick relies on how the standard TCP 3-way handshake operates:

  1. Device A sends a SYN packet to start a connection. (No ACK flag is set).

  2. Device B replies with a SYN-ACK packet. (ACK flag IS set).

  3. Device A replies with an ACK packet. (ACK flag IS set).

Because the very first packet (the initial SYN) is the only packet in a normal TCP conversation that doesn't have the ACK flag set, the established keyword effectively blocks outside devices from initiating new connections, while allowing return traffic from connections you started from the inside.

If the router sees ACK == 1 OR RST == 1, the packet is permitted. If both are 0, the packet is dropped.

To understand why this ultra-simple check actually works for 99% of normal network traffic, we have to look at the rules of the Transmission Control Protocol (TCP) itself.

Why Checking Just 'ACK' Covers Almost Everything

In the standard TCP protocol, there are six primary control flags (URG, ACK, PSH, RST, SYN, FIN).

The trick is that every single legitimate packet sent after the very first packet in a TCP session will have the ACK bit set to 1. Here is how that looks across the lifespan of a connection:

  • The Initial Request (SYN): The outside device says "Hello, I want to connect." It sets SYN=1 and ACK=0.

    • Router Action: Dropped. (Because ACK and RST are both 0).
  • The Reply (SYN-ACK): If the internal server had started the connection instead, the outside server's reply is "I acknowledge your request, let's connect." It sets SYN=1 and ACK=1.

    • Router Action: Permitted.
  • Sending Data (PSH-ACK / ACK): While you are downloading a file or loading a web page, every packet transferring data or acknowledging receipt has the ACK bit turned on.

    • Router Action: Permitted.
  • Closing the Connection (FIN-ACK): When it's time to politely close the connection, the devices send FIN packets. These almost always include an acknowledgment of the last piece of data received, so FIN=1 and ACK=1.

    • Router Action: Permitted.

Why is 'RST' Included?

The RST (Reset) flag is used when a device receives a packet for a connection it knows nothing about, or when a connection crashes unexpectedly. It essentially means "Abort!" or "Stop talking to me."

Cisco includes the RST=1 check in the established rule so that if an external server outright refuses a connection your internal device tried to make (for example, if the port is closed), that rejection message is allowed back through. If it blocked the RST packet, your internal computer would just sit there waiting and timing out instead of closing the application immediately.

Well, that is a lot of text to request “please add TCP flags as a matching criterion in switch rules”…

Probably those that want the utmost in performance without loading the CPU have already moved on to “L3 acceleration” but it could still be a useful option for the lower end devices that do not have that.

Excellent entry point for DoS...

I agree, but this would be a deal breaker for my next Mikrotik for our purpose if the option’s not there. It’s better than nothing if we can’t set a stateful firewall up because the throughput requirement is very high, and at the same time, using L2. Would otherwise have to resort to the switch that is even upstream.

Stateless Hardware Firewall

While connection tracking and stateful firewalling can be performed only by the CPU, the hardware can perform stateless firewalling via switch rules (ACL). The next example prevents (on a hardware level) accessing a MySQL server from the ether1, and redirects to the CPU/Firewall packets from ether2 and ether3:

The “L3 acceleration” still restricts the number of connections and memory in CRS3xx/CRS5xx (I have three 98DX8xxx switches) when it’s about stateful firewalls and Fasttrack HW Offloading. Doing stateless (switch rules) is the only practical option that is wire-rate, and the control flags (ACK/RST) support is the key bottleneck to working with ‘allow some and deny rest‘ policies over ‘deny some and allow rest‘ policies.