dst-nat support for shifted portmap ranges?

Hello all

I am seeing a problem with port range forwarding (different source range to target range, but same number of ports)

For the following rule:

/ip firewall nat add action=dst-nat chain=dstnat comment="redirect port range" dst-address=185.50.105.156 dst-port=32123-32160 protocol=udp src-address=192.168.10.50 to-addresses=192.168.10.2 to-ports=32223-32260

Log shows:

prerouting: in:bridge_lan out:(unknown 0), src-mac 40:8d:5c:44:ef:ff, proto UDP, 192.168.10.50:58228->185.50.105.156:32127, NAT (192.168.10.50:58228->192.168.10.1:58228)->(195.50.105.157:32127->192.168.10.2:32260), len 576

So even though the client is trying to reach port 32127 (which is not the last port in the dst-port range), DST-NAT is pushing them to port 32260 (which is the last port to-ports range)

To work around this, I had to create a manual dst-nat rule for each port, now everything is fine… but my firewall is clogged with several rules

Am I doing something wrong here, or is this a (pretty serious…?) bug?

I presume it works fine if to-ports==dst-ports, but intuitively it should work if to-ports != dst-ports but the port count is the same… (but I did not test same ports, only reporting this issue with different ports)

Thank you..

I’m running v6.47.1

Well your rule does need scrutiny.
Can I assume you have fixed/static wanip and hopefully you have fudged the numbers and its not exactly what you have shown.

I dont understand why you have a source address? Do you mean to say there is only one external WANIP that is allowed to come in through the router.
Typically folks, if they have more than one KNOWN, create a firewall source adddress list.
But why is the source address a private LANIP looking address???

Normally people dont know the IP addresses of those wishing to come through the router and thus there is no source address of any ilk, in the rule.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

IF your intention is allow devices/people from the SAME Subnet to access the server (already within the router) you do not need source addresses.
YOu have a loopback or hairpin nat scenario.
Step1: Ditch the source address in the current dst nat rule and
Step2: Add one more sourcenat rule to your config
add action=src-nat chain=srcnat source-address=192.168.10.1/24 dst-address=192.168.10.1/24

