netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf-next] netfilter: introduce support for reject at prerouting stage
@ 2020-05-28 17:14 Laura Garcia Liebana
  2020-05-28 17:24 ` Florian Westphal
  2020-05-29  8:47 ` Reindl Harald
  0 siblings, 2 replies; 5+ messages in thread
From: Laura Garcia Liebana @ 2020-05-28 17:14 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, devel

REJECT statement can be only used in INPUT, FORWARD and OUTPUT
chains. This patch adds support of REJECT, both icmp and tcp
reset, at PREROUTING stage.

The need for this patch becomes from the requirement of some
forwarding devices to reject traffic before the natting and
routing decisions.

It is supported ipv4, ipv6 and inet families for nft
infrastructure.

Signed-off-by: Laura Garcia Liebana <nevola@gmail.com>
---
 net/ipv4/netfilter/nf_reject_ipv4.c | 18 ++++++++++++++++++
 net/ipv6/netfilter/nf_reject_ipv6.c | 21 +++++++++++++++++++++
 net/netfilter/nft_reject.c          |  3 ++-
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index 2361fdac2c43..c6b46b7bca8b 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -96,6 +96,18 @@ void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
 }
 EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
 
+static void nf_reject_fill_skb_dst(struct sk_buff *skb_in)
+{
+	struct dst_entry *dst = NULL;
+	struct flowi fl;
+	struct flowi4 *fl4 = &fl.u.ip4;
+
+	memset(fl4, 0, sizeof(*fl4));
+	fl4->daddr = ip_hdr(skb_in)->saddr;
+	nf_route(dev_net(skb_in->dev), &dst, &fl, false, AF_INET);
+	skb_dst_set(skb_in, dst);
+}
+
 /* Send RST reply */
 void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
 {
@@ -109,6 +121,9 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
 	if (!oth)
 		return;
 
+	if (hook == NF_INET_PRE_ROUTING)
+		nf_reject_fill_skb_dst(oldskb);
+
 	if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
 		return;
 
@@ -175,6 +190,9 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
 	if (iph->frag_off & htons(IP_OFFSET))
 		return;
 
+	if (hook == NF_INET_PRE_ROUTING)
+		nf_reject_fill_skb_dst(skb_in);
+
 	if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
 		icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
 		return;
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 5fae66f66671..d59b38a16eaa 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -126,6 +126,18 @@ void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
 }
 EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
 
+static void nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
+{
+	struct dst_entry *dst = NULL;
+	struct flowi fl;
+	struct flowi6 *fl6 = &fl.u.ip6;
+
+	memset(fl6, 0, sizeof(*fl6));
+	fl6->daddr = ipv6_hdr(skb_in)->saddr;
+	nf_route(dev_net(skb_in->dev), &dst, &fl, false, AF_INET6);
+	skb_dst_set(skb_in, dst);
+}
+
 void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
 {
 	struct net_device *br_indev __maybe_unused;
@@ -154,6 +166,12 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
 	fl6.daddr = oip6h->saddr;
 	fl6.fl6_sport = otcph->dest;
 	fl6.fl6_dport = otcph->source;
+
+	if (hook == NF_INET_PRE_ROUTING) {
+		nf_route(dev_net(oldskb->dev), &dst, flowi6_to_flowi(&fl6), false, AF_INET6);
+		skb_dst_set(oldskb, dst);
+	}
+
 	fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
 	fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
 	security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
@@ -245,6 +263,9 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
 	if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
 		skb_in->dev = net->loopback_dev;
 
+	if (hooknum == NF_INET_PRE_ROUTING)
+		nf_reject6_fill_skb_dst(skb_in);
+
 	icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
 }
 EXPORT_SYMBOL_GPL(nf_send_unreach6);
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c
index 00f865fb80ca..5eac28269bdb 100644
--- a/net/netfilter/nft_reject.c
+++ b/net/netfilter/nft_reject.c
@@ -30,7 +30,8 @@ int nft_reject_validate(const struct nft_ctx *ctx,
 	return nft_chain_validate_hooks(ctx->chain,
 					(1 << NF_INET_LOCAL_IN) |
 					(1 << NF_INET_FORWARD) |
-					(1 << NF_INET_LOCAL_OUT));
+					(1 << NF_INET_LOCAL_OUT) |
+					(1 << NF_INET_PRE_ROUTING));
 }
 EXPORT_SYMBOL_GPL(nft_reject_validate);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH nf-next] netfilter: introduce support for reject at prerouting stage
  2020-05-28 17:14 [PATCH nf-next] netfilter: introduce support for reject at prerouting stage Laura Garcia Liebana
