Page 1 of 1
Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 9:57 am
by VictorS
Dear Colleagues,
I have written a script to add host routes to the IPv4 routing table, please see the complete script below. The problem however is that on each invocation, the script creates duplicate entries in the routing table, and of course it does not delete old entries (which it created when the IP addresses were different). Can you please advise me some way to detect obsolete entries? It would be nice to use some timestamps on configuration entries, but I don't know of such a feature existing in RouterOS.
The script itself:
# extract addresses in the list
:local AddressList [/ip firewall address-list find comment~"api\\."];
:local ipAddress;
:foreach entry in=$AddressList do={
:set ipAddress ([/ip firewall address-list get $entry]->"address");
:put ($ipAddress."/32");
/ip/route/add comment=([/ip firewall address-list get $entry]->"comment") disabled=no distance=1 dst-address=($ipAddress."/32") gateway=10.x.x.x routing-table=main;
};
Of course I could delete all the generated routes on each script invocation, like in
# delete all API routes
/ip/route/remove [find comment~"api\\."];
But this will probably cause traffic disruptions if I run the script from cron.
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 3:38 pm
by rextended
I won't write it down, but I'll give you an idea.
Scroll through the list of addresses.
For each of theroutes you find that are the same as the ones you need,
update the comment with a prefix and today's date (for example "$comment 2025/01/24 14:30")
add the routes that don't exist, always with the same comment "$comment 2025/01/24 14:30"
Finally, delete among all the routes that contain "api." those with a comment that not containing "2025/01/24 14:30"
/ip/route/remove [find where (comment~"api\\.") and !(comment~"2025/01/24 14:30")]
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 4:18 pm
by VictorS
Basically, this boils down to
1. At the start of the script, generate some unique string (e.g. :timestamp )
2. Add this string to the comments of all the routes generated within this iteration of the script
3. At the end of the script, delete all the routes which do not contain this unique string
Do I understand your idea correctly?
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 4:41 pm
by rextended
Basically, yes, but for be more "nice" on the point 2: on foreach cycle at the same time you UPDATE the comment if the rule already exist AND add new rules with :timestamp.
This do not delete what already exist (and must be keeped) and do not (temporarly) duplicate rules.
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 4:48 pm
by VictorS
Why would I care to take into account what already exists when I can create a bunch of new routes with the current timestamp (even if they are duplicates of the older routes, it does not seem to cause any harm) and then delete everything with non-current timestamps? This looks much simpler, unless it is wrong for some reason.
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 4:54 pm
by rextended
This produce same output at the end, but is just for progam in "nice" way (avoid duplicates, avoid deleting what must be rewrited, etc.).
Anyway, the important thing is the rest, which I think you understood from my suggestion.
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 5:38 pm
by BartoszP
Tip no. 1:
Use route marking. Make a mangle rule that mark packets from your list with routing mark and stay away from routing table where the only route rule for all that addresses (route mark) is needed. No matter when and how you update the list only members of it would get the needed routing with no hickups
Tip no. 2:
The list that you prepare should be timebased so when you add an entry to it then you should set timer for the entry for eg. 6 hours if you refresh that list every 6 hours. When you readd the entry during that period you just refresh/reset that timer, if not the entry just vanishes. No need to worry of any leftovers.
Tip no. 3:
Read that "The International Microtik Obsfucated Code Contest"
for updating address lists:
viewtopic.php?p=606832#p606832
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 6:17 pm
by rextended
Tip n.1 for tip n.1: Use routing / rules. Each item has it's own tool.... when MikroTik finally add address-lists to routing rules........................
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 9:41 pm
by BartoszP
Tip 1 to tip 1 to tip 1:
Address list for marking routes in mangling
One route rule to route mangled packets.
Re: Garbage collect old routes and duplicate routes
Posted: Fri Jan 24, 2025 11:42 pm
by rextended
(when MikroTik have done) generic tip: do not use firewall to do routing job....
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 12:34 am
by BartoszP
You just killed "policy routing" idea
https://help.mikrotik.com/docs/spaces/R ... cy+Routing
Policy routing is the method to steer traffic matching certain criteria to a certain gateway. .....
RouterOS gives you two options to choose from:
firewall mangle - it gives more control over the criteria to be used to steer traffic, for example, per connection or per packet balancing, etc. For more info on how to use mangle marking see Firewall Marking examples......
The problem IMHO is that mangling is in the Firewall menu even if it provides mostly nonfirewall services but that place suggest that mangle is firewall thing. For me the most firewall-like actions are the green ones.
- change-dscp - change the Differentiated Services Code Point (DSCP) field value specified by the new-dscp parameter
- change-mss - change the Maximum Segment Size field value of the packet to a value specified by the new-mss parameter
- change-ttl - change the Time to Live field value of the packet to a value specified by the new-ttl parameter
- clear-df - clear 'Do Not Fragment' Flag
- fasttrack-connection - shows fasttrack counters, useful for statistics
- mark-connection - place a mark specified by the new-connection-mark parameter on the entire connection that matches the rule
- mark-packet - place a mark specified by the new-packet-mark parameter on a packet that matches the rule
- mark-routing - place a mark specified by the new-routing-mark parameter on a packet. This kind of mark is used for policy routing purposes only. Do not apply any other routing marks besides "main" for the packets processed by FastTrack, since FastTrack can only work in the main routing table.
route - forces packets to a specific gateway IP by ignoring normal routing decisions (prerouting chain only)
- set-priority - set priority specified by the new-priority parameter on the packets sent out through a link that is capable of transporting priority (VLAN or WMM-enabled wireless interface). Read more
- sniff-pc - send a packet to a remote RouterOS CALEA server.
- sniff-tzsp - send a packet to a remote TZSP compatible system (such as Wireshark). Set remote target with sniff-target and sniff-target-port parameters (Wireshark recommends port 37008)
- strip-ipv4-options - strip IPv4 option fields from IP header, the action does not actually remove IPv4 options but rather replaces all option octets with NOP, further matcher with ipv4-options=any will still match the packet.
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 12:06 pm
by VictorS
Basically, yes, but for be more "nice" on the point 2: on foreach cycle at the same time you UPDATE the comment if the rule already exist AND add new rules with :timestamp.
This do not delete what already exist (and must be keeped) and do not (temporarly) duplicate rules.
I agree that your proposal looks nicer, but as I am writing this script to solve a very small personal problem (changing IP addresses of load balancers), I prefer the solution to be quick and simple, and I am ready for it to be dirty. I only have to write a couple of scripts in RouterOS and will probably never need the language again for several years.
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 12:16 pm
by VictorS
Tip no. 1:
Use route marking. Make a mangle rule ...
Oh no. In fact, I tried to solve my problem first with address-lists + PBR (policy based routing). There are many examples of PBR for Mikrotik in the internet, using the firewall and multiple routing tables.
It worked but (!) TCP worked
SO slowly that kubectl and Lens did not tolerate such response times and produced errors. I was never able to find the reason why packets going via PBR were
so slow and had to revert to regular routing which works fast.
I even thought of using BGP to announce those dozen /32 routes to Mikrotik, but the solution with DNS -> routing seems simpler to implement though it requires scripting (and I am a newbie in RouterOS scripting).
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 1:44 pm
by MrYan
Oh no. In fact, I tried to solve my problem first with address-lists + PBR (policy based routing). There are many examples of PBR for Mikrotik in the internet, using the firewall and multiple routing tables.
It worked but (!) TCP worked SO slowly that kubectl and Lens did not tolerate such response times and produced errors. I was never able to find the reason why packets going via PBR were so slow and had to revert to regular routing which works fast.
Chances are that you were fast-tracking the traffic subject to PBR. It will work very slowly because some packets will use the slow path and get through. From
https://help.mikrotik.com/docs/spaces/R ... n+tracking:
Note that not all packets of the connection can be FastTracked, so it is likely to see some packets going through a slow path even though the connection is marked for FastTrack. This is the reason why fasttrack-connection is usually followed by an identical "action=accept" rule.
If using connection-mark then excluding these from the fasttrack rule should work:
chain=forward action=fasttrack-connection connection-state=established,related connection-mark=no-mark
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 1:53 pm
by VictorS
Tip no. 2:
The list that you prepare should be timebased so when you add an entry to it then you should set timer for the entry for eg. 6 hours if you refresh that list every 6 hours. When you readd the entry during that period you just refresh/reset that timer, if not the entry just vanishes. No need to worry of any leftovers.
Tip no. 3:
Read that "The International Microtik Obsfucated Code Contest"
for updating address lists:
viewtopic.php?p=606832#p606832
This brings about a question. How are address-lists resolved and refreshed? If I create an address-list from the name "api.mycluster.example" and it resolves into 3 dynamic address-lists with IP addresses, how do I make sure that these dynamic lists do not become stale and my code
:local AddressList [/ip firewall address-list find comment~"api\\."];
:foreach entry in=$AddressList do={
:set ipAddress ([/ip firewall address-list get $entry]->"address");
...
always receives the actual IP addresses?
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 3:26 pm
by BartoszP
As rextended suggested use comment for tagging your "dynamic" routes:
viewtopic.php?p=1121406#p1121406
You have to have global variable holding the last used TAG. Add new/current routes with a new tag and delete all with old one.
If routes are doubled then only the one of them is active and even if active one is just removed the second takes over.
Do not kow if changeing the distance for the old ones to +1 could help as the first step to let the new entries get active immediately but it is just an idea.
The main question is where the "api*" list come from? Is it a list of PPoE interfaces or it is based on DHCP. If yes maybe you should consider using on/off scripts to activate/deactivate particular routes and netwatch script to clear the stale ones?
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 4:07 pm
by VictorS
The main question is where the "api*" list come from?
It comes from
/ip firewall address-list
where DNS names like
,
create several dynamic address lists with the
or
in their comment. It happens automatically. Hence my question how these dynamic address lists are updated.
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 4:31 pm
by BartoszP
Seems that the TTL of the dynamic DNS based names is used to feed the list and when it expires the list is refreshed to the actual apiN.example.com
viewtopic.php?t=177324
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 4:42 pm
by VictorS
Seems that the TTL of the dynamic DNS based names is used to feed the list and when it expires the list is refreshed to the actual apiN.example.com
viewtopic.php?t=177324
This is good.
Re: Garbage collect old routes and duplicate routes
Posted: Sat Jan 25, 2025 5:10 pm
by BartoszP
You can check it easily: make a list based on any noncrucial DNS name and then set local static DNS name with different IP and set the low test TTL for that. Then watch how and when the address list reacts to changes to static entry or disabling it.
Re: Garbage collect old routes and duplicate routes
Posted: Mon Jan 27, 2025 4:43 am
by VictorS
You can check it easily: make a list based on any noncrucial DNS name and then set local static DNS name with different IP and set the low test TTL for that. Then watch how and when the address list reacts to changes to static entry or disabling it.
I have created a DNS name with 3 A RRs and TTL=300 in one of my DNS zones, and changing the RRs in DNS, I confirm that the dynamic address lists also change in Mikrotik.
Re: Garbage collect old routes and duplicate routes
Posted: Mon Jan 27, 2025 5:47 am
by VictorS
/ip/route/remove [find where (comment~"api\\.") and !(comment~"2025/01/24 14:30")]
OK, the final script (quick and dirty but functional) would be
# extract addresses in the list
:local AddressList [/ip firewall address-list find comment~"api\\."];
:local ipAddress;
:local timeStamp [:timestamp]
:foreach entry in=$AddressList do={
:set ipAddress ([/ip firewall address-list get $entry]->"address");
:put ($ipAddress."/32");
/ip/route/add comment=([/ip firewall address-list get $entry]->"comment"."_$timeStamp") disabled=no distance=1 dst-address=($ipAddress."/32") gateway=10.x.x.x routing-table=main;
};
# delete old API routes
/ip/route/remove [find where (comment~"api\\.") and !(comment~".*_$timeStamp")]