From: Marc SCHAEFER <schaefer@alphanet.ch>
To: netfilter@vger.kernel.org
Subject: nftables DNAT routes to wrong iface
Date: Sat, 25 Jan 2025 16:55:49 +0100 [thread overview]
Message-ID: <Z5UJheaMk+bZsEFe@alphanet.ch> (raw)
Hello,
I am trying to do this:
Both local IP addresses, when access from outside:
enp2s0.310: 193.72.186.130:8080
br0: 46.140.72.218:8080
are DNATed to
enp2s0.202: 192.168.202.10:80 (a remote machine)
I know there are two steps:
- the incoming DNAT in prerouting (and the forward accept)
-> this part I am stuck, see below
- then when the reply comes back, route to the proper interface where
it came from (using conntrack + marks + specific routing tables)
-> this part I have not done yet -- it would be required for
193.72.186.130:8080 obviously because the default route
does not go there.
What I observe:
telnet 46.140.72.218 8080 from outside works (*), it connects to 192.168.202.10:80
and there is nothing bizarre in tcpdump either on br0 nor on
enp2s0.202 (no delays, lost packets, e.g.) (**)
telnet 193.72.186.130 8080 gives this on enp2s0.300
IP 193.72.186.190.52636 > 193.72.186.130.8080 (normal)
IP 193.72.186.190.52636 > 192.168.202.10.80 (good, it was DNATted, BUT should be on enp2s0.202!)
aka the DNAT is executed, but then 192.168.202.10 is not routed
correctly. From the diagram https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks
I thought that routing would be done AFTER prerouting/DNAT.
The routing table has:
default via 46.140.72.217 dev br0 onlink
46.140.72.216/29 dev br0 proto kernel scope link src 46.140.72.218
192.168.202.0/24 dev enp2s0.202 proto kernel scope link src 192.168.202.2
193.72.186.128/26 dev enp2s0.300 proto kernel scope link src 193.72.186.130
(*) not from 193.72.186.0/24, however, gets the same bug.
The nftables config:
table ip filter {
# obviously a later goal is also to encode the L4 protocol here
# and not hardcode it in the prerouting
map multihoming_ext {
type ipv4_addr . inet_service : ipv4_addr . inet_service
elements = { 193.72.186.130 . 8080 : 192.168.202.10 . 80,
46.140.72.218 . 8080 : 192.168.202.10 . 80 }
}
set w_all {
type ipv4_addr
flags interval
elements = { 46.140.72.216/29,
192.168.202.1, 193.72.186.0/24
}
}
chain input {
type filter hook input priority filter; policy drop;
ct state invalid counter packets 3 bytes 120 drop
ct state { established, related } counter packets 1092 bytes 76846 accept
iif "lo" counter packets 0 bytes 0 accept
counter packets 324 bytes 13539 jump whitelist
counter packets 323 bytes 13455 jump blacknets
counter packets 323 bytes 13455 jump blacklist
counter packets 323 bytes 13455 jump incoming
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state invalid counter packets 0 bytes 0 drop
ct state { established, related } counter packets 12 bytes 548 accept
# already after DNAT, obviously
iifname "br0" ip daddr 192.168.202.10 tcp dport 80 accept
iifname "enp2s0.300" ip daddr 192.168.202.10 tcp dport 80 accept
}
chain output {
type filter hook output priority filter; policy accept;
ct state invalid counter packets 0 bytes 0 drop
ct state { established, related } counter packets 890 bytes 182096 accept
oif "lo" counter packets 0 bytes 0 accept
counter packets 1 bytes 76 jump outgoing
}
chain rejectcounter {
meta l4proto tcp counter packets 0 bytes 0 reject with tcp reset
meta l4proto udp counter packets 0 bytes 0 reject
counter packets 0 bytes 0 drop
}
chain dropcounter {
counter packets 320 bytes 13349 drop
}
chain whitelist {
ip saddr @w_all counter packets 1 bytes 84 accept
}
chain blacknets {
}
chain blacklist {
}
chain incoming {
icmp type echo-request counter packets 3 bytes 106 accept
icmp type echo-reply counter packets 0 bytes 0 accept
tcp dport 22 ip saddr { 46.140.72.216/29, 192.168.202.1, 193.72.186.0/24 } counter packets 0 bytes 0 jump dropcounter
udp dport 22 ip saddr { 46.140.72.216/29, 192.168.202.1, 193.72.186.0/24 } counter packets 0 bytes 0 jump dropcounter
counter packets 320 bytes 13349 jump dropcounter
}
chain outgoing {
}
chain multihoming_prerouting {
type nat hook prerouting priority dstnat; policy accept;
# this is the DNAT
dnat ip to ip daddr . tcp dport map @multihoming_ext
}
}
table ip myhelpers {
chain prerouting {
type filter hook prerouting priority filter; policy accept;
}
}
[ I removed ip6 entries ]
Any idea what could be wrong?
Thank you.
(**) very nice:
br0:
IP 46.140.72.222.60394 > 46.140.72.218.8080
IP 46.140.72.218.8080 > 46.140.72.222.60394
IP 46.140.72.222.60394 > 46.140.72.218.8080
enp2s0.202 (another connection):
IP 46.140.72.222.57790 > 192.168.202.10.80
IP 192.168.202.10.80 > 46.140.72.222.57790
IP 46.140.72.222.57790 > 192.168.202.10.80
next reply other threads:[~2025-01-25 16:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-25 15:55 Marc SCHAEFER [this message]
2025-01-26 6:19 ` nftables DNAT routes to wrong iface Sunny73Cr
2025-01-26 9:23 ` Marc SCHAEFER
2025-01-26 9:36 ` Marc SCHAEFER
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z5UJheaMk+bZsEFe@alphanet.ch \
--to=schaefer@alphanet.ch \
--cc=netfilter@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.