How to Masquerade with nftables in Linux

linuxnat;networkingnftables

I have PC-1 with 2 uplinks (modem1 and modem2) and LAN on eth0 interface:

# ip -c -brief addr
lo               UNKNOWN        127.0.0.1/8
eth0             UP             192.168.0.7/24
modem2           UNKNOWN        10.73.15.79/27
modem1           UNKNOWN        10.176.229.31/26

('unknown' state for modem1 and modem2 is seemed ok).

I've setup routing as follows:

# ip -c rule
0:      from all lookup local
32764:  from 10.73.15.79 lookup 2
32765:  from 10.176.229.31 lookup 1
32766:  from all lookup main
32767:  from all lookup default

# ip -c route ls table main
default
        nexthop via 10.176.229.32 dev modem1 weight 1
        nexthop via 10.73.15.80 dev modem2 weight 1
10.73.15.64/27 dev modem2 proto kernel scope link src 10.73.15.79
10.176.229.0/26 dev modem1 proto kernel scope link src 10.176.229.31
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.7

# ip -c route ls table 1
default via 10.176.229.32 dev modem1
10.73.15.64/27 dev modem2 scope link
10.176.229.0/26 dev modem1 scope link src 10.176.229.31
127.0.0.0/8 dev lo scope link
192.168.0.0/24 dev eth0 scope link

# ip -c route ls table 2
default via 10.73.15.80 dev modem2
10.73.15.64/27 dev modem2 scope link src 10.73.15.79
10.176.229.0/26 dev modem1 scope link
127.0.0.0/8 dev lo scope link
192.168.0.0/24 dev eth0 scope link

So, locally on PC-1, I have internet access.

I have also PC-2 within the LAN, and would like to setup masquerade on PC-1 to provide internet for PC-2.

I'm trying the following nftables config:

# nft list ruleset
table ip filter {
        chain input {
                type filter hook input priority 0; policy accept;
        }

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

        chain output {
                type filter hook output priority 0; policy accept;
        }
}
table ip nat {
        chain input {
                type nat hook input priority 0; policy accept;
                ip protocol icmp accept
        }

        chain prerouting {
                type nat hook prerouting priority 0; policy accept;
        }

        chain postrouting {
                type nat hook postrouting priority 100; policy accept;
                ip saddr 192.168.0.0/24 oifname "modem*" masquerade
        }

        chain output {
                type nat hook output priority 0; policy accept;
        }
}

But it does not work. I have tried several different versions of the config, but unsuccessfully. How can I setup nftables for masquerade?

I also setup:

# sysctl -w net.ipv4.ip_forward="1"
net.ipv4.ip_forward = 1

Linux kernel 4.19.0

Edit:

I have configured masquerade with nftables on another PC successfully.
The difference noticed by me (I do not know whether it has sense):

On PC-1:

# sudo iptables -S
iptables: No chain/target/match by that name.

On another PC:

# sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

Best Answer

So, the problem - IPV4_DEVCONF_FORWARDING was unset on eth0 interface. I have set it with help of libnl - method rtnl_link_inet_set_conf.

Edit:

This is the same option sysctl net.ipv4.conf.eth0.forwarding. Thanks for @A.B.