LAN device cannot request itself through WAN IP and port forwarding

Hello,

Here is the problem I am trying to solve: I have a service running on a computer (let’s call it PC1), that I want to be reachable from any device on LAN or WAN, even from PC1 itself. And this service should be addressed the same way by all clients, so using WAN IP. Then, I have set a port forwarding rule in Firewall to forward the wan requests on the concerned port to PC1. This way, it seems that any device on LAN or WAN can reach the service running on PC1… all but PC1 itself !

Example:

  • PC1 (LAN IP: 192.168.8.112) runs netcat -lk -p 8888 so listens on TCP 8888, and port forwarding rule forwards incoming requests on 8888 on WAN to 8888 on 192.168.1.112. Then I run telnet <WAN_IP> 8888 from several points

    • From the Internet: OK :white_check_mark:
    • From another LAN computer (let’s call it PC2): OK :white_check_mark:
    • From PC1: KO :x:
  • So I change the configuration, I make PC2 (LAN IP: 192.168.8.212) run netcat -lk -p 8888, and I edit port forwarding rule so incoming requests on 8888 on WAN are this time forwarded to 8888 on 192.168.1.212 (PC2), and I try again:

    • From the Internet: OK :white_check_mark:
    • From PC1: OK :white_check_mark:
    • From PC2: KO :x:

Is there a rule somewhere that prevents a device from requesting itself using WAN IP (because of course using localhost it works) ? And if yes, how can I change this ?

Thank you

I did this for some Restful WebAPIs when helping a developer.
I have a simpler solution as my GL-INET is behind another router which already does this.

Lets think about this. When someone comes from the outside and we forward the traffic we do an DNAT (Destination NAT) rule that changes the destination from the WAN IP address to the internal IP address and forwards. All good.

When I use the WAN IP address I am coming from the inside, so when the kernel is scanning the firewall rules the source firewall zone (read interface) is the inside ethernet port not the outside internet port so the kernel does not match the rule, so we try to connect to port 8888 of the router … and probably fail.

Note: Some SME routers default to doing the below in one rule, its actually a bit of a security hole, so Openwrt in my mind anyway, does the right thing and does not do it out of the box, but after reading the warnings if you really have to, you can do it!

We have to do one more thing if we want the firewall to behave properly and avoid the client connecting via the router, but the server sending back directly to the client - which may not work depending on how paranoid your client OS is. We have to perform a SNAT (Source NAT) to change the IP address the server sees the packet from. Normally if we are sending a packet to google, your router just does that, using the external IP address your router got from your ISP.

You need to use the firewall in advanced (well for the internal traffic anyway).
In LUCI, Network->Firewall, Port Forward Tab. add a rule.
Name it, choose TCP (for your NC example) and source zone LAN.
External port 8888
Destination Zone lan, internal IP address the server.
In the advanced tab, make sure Enable NAT Loopback is ticked, and
either use internal ip address (may not work), or use external IP address so we change the Source IP address as above.

This should allow the traffic to “Trumbone” through the router between client and server.

Simon

1 Like

Many thanks for the detailed explanation. Not easy to debug !

I am indeed currently trying to replace my ISP router with my GL-iNet router, and I’m re-setting up what was already working with the ISP router, and with it just a simple forwarding rule from WAN to LAN and use the WAN IP was enough to reach the service from everywhere. So, for this new setup, I have set my ISP router in bridge mode to completely delegate the routing work to the GL-iNet router… would you recommend to do otherwise and chain 2 routers ?

Besides, I tried the solution you propose. If I understand it well, the rule you suggest is exactly the same than the one I had, except it’s LAN to LAN instead of WAN to LAN (funny, in GL-iNet interface you cannot create LAN to LAN rule, even in LuCi interface actually, it’s only in editing a created rule that I could set LAN as source zone). Here is the result:


(Enable NAT Loopback is correctly ticked for both)

Unfortunately it still doesn’t work, same result as before, everyone can connect to the netcat using the WAN IP but the machine running the netcat listener. Did I miss anything ? Especially about the Source IP address field, I’m not sure what you meant but I also tried to force Source IP address with PC1 internal IP and external IP address with WAN IP but none of these worked.

When I use the WAN IP address I am coming from the inside, so when the kernel is scanning the firewall rules the source firewall zone (read interface) is the inside ethernet port not the outside internet port so the kernel does not match the rule, so we try to connect to port 8888 of the router … and probably fail.

By the way, I’m just thinking, if that is the case, wouldn’t this mean that the port forwarding rule should not match for any device using WAN IP from the inside ?
Because actually it does, I can request PC1 from PC2, both being in the LAN, using only the WAN to LAN port forwarding rule.

