3

I am trying to set up a port forwarding proxy using a Raspberry Pi 4 with NFTables. I want to duplicate the simple port forwarding capabilities of a cheap home nat router. This a component of a larger remote admin application I am working on.

I can get it to redirect ports on the host itself using redirect. But I cannot get it to forward anything beyond the host.

I have routing enabled. But I would also like it to work from within the lan. I don't think this is a factor.

Looking at journalctl, it appears my rule is getting triggered. But the browser never brings up the page.

  • port 80 is redirecting to a web app running locally on 8088 and this works
  • port 81 is supposed to forward to the admin screen on a printer
  • port 82 is trying to forward to an external web site
$ curl -i http://192.168.10.32:81
^C (no response)
$

Log and config are below.

Update: I failed to mention that the device was initially also running WireGuard. To simplify, I have disabled WireGuard and relisted the config and logs. So it's a pretty vanilla config now.

# nft list ruleset
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        ct state invalid drop
        iifname "lo" accept
        ip protocol icmp accept
        tcp dport { ssh, 22222 } ct state new log prefix "[nftables] New SSH Accepted: " accept
        tcp dport { http, https, 81, 82, omniorb } accept
        pkttype { host, broadcast, multicast } drop
        log prefix "[nftables] Input Denied: " flags all counter packets 0 bytes 0 drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}
table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        masquerade
    }

    chain prerouting {
        type nat hook prerouting priority -100; policy accept;
        tcp dport http log prefix "redirect to 8088 " redirect to :omniorb
        tcp dport 81 log prefix "pre redirect to printer " level debug dnat to 192.168.10.10:http
        tcp dport 82 log prefix "redirect to web " dnat to 104.21.192.38:http
    }
}

  • redirect 80 to 8088 works
  • forward to printer and web do not work
Apr 17 13:59:48 douglas kernel: redirect to 8088 IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=20702 DF PROTO=TCP SPT=44984 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:00:50 douglas kernel: pre redirect to printer IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=2569 DF PROTO=TCP SPT=34024 DPT=81 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:00:51 douglas kernel: pre redirect to printer IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=2570 DF PROTO=TCP SPT=34024 DPT=81 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:00:53 douglas kernel: pre redirect to printer IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=2571 DF PROTO=TCP SPT=34024 DPT=81 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:00:59 douglas kernel: redirect to web IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=36328 DF PROTO=TCP SPT=44326 DPT=82 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:01:00 douglas kernel: redirect to web IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=36329 DF PROTO=TCP SPT=44326 DPT=82 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:01:02 douglas kernel: redirect to web IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=36330 DF PROTO=TCP SPT=44326 DPT=82 WINDOW=64240 RES=0x00 SYN URGP=0 
Apr 17 14:01:06 douglas kernel: redirect to web IN=eth0 OUT= MAC=dc:a6:32:ab:9c:76:f4:6d:04:63:aa:7d:08:00 SRC=192.168.10.20 DST=192.168.10.32 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=36331 DF PROTO=TCP SPT=44326 DPT=82 WINDOW=64240 RES=0x00 SYN URGP=0 
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:ab:9c:76 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.32/24 brd 192.168.10.255 scope global dynamic noprefixroute eth0
       valid_lft 603659sec preferred_lft 528059sec
    inet6 fe80::2cd9:f195:bfe6:38e8/64 scope link 
       valid_lft forever preferred_lft forever
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether dc:a6:32:ab:9c:77 brd ff:ff:ff:ff:ff:ff
# ip route
default via 192.168.10.1 dev eth0 proto dhcp src 192.168.10.32 metric 202 
192.168.10.0/24 dev eth0 proto dhcp scope link src 192.168.10.32 metric 202
#  sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
4
  • From your logs one can see you are behind CGNAT and are using a wireguard tunnel. While normally an answer would be easy, considering you're using a VPN and didn't mention it can most likely not make things working as intended with a simple answer. So please provide the missing network topology and routing configuration. Also why such setup is in place (most probably to overcome CGNAT, but you have to explain).
    – A.B
    Commented Apr 17, 2021 at 16:34
  • Also whatever tutorial tells to use ip6 nexthdr ipv6-icmp is wrong, because there are subtle cases where this doesn't work. But that's not related to the question.
    – A.B
    Commented Apr 17, 2021 at 16:36
  • Good point. I have simplified the config. WireGuard is disabled as is the WiFi. So eth0 is the only active interface now. But the problem persists. The devices are all in the same room in the same switch. I'm sure I am missing something stupid. Thanks for the fast input... Using curl from another host, I get no response. But the log says my rule is getting triggered. Commented Apr 17, 2021 at 18:17
  • about ip6 nexthdr ipv6-icmp accept (that should not be used) use instead meta nfproto ipv6 meta l4proto ipv6-icmp accept. See these two Q/A where I made a rationale about it: unix.stackexchange.com/questions/408497/… , superuser.com/questions/1560376/… . Depending on the nftables version (including current) the nfproto part might not be displayed back, that would be a minor bug.
    – A.B
    Commented Apr 17, 2021 at 19:48

1 Answer 1

6

Your current setup doesn't work simply because forwarding is disabled, despite:

#  sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

because of the type filter hook forward chain set to policy drop:

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

If you want to restrict forwarding, in case some systems wrongly sets the RPi4 as its gateway, rather than just forwarding everything (by changing above policy from drop to accept or by completely removing the forward chain), you can choose to forward only packets that underwent a dnat translation:

nft add rule inet filter forward ct status dnat accept

This suffices for all packets of the flow, as this information is stored in the unique conntrack lookup entry that was created (and is used for both directions and every packet).

1
  • 2
    That was it! It seems computers only do what humans tell them to do. I knew it was something stupid. I could not move because I was standing on my foot... I owe you a beer! Thanks Commented Apr 17, 2021 at 20:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .