Skip Navigation

Forward packets Wireguard to local subnet, with Nftables. [ solved ]

Hi,

I would like to forward packets that come from a wireguard connection to a local subnet

environment
  • Client: connected to server trough wireguard IP 192.168.X.2
  • server: connected to Client trough wireguard IP 192.168.X.1 and 192.168.Y.1 ( it's not systemd free ¯(ツ)/¯  )
  • aMachine: on the same subnet as server IP 192.168.Y.2

   

on the server I've done

 bash
    
#I don't know if this is necessary ?
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl --system

  

I've added the following rule to the nftables config on server but it seem the packet get lost ?

 nft
    
#added inside existing table `table ip Tip {}`
chain chPreRoute {
type nat hook prerouting priority 0; policy accept;
iif wg0 icmp type echo-request dnat to 192.168.Y.2
}

  
6 comments
  • Here's mine, if this helps? I have WireGuard running on an Alpine LXC on my LAN, and use it to connect back home. I can SSH to or use resources from any other machine on the LAN while connected. You'll need to amend the include rules to match whatever distro you're using (the paths will be different), and you can add whatever rules you wish under the LAN section to allow local access to the WireGuard 'host' for other services (eg SSH).

    There's also a lot of useful info on the Pro Custodibus blog.

     undefined
        
    #!/usr/sbin/nft -f
    flush ruleset
    
    define pub_iface = "eth0"
    define wg_iface = "wg0"
    define wg_port = "51820"
    
    table inet my_table {
        set LANv4 {
            type ipv4_addr
            flags interval
    
            elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
        }
        set LANv6 {
            type ipv6_addr
            flags interval
    
            elements = { fd00::/8, fe80::/10 }
        }
    
        chain my_input_lan {
            ip6 daddr fe80::/64 udp dport dhcpv6-client accept comment "Accept DHCPv6 configuration"
            udp dport netbios-ns accept comment "Accept NetBIOS Name Service (nmbd)"
            udp dport netbios-dgm accept comment "Accept NetBIOS Datagram Service (nmbd)"
            tcp dport netbios-ssn accept comment "Accept NetBIOS Session Service (smbd)"
            udp sport { bootpc, 4011 } udp dport { bootps, 4011 } accept comment "Accept PXE"
            tcp dport ssh accept comment "Accept SSH on port 22"
        }
    
        chain my_input {
            type filter hook input priority 0; policy drop;
    
            iif lo accept comment "Accept any localhost traffic"
            ct state invalid counter drop comment "Drop invalid connections"
            ct state established,related accept comment "Accept traffic originated from us"
    
            tcp dport 113 reject with icmpx type port-unreachable \
                    comment "Reject AUTH to make it fail fast"
    
            # ICMPv4
    
            ip protocol icmp icmp type {
                echo-reply,  # type 0
                destination-unreachable,  # type 3
                echo-request,  # type 8
                time-exceeded,  # type 11
                parameter-problem,  # type 12
            } accept \
            comment "Accept ICMP"
    
            # ICMPv6
    
            icmpv6 type {
                destination-unreachable,  # type 1
                packet-too-big,  # type 2
                time-exceeded,  # type 3
                parameter-problem,  # type 4
                echo-request,  # type 128
                echo-reply,  # type 129
            } accept \
            comment "Accept basic IPv6 functionality"
    
            icmpv6 type {
                nd-router-solicit,  # type 133
                nd-router-advert,  # type 134
                nd-neighbor-solicit,  # type 135
                nd-neighbor-advert,  # type 136
            } ip6 hoplimit 255 accept \
            comment "Allow IPv6 SLAAC"
    
                    icmpv6 type {
                            mld-listener-query,  # type 130
                            mld-listener-report,  # type 131
                            mld-listener-reduction,  # type 132
                            mld2-listener-report,  # type 143
                    } ip6 saddr fe80::/10 accept \
                    comment "Allow IPv6 multicast listener discovery on link-local"
    
                    ip6 saddr fe80::/10 udp sport 547 udp dport 546 accept \
                    comment "Accept DHCPv6 replies from IPv6 link-local addresses"
    
            ip protocol igmp accept comment "Accept IGMP"
            udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
            udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
    
            ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges"
            ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges"
    
            udp sport bootpc udp dport bootps ip saddr 0.0.0.0 ip daddr 255.255.255.255 accept comment "Accept DHCPDISCOVER (for DHCP-Proxy)"
    
            # Accept all WireGuard packets received on a public interface
            iifname $pub_iface udp dport $wg_port accept
            # Accept all DNS packets from wg clients sent to a DNS server running on the same local server (i.e. if running DNS and WG on the same VPS). 
            # Doesn't seem necessary if the DNS is just on a separate server on the LAN.
            iifname $wg_iface tcp dport 53 accept
            iifname $wg_iface udp dport 53 accept
            counter comment "count dropped packets"
        }
    
        chain forward {
            type filter hook forward priority 0; policy drop;
            ct state vmap { invalid : drop, established : accept, related : accept }
            iifname $wg_iface oifname $pub_iface accept
            reject with icmpx type host-unreachable
        }
    
        chain my_output {
            type filter hook output priority filter; policy accept;
            # Accept every outbound connection
            }
    }
    
    table inet nat {
        chain postrouting {
            type nat hook postrouting priority 100; policy accept;
            iifname $wg_iface oifname $pub_iface masquerade
        }
    }
    
    # The state of stateful objects saved on the nftables service stop.
    include "/var/lib/nftables/*.nft"
    
    # Rules
    include "/etc/nftables.d/*.nft"
    
    
      
  • Hi, Thank to all of you.

    I made a test environment with the following.

    • Machine A: 192.168.Y.1
    • Machine B: 192.168.Y.2
    • Machine C: 192.168.Y.3

    The goal is to send a ping A to B, B forward to C

    So ping -4c 1 192.168.y.2 from A, should ping B fw C

    I've set the following rule in /etc/nftables.conf

     nft
        
    table ip Tip {
            chain prerouting {
                    type nat hook prerouting priority dstnat; policy accept;
                    iif "eth0" ip protocol icmp dnat to 192.168.y.3
            }
            chain postrouting {
                    type nat hook postrouting priority 100; policy accept;
                    ip saddr 192.168.y.3 masquerade
            }
    }
    
    
      

    but is not working :'(

    I see B receive the package

     undefined
        
    preroute: IN=eth0 OUT= MAC=▒▒ SRC=192.168.y.1 DST=192.168.y.2 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21398 DF PROTO=ICMP TYPE=8 CODE=0 ID=17950 SEQ=1
    
    
      

    but it seem C receive nothing..

    Any ideas ?

    • SOLVED

      The following works !

      I guess one of my others rules was blocking

       nft
          
      table ip Tip {
              chain prerouting {
                      type nat hook prerouting priority -100; policy accept;
                      ip daddr 192.168.y.2 log prefix "forwarded " dnat to 192.168.y.3
              }
              chain postrouting {
                      type nat hook postrouting priority 100; policy accept;
                      masquerade
              }
              chain INPUT {
                      type filter hook input priority filter; policy accept;
              }
              chain FORWARD {
                      type filter hook forward priority filter; policy accept;
              }
              chain OUTPUT {
                      type filter hook output priority filter; policy accept;
              }
      }
      
        
6 comments