Need to resolve to multiple IP addresses

Dear Colleagues,

I am looking for a script which would resolve a DNS name and add the resulting IP addresses to the routing table. I could use something like

add comment=test11 dst-address=[:resolve api.XXX.YYY] gateway=10.4.0.33 routing-table=main

But the problem is that api.XXX.YYY resolves to multiple IP addresses, and I need all of them in the routing table. Can you give me an example script please?

PS I have tried the /ip/firewall/address-list + route-mark solution but it did not work well for me. It works, but for some reason the response from api.XXX.YYY is much slower in this case (in comparison with the situation when the IPs are simply added as static /32 routes to the main table). Sorry I do not know the reason.

Thank you very much for any advice.

Sounds like there might be some other issues at play here, but just to focus on exactly what you asked for.

You could achieve what you’re after by combining an address list entry with your script.

First, add an entry for the host you’re trying to resolve:

/ip/firewall/address-list add address=bbc.co.uk list=resolved

Then this script will add route entries for each address that gets resolved:

:local ipList [/ip/firewall/address-list/print as-value where comment=bbc.co.uk]

:foreach line in=$ipList do={
    /ip/route/add comment=test11 dst-address=($line->$address) gateway=10.4.0.33 routing-table=main
}

You’ll want to add some logic to deal with clearing out the current routes before re-adding them, maybe checking for changes before doing so etc.

So you suggest using /ip/firewall/address-list just as a mechanism to expand a name into multiple IPs? It is a clever trick, if there are no other mechanisms, thank you very much for the idea!

That aside, do you think there could be reasons why the /ip/firewall/address-list + route-mark solution could be slow? I see it even visually while running “kubectl get something”, and Lens simply chokes and refuses to work with such a delay but does work when I have static routes in the route table.

If you know the number of IP addresses in advance:

{
:local ipList
:local domain "bbc.co.uk"
:local numberOfAddresses 3
:for resolved from=0 to=($numberOfAddresses-1) do={ :set ($ipList->resolved) [:resolve $domain] }
:foreach line in=$ipList do={
	/ip/route/add comment=test11 dst-address=($line) gateway=10.4.0.33 routing-table=main
}
}

There is no protection in /ip/route for adding multiple times the same route so :do{} on-error={} does not work.

Ahhh :resolve does appear to work round robin, I didn’t think it did.

I guess then you should be able to do a :while loop of :resolve putting the results into an array each time then exit when the next address is already in the array. Maybe add a max iterations counter as well.

You’ll need to post a config export for us to have a chance of working it out.
I can tell you I use policy based routing all the time and it works well for me.

It works for me too, it just is slow for some reason, like maybe TCP setup is slow. The relevant config lines are:

/ip firewall address-list
add address=api.dev2.YY.XXXX list=Kubernetes
add address=api.prod2.YY.XXXX list=Kubernetes
add address=api.prod.YY.XXXX list=Kubernetes

/ip firewall mangle
add action=mark-routing chain=prerouting comment="Route Kubernetes via WG" disabled=no dst-address-list=Kubernetes in-interface=bridge new-routing-mark=wireguard passthrough=no

/routing rule
add action=lookup-only-in-table comment=wireguard disabled=no routing-mark=wireguard table=wireguard

/routing table
add disabled=no fib name=wireguard


/ip route
[...]
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=10.99.0.33 routing-table=wireguard scope=30 suppress-hw-offload=no target-scope=10

Very similar to a lot of config I use. Except I don’t have the /routing rule.

Out of interest, since you’re matching on dst-address, is there a specific subnet you’re trying to hit over the tunnel?
In which case you can simply put a route to that subnet in your table instead.

Turns out the

/routing rule

was not necessary. The new-routing-mark action in

/ip firewall mangle

is sufficient to direct the traffic into an alternative routing table. However, removing the

/routing rule

did not help the situation: the API queries are still very slow, Lens does not tolerate such response times. I had to revert to explicit ip routes.

Of course there is no specific subnet. The addresses are public, dynamic and very distant. If there were a subnet, such a question would never have arisen. Unless I want to send several /19 AWS blocks into the tunnel which I do not.