Hai, anyone here could explain best description on how firewall JUMP action working and also some explanation script? Thank in advance.
Sent from my Redmi 5 using Tapatalk
Hai, anyone here could explain best description on how firewall JUMP action working and also some explanation script? Thank in advance.
Sent from my Redmi 5 using Tapatalk
It jumps to different chain and continues with rules there. And either finds one that does something, or reaches the end, jumps back to original chain and continues there. It can save a lot or processing.
For example, let’s say you have hundered external addresses and hundered forwarded ports from each:
/ip firewall nat
add chain=dstnat dst-address=x.x.x.1 protocol=tcp dst-port=10001 action=dst-nat to-addresses=a.a.a.1
<other rules with dst-address=x.x.x.1>
add chain=dstnat dst-address=x.x.x.1 protocol=tcp dst-port=10100 action=dst-nat to-addresses=a.a.a.100
add chain=dstnat dst-address=x.x.x.2 protocol=tcp dst-port=10001 action=dst-nat to-addresses=b.b.b.1
<other rules with dst-address=x.x.x.2>
add chain=dstnat dst-address=x.x.x.2 protocol=tcp dst-port=10100 action=dst-nat to-addresses=b.b.b.100
<rules with many other dst-addresses>
add chain=dstnat dst-address=x.x.x.100 protocol=tcp dst-port=10001 action=dst-nat to-addresses=c.c.c.1
<other rules with dst-address=x.x.x.100>
add chain=dstnat dst-address=x.x.x.100 protocol=tcp dst-port=10100 action=dst-nat to-addresses=c.c.c.100
So it’s ten thousands rules. The worse case scenario is that incoming connection matches neither one of them. It means that router will have to check the packet against all ten thousands rules. Or you could use jumps like this:
/ip firewall nat
add chain=dstnat dst-address=x.x.x.1 action=jump jump-target=fwd1
add chain=dstnat dst-address=x.x.x.2 action=jump jump-target=fwd2
<other rules for dst-address=x.x.x.3-99>
add chain=dstnat dst-address=x.x.x.100 action=jump jump-target=fwd100
add chain=fwd1 protocol=tcp dst-port=10001 action=dst-nat to-addresses=a.a.a.1
<other rules for dst-port=10002-10099>
add chain=fwd1 protocol=tcp dst-port=10100 action=dst-nat to-addresses=a.a.a.100
add chain=fwd1 action=accept
add chain=fwd2 protocol=tcp dst-port=10001 action=dst-nat to-addresses=b.b.b.1
<other rules for dst-port=10002-10099>
add chain=fwd2 protocol=tcp dst-port=10100 action=dst-nat to-addresses=b.b.b.100
add chain=fwd2 action=accept
<many other rules for chain=fwd3-99>
add chain=fwd100 protocol=tcp dst-port=10001 action=dst-nat to-addresses=c.c.c.1
<other rules for dst-port=10002-10099>
add chain=fwd100 protocol=tcp dst-port=10100 action=dst-nat to-addresses=c.c.c.100
add chain=fwd100 action=accept
You won’t save any rules, in fact you’ll have two hundered more (jumps and ending accepts). But processing will be much more efficient. Not only the worst case will mean checking only two hundered rules, but rules in fwdX chains don’t need to check dst-address all over again.
Just one additional point - although the action name is jump, the actual functionality is more a call, because if no rule in the jump-target chain matches (or if a rule with action=return in that chain does match), the processing of the packet continues in the calling chain, starting by the first rule following the jump one. So I routinely use things like
chain=forward action=accept connection-state=established,related
…
chain=forward action=jump jump-target=forward-to-ether2 out-interface=ether2
chain=forward action=jump jump-target=forward-to-ether3 out-interface=ether3
chain=forward action=drop
chain=forward-to-ether2 src-address-list=permitted-clients-of-ether2
chain=forward-to-ether3 src-address-list=permitted-clients-of-ether3
I.e. there is just a single “drop the rest” rule in the end of the forward chain, and the individual chains for each out-interface just contain the exception rules from this final drop one.
Or, when connection-marking packets in LAN->WAN direction in /ip firewall mangle, you need to assign a routing-mark also to packets which have just been connection-marked, but at the same time you want to keep the number of rules handling each packet as low as possible. So I do
chain=prerouting action=jump jump-target=pr-conn-mark connection-mark=no-mark
chain=prerouting action=mark-routing new-routing-mark=RM1 connection-mark=CM1 passthrough=no
chain=prerouting action=mark-routing new-routing-mark=RM2 connection-mark=CM2 passthrough=no
chain=pr-conn-mark action=mark-connection new-connection-mark=CM1 <… match conditions for assigning CM 1…>
chain=pr-conn-mark action=mark-connection new-connection-mark=CM2 connection-mark=no-mark <… match conditions for assigning CM 2…>
chain=pr-conn-mark action=mark-connection new-connection-mark=use-main connection-mark=no-mark
Here again, the chain pr-conn-mark is “called” when necessary, to assign a connection-mark to first packets of connections, and the processing then continues by eventually assigning a routing-mark based on the connection-mark.
The match condition in the first rule could as well be connection-state=new rather than connection-mark=no-mark, which would make the connection-mark value use-main redundant, but I deem the way with connection-mark=no-mark more comprehensible for the reader.
Another remark just for the case, the passthrough=no is there only to prevent matching the packet against the subsequent rules in chain=prerouting once the routing-mark has been assigned, as it would be a useless waste of CPU. It is not there to prevent the packets to get to chain pr-conn-mark which follows chain prerouting in the configuration - the packets don’t jump from one chain to another without being explicitly told so using action=jump.
Thank you for detailed explanation.
I use mikrotik against DDoS attacks. Our raw and filter rules use a lot of CPU. I am learning jump rules to save CPU usage. You explained it very well but do you have any other suggestions for lowering CPU usage for firewall rules?
RAW is introduced to be able to block traffic before it hits connection tracking and so avoid high CPU usage.
UDP/Mangle/Filter need connection tracking and so using the CPU big time.
We use only filter for single IP connection limit and renewing src-lists timeouts.
Unfortunately, no magic is available. To spend as few firewall rules as possible on most “legal” packets is what helps when dealing with normal traffic; to use drop rules in raw, matching on an address-list populated by rules in filter, in order to prevent the (D)DoS packets from reaching more CPU-intensive stages of handling, as you already do, is the most efficient way of dealing with (D)DoS locally, i.e. once the malicious packet has reached your machine. If you cannot agree with your upstream provider on informing them about sources of (D)DoS traffic so that they would cut them off at all their interconnect links (where the total bandwidth of the DDoS attack may be distributed among multiple ingress interfaces), there’s not much you can do.
Dropping traffic by dst-address-list is more efficient against DDoS than dropping it by src-address-list as the dst-address-list is much smaller, so it needs a little bit less CPU to search it through, but that protects your router from glowing red and the DDoS target from overload, but the target service is not happy as you block also the “legal” traffic to it that way.
One possibility might be a switch (or a switch chip) supporting rules with hardware L3 matching, which you could dynamically configure to drop the traffic towards the affected target address using a script. Dropping it by source address on a switch chip makes little sense as usually only a few rules are available. So it is again just a protection of the router’s CPU, not of the availability of target’s service for legal users.
Specialized devices exist which can selectively filter only traffic which looks like a DDoS one and let normal traffic through. I suppose they use advanced hardware filters but I have no hands-on experience with them.
Thank you again for informatinal post. It helped a lot.
Could you please explain Raw Rule > Dst. Limit Limit by options ? For example : Limit By dst. address , Limit By src. address , Limit By dst. address and src. address
I understand src. address is like this : Rate 10 means 1 IP sends a dst. address only 10 packets at a time right?
Thank you.
First, please don’t quote complete posts, this is no e-mail so the history is always on the same screen. Here, quoting only makes sense when you respond to multiple individual points in the previous post and need to provide context for each response, or if you respond in multi-threaded or noisy topics.
To the subject - yes, you got it right regarding the src-address as mode, but I’m not sure I understand the “at a time” part the same way like you - for me, “at a time” means at the same time instant. As this is technically impossible, you specify the time interval as the time parameter of the matcher, which defaults to 1s, which is the lowest value available.
The dst-limit matcher dynamically creates a dedicated rate counter with the count/time and burst parameters per each “flow” identified by combination of source and/or destination address(es) and port(s) (let’s say a traffic selector) chosen by mode. Whenever the rule processes a packet matching to an already existing flow, the rate counter for that flow is updated; whenever the rule processes a packet not matching to any existing flow, a new rate counter for that new flow is added to the list.
The dst-limit only handles a packet if other match conditions of the rule match. If the rate counter corresponding to the packet being processed exceeds the threshold, the dst-limit gives a match as well, so the whole rule then matches and executes its action.
Therefore, the matching of packet’s headers to a “flow” may get equally complex as matching them to “connection” in connection tracking if mode requests that multiple address fields of the packet be taken into account. So if you stay with mode=src-address, this matcher is about as CPU-intensive as the src-address-list one, but if you set mode=addresses-and-dst-port, it becomes heavier.
So with mode=src-address, it is better to use the rule with action=drop directly; with mode=addresses-and-dst-port, it is likely better to use it with action=add-src-to-address-list and place a rule dropping packets whose source address matches that address list before it.
In case of a DDoS, the address list or flow list will be long if you build it from source addresses. Also the rate from each individual malicious source may be relatively low, indistinguishable from one from a regular user. So to me, using src-address as mode (flow indentifier) looks like an unreliable approach. So again, I would opportunistically be dropping by destination address in order to protect the router and thus indirectly the other services to a certain extent, as the DDoS target won’t work anyway.
How do you avoid blocking legitimate port forwarding if you have blocking in raw by destination address??
When it comes to DDoS, you don’t care about such tiny details.