@ 2020-05-28 17:24 ` Florian Westphal
  2020-05-29  8:38   ` Laura García Liébana
  2020-05-29  8:47 ` Reindl Harald
  1 sibling, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2020-05-28 17:24 UTC (permalink / raw)
  To: Laura Garcia Liebana; +Cc: netfilter-devel, pablo, devel

Laura Garcia Liebana <nevola@gmail.com> wrote:
> +static void nf_reject_fill_skb_dst(struct sk_buff *skb_in)
> +{
> +	struct dst_entry *dst = NULL;
> +	struct flowi fl;
> +	struct flowi4 *fl4 = &fl.u.ip4;
> +
> +	memset(fl4, 0, sizeof(*fl4));
> +	fl4->daddr = ip_hdr(skb_in)->saddr;
> +	nf_route(dev_net(skb_in->dev), &dst, &fl, false, AF_INET);

Hmm, won't that need error handling for the case where we can't find
a route?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH nf-next] netfilter: introduce support for reject at prerouting stage
  2020-05-28 17:24 ` Florian Westphal
@ 2020-05-29  8:38   ` Laura García Liébana
  0 siblings, 0 replies; 5+ messages in thread
From: Laura García Liébana @ 2020-05-29  8:38 UTC (permalink / raw)
  To: Florian Westphal
  Cc: Netfilter Development Mailing list, Pablo Neira Ayuso, devel

On Thu, May 28, 2020 at 7:24 PM Florian Westphal <fw@strlen.de> wrote:
>
> Laura Garcia Liebana <nevola@gmail.com> wrote:
> > +static void nf_reject_fill_skb_dst(struct sk_buff *skb_in)
> > +{
> > +     struct dst_entry *dst = NULL;
> > +     struct flowi fl;
> > +     struct flowi4 *fl4 = &fl.u.ip4;
> > +
> > +     memset(fl4, 0, sizeof(*fl4));
> > +     fl4->daddr = ip_hdr(skb_in)->saddr;
> > +     nf_route(dev_net(skb_in->dev), &dst, &fl, false, AF_INET);
>
> Hmm, won't that need error handling for the case where we can't find
> a route?

Right. I'll send a v2.

Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH nf-next] netfilter: introduce support for reject at prerouting stage
  2020-05-28 17:14 [PATCH nf-next] netfilter: introduce support for reject at prerouting stage Laura Garcia Liebana
  2020-05-28 17:24 ` Florian Westphal
@ 2020-05-29  8:47 ` Reindl Harald
  2020-05-29  9:46   ` Laura García Liébana
  1 sibling, 1 reply; 5+ messages in thread
From: Reindl Harald @ 2020-05-29  8:47 UTC (permalink / raw)
  To: Laura Garcia Liebana, netfilter-devel; +Cc: pablo, devel



Am 28.05.20 um 19:14 schrieb Laura Garcia Liebana:
> REJECT statement can be only used in INPUT, FORWARD and OUTPUT
> chains. This patch adds support of REJECT, both icmp and tcp
> reset, at PREROUTING stage.
> 
> The need for this patch becomes from the requirement of some
> forwarding devices to reject traffic before the natting and
> routing decisions.

on the other hand you shoot yourself in the foot if you REJECT in
response of "ctstate INVALID" which is a such better place in "-t mangle
PREROUTING" because the reject to out of order re-transmit will kill
your connections

in the worst case you even send ICMP responses back to a forged source

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH nf-next] netfilter: introduce support for reject at prerouting stage
  2020-05-29  8:47 ` Reindl Harald
@ 2020-05-29  9:46   ` Laura García Liébana
  0 siblings, 0 replies; 5+ messages in thread
From: Laura García Liébana @ 2020-05-29  9:46 UTC (permalink / raw)
  To: Reindl Harald
  Cc: Netfilter Development Mailing list, Pablo Neira Ayuso, devel

On Fri, May 29, 2020 at 10:47 AM Reindl Harald <h.reindl@thelounge.net> wrote:
>
> Am 28.05.20 um 19:14 schrieb Laura Garcia Liebana:
> > REJECT statement can be only used in INPUT, FORWARD and OUTPUT
> > chains. This patch adds support of REJECT, both icmp and tcp
> > reset, at PREROUTING stage.
> >
> > The need for this patch becomes from the requirement of some
> > forwarding devices to reject traffic before the natting and
> > routing decisions.
>
> on the other hand you shoot yourself in the foot if you REJECT in
> response of "ctstate INVALID" which is a such better place in "-t mangle
> PREROUTING" because the reject to out of order re-transmit will kill
> your connections
>
> in the worst case you even send ICMP responses back to a forged source

The main use case is to be able to send a graceful termination to
legitimate clients that, under any circumstances, the NATed endpoints
are not available. This option allows clients to decide either to
perform a reconnection or manage the error in their side, instead of
just dropping the connection and let them die due to timeout.

Thanks for your comments.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-05-29  9:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-28 17:14 [PATCH nf-next] netfilter: introduce support for reject at prerouting stage Laura Garcia Liebana
2020-05-28 17:24 ` Florian Westphal
2020-05-29  8:38   ` Laura García Liébana
2020-05-29  8:47 ` Reindl Harald
2020-05-29  9:46   ` Laura García Liébana

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).