I've been using openwrt my raspberry pi CM4 for a while now and I've recently upgraded to 21.02.5.
In the firewall I have some "port forward" rules sending e.g. port 80 and port 443 on the wan interface to a server on my lan.
Previously, connecting on the public IP address from within the lan worked fine and correctly redirected the traffic to the internal address so I had no problem connecting to it from within the network. Since the upgrade however this seems to have stopped working (without the rules having changed). For completeness, I did start using docker on openwrt, but removing it and all the interfaces/zones for it does not seem to have any effect.
Since it didn't work, I started troubleshooting and launched a tcpdump on the br-lan interface to see what's going on, and surely, while tcpdump is running on the br-lan interface I can properly connect to it. Note that this only happens when running on br-lan. If I run on the actual physical interface (eth0) it does not work.
Does that ring a bell to anyone?
EDIT:
I'm running tcpdump like this
tcpdump -n -i br-lan host 10.0.2.1 and port 443
Here's the firewall configuration (/etc/config/firewall)
root@pirouter:~# cat /etc/config/firewall
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'
list device 'tun+'
config zone
option name 'wan'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'
list network 'wan'
list network 'wan6'
list network 'WAN'
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 src_ip 'fc00::/6'
option dest_ip 'fc00::/6'
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 'Support-UDP-Traceroute'
option src 'wan'
option dest_port '33434:33689'
option proto 'udp'
option family 'ipv4'
option target 'REJECT'
option enabled '0'
config include
option path '/etc/firewall.user'
config redirect
option target 'DNAT'
option name 'http'
list proto 'tcp'
option src 'wan'
option src_dport '80'
option dest 'lan'
option dest_ip '10.0.2.1'
option dest_port '80'
list reflection_zone 'lan'
config redirect
option target 'DNAT'
option name 'https'
list proto 'tcp'
option src 'wan'
option src_dport '443'
option dest 'lan'
option dest_ip '10.0.2.1'
option dest_port '443'
list reflection_zone 'lan'
config redirect
option target 'DNAT'
option name 'ssh'
list proto 'tcp'
option src 'wan'
option src_dport '22'
option dest 'lan'
option dest_ip '10.0.2.1'
option dest_port '22'
list reflection_zone 'lan'
config redirect
option target 'DNAT'
option name 'et'
list proto 'udp'
option src 'wan'
option src_dport '27960'
option dest 'lan'
option dest_ip '10.0.2.1'
option dest_port '27960'
list reflection_zone 'lan'
config redirect
option target 'DNAT'
option name 'znc'
list proto 'tcp'
option src 'wan'
option src_dport '6697'
option dest 'lan'
option dest_ip '10.0.2.1'
option dest_port '6697'
list reflection_zone 'lan'
config rule 'ovpn'
option name 'Allow-OpenVPN'
option src 'wan'
option dest_port '1194'
option proto 'udp'
option target 'ACCEPT'
config redirect
option dest 'lan'
option target 'DNAT'
option name 'torrent'
list proto 'tcp'
option src 'wan'
option src_dport '51413'
option dest_ip '10.0.2.1'
option dest_port '51413'
config redirect
option target 'DNAT'
option name 'intercept-dns'
option src 'lan'
option src_dport '53'
#config zone 'docker'
# option input 'ACCEPT'
# option output 'ACCEPT'
# option forward 'ACCEPT'
# option name 'docker'
# list network 'docker'
config rule
option name 'allow adguard web'
list proto 'tcp'
option src 'lan'
option dest_port '8080'
option target 'ACCEPT'
and (redacted) network configuration (/etc/config/network)
root@pirouter:~# cat /etc/config/network
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 'fdba:717d:a9cc::/48'
config device
option name 'br-lan'
option type 'bridge'
list ports 'eth0'
config interface 'lan'
option device 'br-lan'
option proto 'static'
option netmask '255.255.255.0'
option ipaddr '10.0.2.254'
list dns '10.0.2.253'
list dns '10.0.2.252'
list dns_search 'local'
option ip6assign '60'
config interface 'WAN'
option proto 'pppoe'
option device 'eth1'
option username 'foobar'
option password 'faa'
option ipv6 'auto'
#config interface 'docker'
# option device 'docker0'
# option proto 'none'
# option auto '0'
#
#config device
# option type 'bridge'
# option name 'docker0'
As far as iptables are concerned the reflection rules are there and have some hits. You can try to reset the counters and try again without the tcpdump running to verify that the counters will increase.
Update after a discussion on IRC:
it seems when I run tcpdump -p, thus not putting the br-lan interface in promiscuous mode, the nat reflection does not work.
So the fact that the interface gets put in promiscuous mode makes the NAT reflection work. Hope that's a clue for someone.
So, it seems docker is interfering after all. On a fresh install it works fine until I install the dockerd package. Even if I disable the service with /etc/init.d/dockerd disable it still does not work. I have to actually remove the package with opkg remove dockerd
Even when I disable all rules, interfaces and zones created by dockerd it still happens.
it's caused by the sysctl file created by the dockerd package:
# Do not edit, changes to this file will be lost on upgrades
# /etc/sysctl.conf can be used to customize sysctl settings
# enable bridge firewalling for docker
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
Only when I disable those it works. Still looking how I can fix that.
So it only hits the mangle table prerouting chain and the nat table prerouting chain and then processing stops. I know it hits the proper NAT prerouting rule because I also tried adding a log statement just before and just after that rule. Only the one just before gets logged.
Here's the log when bridge firewalling is disabled:
I had the same issue on OpenWRT 22.03.2 on x86/64. It was also triggered by the sysctl changes made by dockerd and momentarily "fixed" by putting br-lan in promiscuous mode. Reverting net.bridge.bridge-nf-call-iptables and net.bridge.bridge-nf-call-ip6tables to 0 fixed NAT reflection with no change to Docker's behavior that I can see.
I am also wondering whether disabling these sysctls contrary to what Docker wants is OK. I found that this is actually recommended by Oracle Linux's documentation but I'm not sure if the reasons they have for recommending it apply here as well.
Another thing to consider is disabling nf-call-iptables globally with the sysctl and enabling it only for Docker's bridges through /sys/class/net/docker0/bridge/nf_call_iptables, etc. - this seems more like a proper solution but I am not sure.
As noted above, the rule is OK. Here's an example rule:
config redirect
option target 'DNAT'
option src 'wan'
option dest 'lan'
option src_dport '51413'
option dest_port '51413'
option dest_ip 'xxx.xxx.xxx.xxx'
option name 'BitTorrent_dsktp'
list proto 'tcp'
list proto 'udp
Are you're saying the BitTorrent doesn't work until you run tcpdump on br-lan?