All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf] netfilter REJECT: Fix destination MAC in RST packets
@ 2021-03-08  1:16 Marc Aurèle La France
  2021-03-08 10:25 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 9+ messages in thread
From: Marc Aurèle La France @ 2021-03-08  1:16 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 4064 bytes --]

In the non-bridge case, the REJECT target code assumes the REJECTed
packets were originally emitted by the local host, but that's not
necessarily true when the local host is the default route of a subnet
it is on, resulting in RST packets being sent out with an incorrect
destination MAC.  Address this by refactoring the handling of bridged
packets which deals with a similar issue.  Modulo patch fuzz, the
following applies to v5 and later kernels.

Please Reply-To-All.

Thanks.

Marc.

Signed-off-by: Marc Aurèle La France <tsi@tuyoix.net>
Tested-by: Marc Aurèle La France <tsi@tuyoix.net>

--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -237,7 +237,7 @@ static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
 void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
 		   int hook)
 {
-	struct net_device *br_indev __maybe_unused;
+	struct net_device *indev;
 	struct sk_buff *nskb;
 	struct iphdr *niph;
 	const struct tcphdr *oth;
@@ -279,18 +279,20 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,

 	nf_ct_attach(nskb, oldskb);

-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-	/* If we use ip_local_out for bridged traffic, the MAC source on
-	 * the RST will be ours, instead of the destination's.  This confuses
-	 * some routers/firewalls, and they drop the packet.  So we need to
-	 * build the eth header using the original destination's MAC as the
-	 * source, and send the RST packet directly.
+	/* Swap the source and destination MACs of the RST packet from that
+	 * of the REJECTed packet's, if available from it.  Otherwise, let
+	 * ip_local_out decide.
 	 */
-	br_indev = nf_bridge_get_physindev(oldskb);
-	if (br_indev) {
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+	indev = nf_bridge_get_physindev(oldskb);
+	if (!indev)
+#endif
+		indev = oldskb->dev;
+
+	if (indev) {
 		struct ethhdr *oeth = eth_hdr(oldskb);

-		nskb->dev = br_indev;
+		nskb->dev = indev;
 		niph->tot_len = htons(nskb->len);
 		ip_send_check(niph);
 		if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
@@ -298,7 +300,6 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
 			goto free_nskb;
 		dev_queue_xmit(nskb);
 	} else
-#endif
 		ip_local_out(net, nskb->sk, nskb);

 	return;
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -278,7 +278,7 @@ static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
 void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
 		    int hook)
 {
-	struct net_device *br_indev __maybe_unused;
+	struct net_device *indev;
 	struct sk_buff *nskb;
 	struct tcphdr _otcph;
 	const struct tcphdr *otcph;
@@ -346,18 +346,20 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,

 	nf_ct_attach(nskb, oldskb);

-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-	/* If we use ip6_local_out for bridged traffic, the MAC source on
-	 * the RST will be ours, instead of the destination's.  This confuses
-	 * some routers/firewalls, and they drop the packet.  So we need to
-	 * build the eth header using the original destination's MAC as the
-	 * source, and send the RST packet directly.
+	/* Swap the source and destination MACs of the RST packet from that
+	 * of the REJECTed packet's, if available from it.  Otherwise, let
+	 * ip6_local_out decide.
 	 */
-	br_indev = nf_bridge_get_physindev(oldskb);
-	if (br_indev) {
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+	indev = nf_bridge_get_physindev(oldskb);
+	if (!indev)
+#endif
+		indev = oldskb->dev;
+
+	if (indev) {
 		struct ethhdr *oeth = eth_hdr(oldskb);

-		nskb->dev = br_indev;
+		nskb->dev = indev;
 		nskb->protocol = htons(ETH_P_IPV6);
 		ip6h->payload_len = htons(sizeof(struct tcphdr));
 		if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
@@ -367,7 +369,6 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
 		}
 		dev_queue_xmit(nskb);
 	} else
-#endif
 		ip6_local_out(net, sk, nskb);
 }
 EXPORT_SYMBOL_GPL(nf_send_reset6);

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

end of thread, other threads:[~2021-03-11  3:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08  1:16 [PATCH nf] netfilter REJECT: Fix destination MAC in RST packets Marc Aurèle La France
2021-03-08 10:25 ` Pablo Neira Ayuso
2021-03-08 16:21   ` Marc Aurèle La France
2021-03-09  1:36     ` Pablo Neira Ayuso
2021-03-09  4:25       ` Marc Aurèle La France
2021-03-09 10:27         ` Pablo Neira Ayuso
2021-03-10 23:51           ` Marc Aurèle La France
2021-03-11  0:02             ` Pablo Neira Ayuso
2021-03-11  3:39               ` Marc Aurèle La France

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.