If I understand well, when PC2 requests PC1, it creates a packet <p(src, dst)> p1(192.168.8.212, wan_ip) and sends it to gateway 192.168.8.1, the router matches the rule and transforms it with DNAT into a p2(192.168.8.212, 192.168.8.112), so just changeing the destination IP, and then they respond to each other using packet’s src IP ?

So when PC1 requests itself, it creates p1(192.168.8.112, wan_ip) and sends it to the router, which according to the same rule should transform it into a p2(192.168.8.112, 192.168.8.112)… and this is a problem ? Is there a way to know if it’s the router that refuses to create such a packet or if it’s PC1 OS which drops it ?

And I’m not sure to understand how a port forwarding rule could do SNAT and rewrite the src address, while the fields are only matching rules, except the “Internal IP address” fields which is the dst address to rewrite, and that’s all ?

Hello DuxBellorum,

I was testing the new GL-1800AX, so had to swap back to my MT1300 to avoid leaking beta info (sure it would not) and to use tcpdump.

First of all, it actually did not quite behave the way I expected, once I put the network sniffer on, so let met explain with pictures this time!

The bit of the network thats important:
image

I have a router connected to the Internet, GL router connects to it over wifi with an external IP of 10.101.2.16. The GL Router LAN is 10.101.16.0/24. My PC is currently on 10.101.16.173, I have a service running on 10.101.16.195 port 8887. Traffic from the Internet to GL Router port 31887 is forwarded to 10.101.16.195 port 31887, my rule is:

When I try to connect from 10.101.16.173 via my Virgin Media external IP address the following happens.

From a network point of view, this is my PC reaching the Cisco Router in front of the GL Router, the Cisco sees this as an attempt to connect to port 31887, and politely tells my PC to “go away” with that Reset response.

So we need to get the GL-INET to deal with this. I wrote the following rule
in Avanced, Firewall Port Forward.
General Tab is the same as the WAN rule, but as you point out source zone is LAN not WAN.

The advanced tab, I set the following:

Not sure the hi-lighted option is as important as I thought, as you will see.

Now when I try to connect, the following happens.

I actually expected the source to 10.101.2.16 (external address), but that setting does not seem to do much.

you can follow the path in the wireshark, the packet from 10.101.16.173 to external address 31887 results in the packet being sent from 10.101.16.1 to 10.101.16.195:8887, reaching my service.

Check your firewall rule, make sure you save and apply in LuCI.

Hope that helps
Simon

Hello @smiths

Thanks for your reply ! This problem is turning me crazy :exploding_head:
So, if I got everything correctly, to match my problem, the question would be: are you able to connect to 10.101.16.195:8887 from 10.101.16.195 itself, using 77.?.?.?:31887 ?

Well, I also hope the highlighted option Loopback source IP is not important because I just don’t have it :slightly_smiling_face: I have a GL-AX1800 Flint on last stable 3.213 firmware, based on OpenWrt Chaos Calmer 15.05.1.
Here is what my whole LAN to LAN rule looks like:

I have no General or Advanced tab, here are the full options available.

Besides, I did some investigations with wireshark. With or without the LAN to LAN rule, I always get the same kind of failure (with is sightly different from the one you posted). Here is what happens when I try to request PC1 from PC1:
Wireshark_connection_fails

I just don’t get any response to my TCP SYN request from the router. While from any other computer, either on WAN or LAN, it works.

Fun fact 1: if I disable LAN to LAN rule, and disable NAT loopback in WAN to LAN, request from WAN are working but any request from LAN receives a Connection refused error (TCP RST,ACK), so similar to what you have shown.

Fun fact 2: when I request PC1 from PC2

  • when NAT loopback is enabled in LAN to LAN rule, I can see in wireshark that PC1 is exchanging TCP packets with router 192.168.8.1 (which is actually the same behaviour if I remove completely the LAN to LAN rule).
  • However, if I disable NAT loopback in LAN to LAN rule, I can see that PC1 is exchanging TCP packets with 192.168.8.212, so PC2 directly.

But in any case, I cannot find the combination that makes PC1 requesting PC1 working :frowning_face:
If you have any other idea… I don’t want to have to switch to my ISP router as main router, but for now it’s the only option I have to make it work.

Ah - Flint is based on an older openwrt.
I have one in store, I will dig out and see what is ocurring tomorrow.

Simon

1 Like

I can help debug, as I’m also experiencing a similar issue; my LAN servers are port-forwarded, and clients outside the network can connect fine. When an internal client on the LAN zone try to connect to the services via the site’s public IP, the connection times out. This applies for both TCP and UDP traffic. On firmware version 3.213, tracking this thread for suggested fixes / updates. My forwards look like the following:

