Server behind OpenWrt router visible on LAN but not WAN despite port forwarding

I have a Linksys EA8300 router running OpenWRT 22.03.0, r19685-512e76967f. My
ISP-provided router-modem combo is in bridge mode. Behind the router I have a
laptop server running OpenBSD 7.1 and serving with the version of httpd included
in the base system. My router has the default OpenWRT firewall configuration
except for forwarding to port 80 of my router. (I have tried with port 8080, as
well.) I have dynamic DNS set up with Dynu. The service is running on the
router. A test html page served on my server is reachable within my LAN, but not
from WAN. I can ping the server from WAN using either a URL or IP address. A
tcpdump on the router shows incoming connections to the public IP, then to the
server's local IP, then from the server to the connecting client, but no html
content is rendered on the client device. (I have tried this from outside the
network.) My question is: How can I make my server's html content visible on the
WAN? I am new to this, so I suspect that I have made some obvious mistake, but
perhaps others might be helped by having an answer to this question.

We need to see your config.

Please copy the output of the following commands and post it here using the "Preformatted text </> " button:
grafik
Remember to redact passwords, MAC addresses and any public IP addresses you may have:

cat /etc/config/network
cat /etc/config/firewall

Network config

config interface 'loopback'
	option device 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix '[redacted]'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'eth0'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.1.1'
	option netmask '255.255.255.0'
	option ip6assign '60'
	list dns '9.9.9.9'

config interface 'wan'
	option device 'eth1'
	option proto 'dhcp'
	option peerdns '0'
	list dns '9.9.9.9'
	list dns '149.112.112.112'

config interface 'wan6'
	option device 'eth1'
	option proto 'dhcpv6'

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '1 2 3 4 0'

Firewall config

config defaults
	option syn_flood '1'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone
	option name 'lan'
	list network 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'

config zone
	option name 'wan'
	list network 'wan'
	list network 'wan6'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'

config forwarding
	option src 'lan'
	option dest 'wan'

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'lan'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'Server'
	option src 'wan'
	option dest_ip '192.168.1.207'
	option dest_port '80'
	option src_dport '80'

Are you certain you have a public ip address on your wan? What are the first two octets of the ip address shown in the openwrt status page under ipv4 upstream? The part in bold: aaa.bbb.ccc.ddd

Are you sure you're httpd process is configured to accept connections from any IP?

If you wget from the wan, what output do you get?

Are you doing that on all interfaces or the WAN interface (to ensure the package leaves the router).

What is the package that is sent?

No octets are in bold on the Status > Overview page of LuCI (perhaps this is an artifact of my browser), but the first two octets of the IPv4 upstream address are 70.178.

How did you determine this?

You can also issue the command ifconfig and look for the ip address there.

Output of wget:

Resolving [redacted URL] ([redacted URL])... 70.178.xxx.xxx, [redacted IPv6]
Connecting to [redacted URL] ([redacted URL])|70.178.xxx.xxx|:80... failed: Connection timed out.
Connecting to [redacted URL] ([redacted URL])|[redacted IPv6]|:80... failed: Connection timed out.

wget will always return a public ip. This ip may or may not actually be your router’s actual wan ip.

What is the output of ifconfig? Does that ip show up in there?

Output of ifconfig:

br-lan    Link encap:Ethernet  HWaddr [redacted]  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: [redacted] Scope:Global
          inet6 addr: [redacted] Scope:Global
          inet6 addr: [redacted] Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2130182 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3271557 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1460091617 (1.3 GiB)  TX bytes:3690769894 (3.4 GiB)

eth0      Link encap:Ethernet  HWaddr [redacted] 
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2235 errors:0 dropped:0 overruns:0 frame:0
          TX packets:138531 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:178695 (174.5 KiB)  TX bytes:31844492 (30.3 MiB)