Alternatively just move your server to its own subnet (as long as the lan user and server are in different subnets one does NOT need the additional source nat hairpin rule (but still get rid of that extra not needed source address in the dst nat rule.

Basically, I am trying to intercept traffic intended for an outbound (WAN) IP and redirect that to a local/LAN IP (for analogy, imagine us wanting to redirect Google DNS to a server on the same internal subnet but not the mikrotik itself, so the dst-address=8.8.8.8, to-address (in my case) 192.168.10.2, and (again, in my case) only wanting this rule to affect LAN client 192.168.10.50, which is why src-address is 192.168.10.50, so that is correct…). But the scenario is irrelevant anyway. The dst-nat rule works fine when I use individual dst-nat rules for each individual port (along with a masquerading rule). The problem comes into effect when I try to forward the whole range of ports as described. So I can appreciate your reply, but with all due respect it seems like an irrelevant response because you didn’t attempt to tackle the alleged bug itself. I urge you to rather try to replicate a similar scenario by forwarding (dst-nat) a range of UDP ports (with different range of ports in dst-port and to-port, but same port count), and see if you experience the same behavior or not.. When I do this, the to-ports range is not processed correctly - the firewall seems to always try to forward to last port in the to-port range, rather than the nth port corresponding to the dst-port range, as would be expected

I don’t understand your logic, neither do I see how you can call this a bug?

You are sending a port number, you tell the firewall to do port translation, to a “range” of ports, the port number you are sending is not part of this “range” the rule must translate to.

What port number do you expect the rule to translate that port you sent to?

To me it looks like the rule is doing exactly what it is intended to do.

Ok
So let’s say dst-ports=10000-20000 and to-ports=30000-40000
If client tries to connect to port 12345, router should forward to 32345, right? Well it’s not. it’s forwarding to 40000. understand? As far as I can tell, that is very much a bug. What good is port translation if it can’t logically translate a range that the router accepted as valid config? What use are the other ports in the to-ports range (30000-39999) if it’s always going to forward to 40000 anyway? Furthermore, if you think this is expected behaviour, then my question is this: HOW else then am I supposed to Translate a dst-port RANGE from a given range to a Different to-ports range using a single rule otherwise?

Why?

What will make it select port number 32345?

The fact that the client tried to connect to a port 12345 which falls within the dst-ports range of 10000-20000, and that the to-ports range =dst-ports range +10000?

Bro, respectfully, either you’re trolling, or you’re playing really dumb here.
We already know that it is possible to forward a single port with dst-nat, and we also know that the to-port does not need to be the same as the dst-port
We also know that it is possible to forward a range with dst-port (separated by a dash), and that it is equally possible to specify a range (separated by a dash) in the to-ports field.
Don’t you think that would imply that if I specify a to-ports range that is different to the dst-ports range but has the same number of ports in sequence, that the port to be forwarded will be the the difference between the two starting ports respectively? I’m pretty certain this is how it’s supposed to work…

I’m answering your questions but you ignored mine. If I want to create a single rule that forwards a given range of ports to a different range of ports (of equal quantity but different starting port), what would that rule be? Please give me an example. Thank you

For the record, I’m seeing the same problem with TCP forwarding. It works if the two ranges are the same. If you shift the to-ports range, the relative port tracking fails

Sorry but your requirement is not clear and CZFAN does not troll. If its not clear then a better explanation is warranted.

First of all are you port forwarding from the WAN to a server on your lan subnet?? (normal)
OR
Are you port forwarding from a user on your LAN to a server on your lan subnet?? (hairpin nat or loopback).


If the WANIP that the user on your LAN is heading out to IS NOT YOUR WANIP given to you by your ISP, then its not port forwarding.
So please explain better.,

It makes sense to me (I mean requested behaviour), but for some reason it doesn’t work that way.

If I test only one port at a time, even different ones, then it uses same port from to-ports range.

If I test more at a time (e.g. using nmap to scan range), it uses different ports from to-ports range, in increasing manner. I’m not sure about exact rules.

In any case, observed behaviour seems completely useless to me, I can’t think of anything it would be good for. Static 1:1 mapping would be logical and possibly useful for same-sized ranges. Whether it’s bug or or not, I’m not sure. It’s possible that it isn’t, because to-ports with range does something, that could make sense to someone.

Btw, @anav, you’re still missing the point.

For @anav, before he asks. :wink:

I have this rule, 601-605 in dst-port and 1601-1605 in to-ports.

/ip firewall nat
add action=dst-nat chain=dstnat dst-address=b.b.b.b dst-port=601-605 protocol=tcp to-addresses=c.c.c.c to-ports=1601-1605

Both ranges contain five ports. So it would not be unreasonable to expect that requests to 601 will always go to 1601, 602 to 1602, etc, right? But what actually happens is this:

a.a.a.a:58599->c.c.c.c:1604, NAT a.a.a.a:58599->(b.b.b.b:601->c.c.c.c:1604)
a.a.a.a:58600->c.c.c.c:1604, NAT a.a.a.a:58600->(b.b.b.b:601->c.c.c.c:1604)
a.a.a.a:40986->c.c.c.c:1604, NAT a.a.a.a:40986->(b.b.b.b:602->c.c.c.c:1604)
a.a.a.a:40987->c.c.c.c:1604, NAT a.a.a.a:40987->(b.b.b.b:602->c.c.c.c:1604)
a.a.a.a:43730->c.c.c.c:1604, NAT a.a.a.a:43730->(b.b.b.b:603->c.c.c.c:1604)
a.a.a.a:43730->c.c.c.c:1604, NAT a.a.a.a:43730->(b.b.b.b:602->c.c.c.c:1604)
a.a.a.a:43730->c.c.c.c:1605, NAT a.a.a.a:43730->(b.b.b.b:605->c.c.c.c:1605)
a.a.a.a:43730->c.c.c.c:1601, NAT a.a.a.a:43730->(b.b.b.b:601->c.c.c.c:1601)
a.a.a.a:43730->c.c.c.c:1602, NAT a.a.a.a:43730->(b.b.b.b:604->c.c.c.c:1602)
a.a.a.a:43731->c.c.c.c:1602, NAT a.a.a.a:43731->(b.b.b.b:603->c.c.c.c:1602)
a.a.a.a:43731->c.c.c.c:1602, NAT a.a.a.a:43731->(b.b.b.b:601->c.c.c.c:1602)
a.a.a.a:43731->c.c.c.c:1603, NAT a.a.a.a:43731->(b.b.b.b:604->c.c.c.c:1603)
a.a.a.a:43731->c.c.c.c:1604, NAT a.a.a.a:43731->(b.b.b.b:605->c.c.c.c:1604)
a.a.a.a:43731->c.c.c.c:1605, NAT a.a.a.a:43731->(b.b.b.b:602->c.c.c.c:1605)

There’s 601 going to 1604, then 602 is going to same 1604, then 601 again goes to different 1601 or 1602. It’s unpredictable and almost random. And seems useless, because what can you do with that?

@anav
Ok apologies if I was impatient. I will try to explain again … First, please disregard all example scenarios above (src-address etc etc), and let us construct a new, simpler example:

Consider IRC, which uses TCP port 6667:

If I create a dst-nat rule on my router (router IP 192.168.10.1) with dst-port=6667, to-port=6667, and to-address=45.76.131.163 (some IRC server on the internet, listening on TCP port 6667), then my IRC client on my PC (192.168.10.50) can reach the internet IRC server by connecting to the router IP on TCP port 6667 (192.168.10.1:6667). With me so far? Great :smiley:

Similarly, if I create a dst-nat rule with dst-port=5667 and to-port=6667, then my IRC client will reach the IRC server by connecting to 192.168.10.1:5667.

Now let us assume I dst-nat dst-ports=6000-7000 to the destination IP, to-ports=6000-7000. If I connect to 192.168.10.1:6667, it works.
But if I dst-nat dst-ports=5000-6000 to the destination IP, to-ports=6000-7000, and I connect to 192.168.10.1:5667, it doesn’t work?

So, If:
I can dst-nat a single dst-port to a single to-ports where to-ports is the same as dst-port, and
I can dst-nat a single dst-port to a single to-ports where to-ports is NOT the same as the dst-port, and
I can dst-nat a dst-port RANGE to a to-ports RANGE where to-ports is the same as the dst-port RANGE, Then:
Why can I not dst-nat a dst-port RANGE to a to-ports RANGE that is different to dst-nat RANGE but contains the same number of ports as the dst-port RANGE?

As a footnote, I do find it quite remarkable that this hasn’t been discovered (or at least reported) yet. Even if this functionality is rarely needed, I would still imagine that surely someone would have needed it by now. Irrespective of whether such a forwarding configuration seems likely or not, I do think it is reasonable to suggest that it should still be supported, since the only other alternative seems to require that you create a distinct rule for each and every desired port pair otherwise. Why else would the field be called “To ports” and not “To port” anyway? After all, if you want to forward the same port range as the dst-ports, you can just leave it blank anyway, right?

My understanding of how NAT works in ROS is as follows: there are two groups of parameters and parameters from each group are pretty unrelated. The two parameter groups are:

  1. selection criteria properties
    Parameters which govern which packets actually trigger action of particular NAT rule. Most of properties (listed in NAT manual) belong to this group … except for the following properties
  2. action properties
    Parameters which affect the outcome of NAT rule. These are the following:
    to-addresses
    to-ports

So when one specifies range of ports in either src-ports or dst-ports, setting widens selection criteria for certain NAT rule … And when one specifies range of ports in to-ports, it offers ROS to use any of the ports from the range to use in rewritten packet. Thus using range of ports in to-ports doesn’t make much sense if action=dst-nat but may make much sense if action=src-nat.

However, docs don’t imply that the ranges (if used in both parameter groups) are related in any way. As documentation doesn’t imply such correlation, I wouldn’t call the observed behaviour a bug.

As usual I am stuck at simpler concepts.
I cannot get my head around using dstnat for what is normally basic lan to wan traffic.

What he is using dsnat for, is not the
a. typical port forwarding for external users to a server on the lan.
b. typical hairpin loopback for internal users to server on same subnet but via my WANIP (vice the more intuitive lanip LOL)

Thus this looks more like a routing issue then a port forwarding issue, almost.
However you guys are masters at deception and slight of hand and thus can make dstnat rules work for just about every case LOL.
So I imagine its completely legit to have lan to wan traffic you want to contort via a dst nat rule ???

Thus perhaps the issue I have is use of the term port forwarding?? If that terminology was not used, then I would have naturally assumed oh this is one of those twisted SOB/MKX destination nat weird configs that are above my head. :slight_smile:

As for the range of ports, I am with the OP, I think this is a bug.
If I translate a range of ports I would expect that the range I translate two would match up.
In other words I give the router a contiguous series of three ports, A, A+1, A+2 and translate to B,B+1, B+2.
I fully expect a to b, a1 to b1, a2 to b2 etc…
This is the same expectation if I advise the router I have a range of one to one IP addressses to assign.
I woudn’t expect to have to assign each one individually if there was a range option (which I know exists on many soho, enterprise routers I have used).

What “Relative” port forwarding?

Port number “1234” is not the same as “2234” and there are no relation between them. The firewalls / router does not count “is this the 3rd port number in the from range, so lets map to the 3rd port number in the to range”. I suspect that will be too taxing on the NATing process

Disagree for port forwarding and for the contiguous assignment of one to one nat mapping.
Cmon guys, when did you turn into chaos for config… Dont you like order??? I expected higher standards lol

Not that I want to bump this thread, but I feel like we haven’t arrived at a definitive final consensus on this functionality yet

I think that the intended feature in question, namely shifted range port forwarding, is an important consideration for RouterOS (one that it should definitely be supported)

Judging by the responses from this thread so far, it seems the forum is more of a community discussion and that the issue has not reached the eyes of the developers yet. How can we go about bringing this question to the attention of the core developers? I would like to know if/when might this be addressed for future versions?..

Thanks

Post it on the forum as a “feature request”

I have not used this yet, so maybe just search the forum for above, think there are “topic headings” for it.

Alternatively send mail to support@mikrotik.com requesting this feature

Hi all

Quick update on this issue

Through some further research (trying to replicate the desired functionality on debian linux), I discovered the following:

https://stackoverflow.com/questions/33052149/is-it-possible-to-map-11-port-range-iptable-dnat-rules
https://patchwork.ozlabs.org/project/netfilter-devel/patch/3d98278c-6c33-72e1-163d-2f6270060620@dtsystems.be/
http://git.netfilter.org/iptables/commit/?id=36976c4b54061b0147d56892ac9d402dae3069df

Seems it’s been available since iptables 1.8.0 - https://lwn.net/Articles/759184/

Turns out (or, seems to, at least) that this is not a bug in RouterOS, but probably a limitation in some of its dependencies and/or implementation

FWIW, it is possible to implement the desired functionality in Linux, example as follows:

iptables -t nat -D PREROUTING -p tcp -m tcp --dport 5000:5999 -j DNAT --to-destination 45.76.131.163:6000-6999/5000

If I connect to TCP port 5667 on that host where the rule is active, it will DNAT the client to 45.76.131.163:6667. Right now it does not seem possible to create such a rule on RouterOS because a forward-slash is not allowed in the “to-ports” field.

I have E-mailed MikroTik support for advice and am in contact with Arturs C regarding the matter

Not sure what you meant as I am linux challenged besides many other aspects of IT.
Suffice to say the router OS does port redirecting very well, dead easy to change the incoming port number to a different port number before it hits the server and the firewall for that matter.
What we are talking about is a contiguous range of ports remapped to a set of contiguous ports.

If I want to map a group of ports that are not contiguous then I should be able to do this as well separated by commas.
If I only want single to single then thats already covered. The OS should be smart enough to understand what is being directed.

The router OS does port redirecting very well, dead easy to change the incoming port number to a different port number before it hits the server.
What we are talking about is a contiguous range of ports remapped to a set of contiguous ports and multiple entries separated by commas remapped as well.

Current rules

  1. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XXX protocol=tcp to addresses=192.168.0.ww (no translation)
  2. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XXX protocol=tcp to addresses=192.168.0.ww to-ports=YYY (with translation)
  3. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XXX,AXX,BXX,CXX protocol=tcp to addresses=192.168.0.ww (no translation)
  4. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XX1-XX9 protocol=tcp to addresses=192.168.0.ww (no translation)

PROPOSED
5. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XXX, AXX, BXX, CXX protocol=tcp to addresses=192.168.0.ww to-ports=CFF, GHH, UJU (combo translation**)
**logical required mappings XXX to CFF, AXX to GHH, BXX to UJU. CXX is not mapped and remains CXX but need not be stated

  1. add chain=dstnat action=dst-nat dst-address=wanip dst-port=XX1-XX9, BXX, CXX protocol=tcp to addresses=192.168.0.ww to-ports=TR1-TR9, KLK (with and without translation***)
    ***logical required mapping XX1-XX9 to TR1-TR9 (and yes XX1 to TR1, XX2 to TR2 and so forth, BXX to KLK, CXX is not mapped and remains CXX but need not be stated ]

This should be dead easy to implement and is logical from my viewpoint. The router still verifies if
-the incoming traffic with port is noted in dstnat rules and is thus permitted to flow into the router, firewall rule allows port forwarding traffic.
-the router keeps traffic of which port to which server etc. as per normal.