config redirect
        option target 'DNAT'
        option name 'SERVICE_NAME'
        option src 'wan'
        option dest 'lan'
        option src_dport 'PORT_#'
        option dest_ip 'INTERNAL_IP'
        option dest_port 'PORT_#'
        option gl '1'
        option proto 'udp'

System info:

{
        "kernel": "4.4.60",
        "hostname": "gl-ax1800",
        "system": "ARMv7 Processor rev 4 (v7l)",
        "model": "Qualcomm Technologies, Inc. IPQ6018\/AP-CP03-C1",
        "release": {
                "distribution": "OpenWrt",
                "version": "Chaos Calmer",
                "revision": "a828782+r49254",
                "codename": "chaos_calmer",
                "target": "ipq\/ipq60xx",
                "description": "OpenWrt Chaos Calmer 15.05.1"
        }
}

Firstly… I don’t understand why a pc needs to find itself over a network…

Secondly wouldn’t the configuration be loop back node on each pc (127.0.0.1)?

My issue isn’t about the host itself not being able to “find” itself over the network, it’s that all internal LAN host connections time out when browsing to a domain that resolves to the public IP of the router they’re behind. In theory, port forwarding should allow for that, and indeed the “Enable NAT Loopback” option is checked when looking at the rule in the LuCI interface.

In video games for example, it’s not rare that the PC hosting the game also runs one of the clients playing it.
The server subscribes to a public games list that publishes the WAN IP so anyone in the world can connect to it. So you just have to setup the right port forwarding rule and it works.

It works like a charm with my ISP router (that I have put back into service). With my GL-AX1800 Flint, everybody can connect the game…but not me.

1 Like

Hi All,
I got around to firing up my Flint. You cannot set the forwards through Luci (advanced) web interface on the current version as posted by contaktd:

"description": "OpenWrt Chaos Calmer 15.05.1"

There is a beta build of Flint based on openwrt 21, which does let you set the forwards as I suggested in my initial answer. I had a quick play with the beta software - worked ok for me. YMMV - its beta.

You can “probably” config it using command line/luci. You do need 2 firewall redirect rules.
Rule 1: option src ‘wan’
Rule 2: option src ‘lan’

Traffic from outside originates from the Internet, so will come in via wan. Traffic from our local PC will originate from the lan, so we need rule 2 to match this traffic.

My setup
Server: 10.101.16.200
PC: 10.101.16.173
GL Router: lan: 10.101.16.1 <->wan: 10.101.2.16 ← NAT → ISP router lan: 10.101.0.1 ← NAT → Internet.

Just noted above, so that IP addresses below are explained.

The 2 rules - both were set up in advanced web interface, on the travel version of the slate, running the version 4 beta s/w:
For the external traffic

config redirect
        option src 'wan'
        option name 'HTTP-Proxy-Bullseye1'
        option src_dport '31887'
        option target 'DNAT'
        option dest_ip '10.101.16.200'
        option dest 'lan'
        list proto 'tcp'
        option dest_port '8887'
        option reflection_src 'external'

For internal traffic.

config redirect
        list proto 'tcp'
        option src_dport '31887'
        option dest_ip '10.101.16.200'
        option dest_port '8887'
        option src 'lan'
        option name 'HTTP-Proxy-Loop-Bullseye1'
        option dest 'lan'
        option reflection_src 'external'
        option target 'DNAT'

I point a browser on the PC to http://dns name:31887/page.html
This above gives following conversation when I visit the page in the browser. External IP address hidden as external ip.

root@GL-AXT1800:~# tcpdump -nnn -i br-lan tcp port 31887 or tcp port 8887
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
21:41:26.296043 IP 10.101.16.173.18285 > external_ip.31887: Flags [S], seq 1355366318, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
21:41:26.296316 IP 10.101.2.16.18285 > 10.101.16.200.8887: Flags [S], seq 1355366318, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
21:41:26.298030 IP 10.101.16.200.8887 > 10.101.2.16.18285: Flags [S.], seq 707098590, ack 1355366319, win 64240, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
21:41:26.298159 IP external_ip.31887 > 10.101.16.173.18285: Flags [S.], seq 707098590, ack 1355366319, win 64240, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
21:41:26.301028 IP 10.101.16.173.18285 > external_ip.31887: Flags [.], ack 1, win 513, length 0
21:41:26.301265 IP 10.101.2.16.18285 > 10.101.16.200.8887: Flags [.], ack 1, win 513, length 0

There was more data, but the 3-way handshake above should demonstrate the rules working.

Hope this helps.

Simon

Hello,

Giving an update on this topic because I’ve just flashed the latest 4.1.0 firmware for Flint, and gave it another try… and it works ! Without setting anything more than a simple port forwarding rule, like I was initially doing.

It seems like this new v4 firmware has made of Flint a much better product than it started out