I know it is a recurrent thread, but I want impruve my config.
I have config the source hairpin nat. Now, for the destination nat I need a destination addresss list witch my dynamic wan IP. I config this address list with a dns (duckdns or the mikrotik dns)
But I can obtain the dynamic wan ip from the ppoe config with this comand
:put [/ip address get [find where interface=pppoe] value-name=address]
Is there any wat to configure a destination address list or a destination nat with the dynamic wan ip from the ppoe config instead of a address list over DNS?
Use of pppoe client data requires mild scripting. The /interface pppoe-client item refers to a /ppp profile item, and the /ppp profile item has an on-up parameter that can hold a script that is executed each time a new address is assigned to the PPPoE interface. That script may update the action=dst-nat rules.
But if you only have a single public IP as seems to be the case, there is also a possibility to let the dst-nat rules match on any own address of the router that is not a private one: /ip firewall address-list
add list=rfc1918 address=10.0.0.0/8
add list=rfc1918 address=172.16.0.0/12
add list=rfc1918 address=192.168.0.0/16
/ip firewall nat
add chain=dstnat dst-address-type=local dst-address-list=!rfc1918 protocol=x dst-port=y action=dst-nat to-addresses=l.l.l.l to-ports=z
Or, if the above is too esoteric for you, you can let the firewall auto-learn the actual WAN address: /ip firewall mangle
add chain=output out-interface=pppoe-out1 action=add-src-to-address-list address-list=my-wan-ip address-list-timeout=10m
/ip firewall nat
add chain=dstnat dst-address-list=my-wan-ip protocol=x dst-port=y action=dst-nat to-addresses=l.l.l.l to-ports=z
However, in order that this worked, you have to make sure that the router itself keeps sending some traffic to the internet quite frequently (so that it would not take too long to learn the new address once it changes). A netwatch item is the easiest solution, it even does not have to ping a real address - PPPoE is an L3 interface so there is no ARP and you can ping even a private address if it matches the default route.
It’s needlessly complicated - the on-up and on-down scripts expose some global variables as described here. So the script can be much simpler - $“local-address” gives you the current WAN IP directly.
So the whole script would then look something like this:
The way you update the address list entry triggers two modifications of the list. For data structures heavily optimized for lookup/read performance, modifications are always orders of magnitudes more expensive. Each modification probably needs to lock global data structures (lock the whole firewall probaly); and add and remove operations are also normally more costly (because data might need to be reshuffled) than just in-place update. And of course, if the PPPoE re-dial gives you the same IP address then your list is lost.
So I agree that using $“local-address” is better (although if you put the code in a script then you won’t be able to independently call it anymore), but I still stand with my update paths
I don’t think the script execution is blocking anything (and even if it was, it is executed when the WAN has just obtained a new address, so everything was broken until that happened anyway).
The situation is different when a rule with action=add-src-to-address-list or add-dst-to-address-list is executed - there, indeed, the packet processing does not move to the next rule until the address has been added to the list, because the next rule already successfully matches on the address-list:
But you are right that checking whether the currently obtained address is not already present on the list is a better approach, as my script would fail in such a case, because adding the same address to the list again causes an error if done by a script. If done by a firewall rule, it just resets the timeout if there is one.
Well, it actually behaves quite nicely - even if on-up or on-down spawns another script, it passes those variables to it as a kind of environment, so it is just a matter of generating the address list name from the interface name if you want to reuse the same ppp profile for multiple ppp* interfaces.
Sorry, I am an old school software developer and it’s just a habit for me to think about implementation details and low level inefficiency and your script will cause more unnecessary operations (especially writes and memory allocations/deallocations) while holding locks multiple times, that can be minimized for the normal case that the list exists with 1 entry
With “independently call” I meant going to the script list and click “Run”, maybe because you’ve just cleared the address list and want the important entries repopulated.
Arguably the simplest way to create dst-nat / port forward rules when you have a dynamic IP is to just match on in-interface=, and not try to chase the changing IP address at all. Though of course if you also want to implement hairpin NAT, this won’t work, because your LAN-sourced traffic will not arrive at the router via the physical WAN interface.
But what I have found works equally as well, and is equally as simple, is to match on dst-address-type=local. “local” will match any address that the router itself holds…so, basically, when you are setting up NAT rules, you can use this as a shorthand for what would normally be captured by the “input” firewall chain. This would of course include the dynamic WAN address, regardless of in-interface, so as a bonus it also works just fine with hairpin NAT. And the extra cherry on top is that it should allow you to access the same resource via the same port on ANY of the router’s own addresses, even its LAN-side address. Neat! No complicated scripting required (though don’t get me wrong, I love a good ROS script…)