nftables ip6 route to localhost/ ipv6 nat to loopback
I'm trying to route incoming http internet traffic to [::1]:8080 which is where my http server binds to. I'm using nftables on an IPv6-only device. If I add following rules:
sudo nft flush ruleset
sudo nft add table ip6 nat
sudo nft add chain ip6 nat prerouting { type nat hook prerouting priority 0 \; }
sudo nft add chain ip6 nat postrouting { type nat hook postrouting priority 100 \; }
sudo nft add rule ip6 nat prerouting ip6 daddr [global-ip6] tcp dport 80 dnat to ::1 :8080
sudo nft list ruleset
with resulting ruleset:
table ip6 nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
ip6 daddr [global-ip6] tcp dport http dnat to [::1]:http-alt
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
}
}
then requests to [global-ip6]:80 get swallowed (there is no connection refused error) but no connection is established.
If I use one of the rules
sudo nft add rule ip6 nat prerouting tcp dport 80 redirect to 8080
or
sudo nft add rule ip6 nat prerouting ip6 daddr [global-ip6] tcp dport 80 dnat to [global-ip6] :8080
and bind my program to [global-ip6]:8080
, then communication works as expected.
Do you have an idea what I am missing? I tried out some rules in the postrouting
and input
chains but couldn't get it to work. Back with IPv4 and iptables I had to do sudo sysctl -w net.ipv4.conf.all.route_localnet=1
, maybe there is a similar IPv6 flag?
Unfortunately you cannot achieve what you want with the nftables.
After the dnat target the destination address is rewritten to the loopback address (::1
), and then the incoming packet is processed by the routing code. But any incoming packet with the loopback destination address has been received from outside MUST be dropped by RFC 4291 2.5.3. There aren't any sysctl
variables to change this behavior.
You can run some proxy app, that will be accept connection on the external address and connects to the application that listens the loopback address.