eth1      Link encap:Ethernet  HWaddr [redacted]  
          inet addr:70.178.xxx.xxx  Bcast:70.178.yyy.yyy  Mask:255.255.255.0
          inet6 addr: [redacted] Scope:Link
          inet6 addr: [redacted] Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4703019 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2182153 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:3770877652 (3.5 GiB)  TX bytes:1480291601 (1.3 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:13688 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13688 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1383384 (1.3 MiB)  TX bytes:1383384 (1.3 MiB)

wlan0     Link encap:Ethernet  HWaddr [redacted] 
          inet6 addr: [redacted] Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:557634 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1314591 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:240203310 (229.0 MiB)  TX bytes:1313441328 (1.2 GiB)

wlan1     Link encap:Ethernet  HWaddr [redacted]  
          inet6 addr: [redacted] Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1512488 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2253068 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1210450270 (1.1 GiB)  TX bytes:2361453120 (2.1 GiB)

wlan2     Link encap:Ethernet  HWaddr [redacted]  
          inet6 addr: [redacted] Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:142480 errors:0 dropped:0 overruns:0 frame:0
          TX packets:326041 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:46445961 (44.2 MiB)  TX bytes:197165502 (188.0 MiB)

Looks like you do have a proper public ipv4 address. That is good.

Is your web server running on port 80 or port 443?

What happens if you locally connect to http://192.168.1.207:80 ?

Port 80 for now.
curl and wget both fetch the test index page at http://192.168.1.207:80.

tcpdump -n -i any tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
00:13:30.945714 IP [external client IP] > [public IP].80: Flags [S], seq 1312321576, win 64860, options [mss 1380,sackOK,TS val 2525574595 ecr 0,nop,wscale 7], length 0
00:13:30.945953 IP [external client IP] > 192.168.1.207.80: Flags [S], seq 1312321576, win 64860, options [mss 1380,sackOK,TS val 2525574595 ecr 0,nop,wscale 7], length 0
00:13:30.945989 IP [external client IP] > 192.168.1.207.80: Flags [S], seq 1312321576, win 64860, options [mss 1380,sackOK,TS val 2525574595 ecr 0,nop,wscale 7], length 0
00:13:30.946505 IP 192.168.1.207.80 > [external client IP]: Flags [S.], seq 1243927315, ack 1312321577, win 16384, options [mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,TS val 603814621 ecr 2525574595], length 0
00:13:30.946505 IP 192.168.1.207.80 > [external client IP]: Flags [S.], seq 1243927315, ack 1312321577, win 16384, options [mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,TS val 603814621 ecr 2525574595], length 0
00:13:30.946664 IP [public IP].80 > [external client IP]: Flags [S.], seq 1243927315, ack 1312321577, win 16384, options [mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,TS val 603814621 ecr 2525574595], length 0

On server:

cat /etc/httpd.conf
# $OpenBSD: httpd.conf,v 1.22 2020/11/04 10:34:18 denis Exp $
server "[redacted URL]" {
  listen on * port 80
  root "/test"
}

How are you testing the wan connectivity? Are you testing from your lab or from a cellular connection/external network?

I would do -i WAN so that you are sure the package leaves on the right interface
Also record the traffic with tcpdump and check it on you PC with wireshark to see what is being sent to the client.
https://www.wireshark.org/docs/wsug_html_chunked/AppToolstcpdump.html

Sorry, perhaps I am missing something.

tcpdump -n -i WAN tcp port 80
tcpdump: WAN: No such device exists
tcpdump --list-interfaces
1.eth0 [Up, Running]
2.eth1 [Up, Running]
3.br-lan [Up, Running]
4.wlan2 [Up, Running]
5.wlan1 [Up, Running]
6.wlan0 [Up, Running]
7.any (Pseudo-device that captures on all interfaces) [Up, Running]
8.lo [Up, Running, Loopback]

I am testing whether I can access the html on WAN both by using a cellular network and by using a workstation connected to the LAN. The result is the same in both cases.

Try lowercase ‘wan’ or eth1 for the tcp dump.

I don’t see anything wrong with your config, so it is plausible your isp is blocking port 80.

1 Like