* [PATCH] nf-nat: don't use per destination incrementing ports in nat random mode @ 2013-12-19 13:40 Hannes Frederic Sowa 2013-12-19 23:21 ` Daniel Borkmann 0 siblings, 1 reply; 13+ messages in thread From: Hannes Frederic Sowa @ 2013-12-19 13:40 UTC (permalink / raw) To: netfilter-devel; +Cc: netdev, dborkman, kaber Don't use per destination incrementing port allocation in NF_NAT_RANGE_PROTO_RANDOM mode as advised in <https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf>. This is especially important for UDP/DNS. Cc: Patrick McHardy <kaber@trash.net> Cc: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> --- include/net/netfilter/nf_nat_l3proto.h | 2 -- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 8 -------- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 8 -------- net/netfilter/nf_nat_proto_common.c | 4 +--- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index 5a2919b..e4ed045 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -8,8 +8,6 @@ struct nf_nat_l3proto { bool (*in_range)(const struct nf_conntrack_tuple *t, const struct nf_nat_range *range); - u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16); - bool (*manip_pkt)(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index d8b2e14..f50d820 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -15,7 +15,6 @@ #include <linux/icmp.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> -#include <net/secure_seq.h> #include <net/checksum.h> #include <net/route.h> #include <net/ip.h> @@ -69,12 +68,6 @@ static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t, ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip); } -static u32 nf_nat_ipv4_secure_port(const struct nf_conntrack_tuple *t, - __be16 dport) -{ - return secure_ipv4_port_ephemeral(t->src.u3.ip, t->dst.u3.ip, dport); -} - static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, @@ -173,7 +166,6 @@ static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { .l3proto = NFPROTO_IPV4, .in_range = nf_nat_ipv4_in_range, - .secure_port = nf_nat_ipv4_secure_port, .manip_pkt = nf_nat_ipv4_manip_pkt, .csum_update = nf_nat_ipv4_csum_update, .csum_recalc = nf_nat_ipv4_csum_recalc, diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index abfe75a..9e5b3a0 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -13,7 +13,6 @@ #include <linux/ipv6.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> -#include <net/secure_seq.h> #include <net/checksum.h> #include <net/ip6_checksum.h> #include <net/ip6_route.h> @@ -68,12 +67,6 @@ static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t, ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0; } -static u32 nf_nat_ipv6_secure_port(const struct nf_conntrack_tuple *t, - __be16 dport) -{ - return secure_ipv6_port_ephemeral(t->src.u3.ip6, t->dst.u3.ip6, dport); -} - static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, @@ -178,7 +171,6 @@ static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { .l3proto = NFPROTO_IPV6, - .secure_port = nf_nat_ipv6_secure_port, .in_range = nf_nat_ipv6_in_range, .manip_pkt = nf_nat_ipv6_manip_pkt, .csum_update = nf_nat_ipv6_csum_update, diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 9baaf73..1d13101 100644 --- a/net/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c @@ -75,9 +75,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, } if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) - off = l3proto->secure_port(tuple, maniptype == NF_NAT_MANIP_SRC - ? tuple->dst.u.all - : tuple->src.u.all); + off = prandom_u32(); else off = *rover; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] nf-nat: don't use per destination incrementing ports in nat random mode 2013-12-19 13:40 [PATCH] nf-nat: don't use per destination incrementing ports in nat random mode Hannes Frederic Sowa @ 2013-12-19 23:21 ` Daniel Borkmann 2013-12-20 0:48 ` [PATCH next v2] " Hannes Frederic Sowa 0 siblings, 1 reply; 13+ messages in thread From: Daniel Borkmann @ 2013-12-19 23:21 UTC (permalink / raw) To: Hannes Frederic Sowa; +Cc: netfilter-devel, netdev, kaber On 12/19/2013 02:40 PM, Hannes Frederic Sowa wrote: > Don't use per destination incrementing port allocation > in NF_NAT_RANGE_PROTO_RANDOM mode as advised in > <https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf>. > > This is especially important for UDP/DNS. > > Cc: Patrick McHardy <kaber@trash.net> > Cc: Daniel Borkmann <dborkman@redhat.com> > Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> I would have liked a more elaborate commit message ;) but anyway, lgtm, now that we also have periodic reseeding in prandom: Reviewed-by: Daniel Borkmann <dborkman@redhat.com> The referenced paper in section 5 is also available here: http://arxiv.org/pdf/1205.5190v1.pdf ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH next v2] nf-nat: don't use per destination incrementing ports in nat random mode 2013-12-19 23:21 ` Daniel Borkmann @ 2013-12-20 0:48 ` Hannes Frederic Sowa 2013-12-20 8:01 ` Pablo Neira Ayuso 0 siblings, 1 reply; 13+ messages in thread From: Hannes Frederic Sowa @ 2013-12-20 0:48 UTC (permalink / raw) To: Daniel Borkmann; +Cc: netfilter-devel, netdev, kaber We currently use prandom_u32 for allocation of ports in tcp bind(0) and udp code. In case of plain SNAT we try to keep the ports as is or increment on collision. SNAT --random mode does use per-destination incrementing port allocation. As a recent paper pointed out that this mode of port allocation makes it possible an attacker to find the randomly allocated ports. So NF_NAT_RANGE_PROTO_RANDOM actually weakens the port randomization in regard to the attack in this paper. You can find details in this paper: <https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf>. The idea is to send burts of packets to a socket to overflow its receive queue and measure the latency to detect a possible retransmit when the port is found. Because of increasing ports to given destination and port further allocations can be predicted. So switch NF_NAT_RANGE_PROTO_RANDOM to prandom_u32, too. Reviewed-by: Daniel Borkmann <dborkman@redhat.com> Cc: Patrick McHardy <kaber@trash.net> Cc: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> --- v2: More verbose changelog as suggested by Daniel. include/net/netfilter/nf_nat_l3proto.h | 2 -- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 8 -------- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 8 -------- net/netfilter/nf_nat_proto_common.c | 4 +--- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index 5a2919b..e4ed045 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -8,8 +8,6 @@ struct nf_nat_l3proto { bool (*in_range)(const struct nf_conntrack_tuple *t, const struct nf_nat_range *range); - u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16); - bool (*manip_pkt)(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index d8b2e14..f50d820 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -15,7 +15,6 @@ #include <linux/icmp.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> -#include <net/secure_seq.h> #include <net/checksum.h> #include <net/route.h> #include <net/ip.h> @@ -69,12 +68,6 @@ static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t, ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip); } -static u32 nf_nat_ipv4_secure_port(const struct nf_conntrack_tuple *t, - __be16 dport) -{ - return secure_ipv4_port_ephemeral(t->src.u3.ip, t->dst.u3.ip, dport); -} - static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, @@ -173,7 +166,6 @@ static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { .l3proto = NFPROTO_IPV4, .in_range = nf_nat_ipv4_in_range, - .secure_port = nf_nat_ipv4_secure_port, .manip_pkt = nf_nat_ipv4_manip_pkt, .csum_update = nf_nat_ipv4_csum_update, .csum_recalc = nf_nat_ipv4_csum_recalc, diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index abfe75a..9e5b3a0 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -13,7 +13,6 @@ #include <linux/ipv6.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> -#include <net/secure_seq.h> #include <net/checksum.h> #include <net/ip6_checksum.h> #include <net/ip6_route.h> @@ -68,12 +67,6 @@ static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t, ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0; } -static u32 nf_nat_ipv6_secure_port(const struct nf_conntrack_tuple *t, - __be16 dport) -{ - return secure_ipv6_port_ephemeral(t->src.u3.ip6, t->dst.u3.ip6, dport); -} - static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, const struct nf_nat_l4proto *l4proto, @@ -178,7 +171,6 @@ static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { .l3proto = NFPROTO_IPV6, - .secure_port = nf_nat_ipv6_secure_port, .in_range = nf_nat_ipv6_in_range, .manip_pkt = nf_nat_ipv6_manip_pkt, .csum_update = nf_nat_ipv6_csum_update, diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 9baaf73..1d13101 100644 --- a/net/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c @@ -75,9 +75,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, } if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) - off = l3proto->secure_port(tuple, maniptype == NF_NAT_MANIP_SRC - ? tuple->dst.u.all - : tuple->src.u.all); + off = prandom_u32(); else off = *rover; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH next v2] nf-nat: don't use per destination incrementing ports in nat random mode 2013-12-20 0:48 ` [PATCH next v2] " Hannes Frederic Sowa @ 2013-12-20 8:01 ` Pablo Neira Ayuso 2013-12-20 21:40 ` [PATCH v2 -next] netfilter: don't use per-destination " Hannes Frederic Sowa 0 siblings, 1 reply; 13+ messages in thread From: Pablo Neira Ayuso @ 2013-12-20 8:01 UTC (permalink / raw) To: Daniel Borkmann, netfilter-devel, netdev, kaber On Fri, Dec 20, 2013 at 01:48:22AM +0100, Hannes Frederic Sowa wrote: > We currently use prandom_u32 for allocation of ports in tcp bind(0) > and udp code. In case of plain SNAT we try to keep the ports as is or > increment on collision. > > SNAT --random mode does use per-destination incrementing port > allocation. As a recent paper pointed out that this mode of port > allocation makes it possible an attacker to find the randomly > allocated ports. So NF_NAT_RANGE_PROTO_RANDOM actually weakens the port > randomization in regard to the attack in this paper. > > You can find details in this paper: > <https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf>. > > The idea is to send burts of packets to a socket to overflow its receive > queue and measure the latency to detect a possible retransmit when the > port is found. Because of increasing ports to given destination and port > further allocations can be predicted. > > So switch NF_NAT_RANGE_PROTO_RANDOM to prandom_u32, too. I think that we should be a bit more conservative and add a new option for this and document this new behaviour, so the user can select what approach is better according to their needs. There are protocols that rely on consecutive port allocation to work, eg. RTP/RCTP, I'm afraid that this full randomization approach will break them. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-20 8:01 ` Pablo Neira Ayuso @ 2013-12-20 21:40 ` Hannes Frederic Sowa 2013-12-21 12:17 ` Pablo Neira Ayuso ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Hannes Frederic Sowa @ 2013-12-20 21:40 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: Daniel Borkmann, netfilter-devel, netdev, kaber From: Daniel Borkmann <dborkman@redhat.com> We currently use prandom_u32() for allocation of ports in tcp bind(0) and udp code. In case of plain SNAT we try to keep the ports as is or increment on collision. SNAT --random mode does use per-destination incrementing port allocation. As a recent paper pointed out in [1] that this mode of port allocation makes it possible to an attacker to find the randomly allocated ports through a timing side-channel in a socket overloading attack conducted through an off-path attacker. So, NF_NAT_RANGE_PROTO_RANDOM actually weakens the port randomization in regard to the attack described in this paper. As we need to keep compatibility, add another flag called NF_NAT_RANGE_PROTO_RANDOM_FULLY that would replace the NF_NAT_RANGE_PROTO_RANDOM hash-based port selection algorithm with a simple prandom_u32() in order to mitigate this attack vector. Note that the lfsr113's internal state is periodically reseeded by the kernel through a local secure entropy source. More details can be found in [1], the basic idea is to send bursts of packets to a socket to overflow its receive queue and measure the latency to detect a possible retransmit when the port is found. Because of increasing ports to given destination and port, further allocations can be predicted. This information could then be used by an attacker for e.g. for cache-poisoning, NS pinning, and degradation of service attacks against DNS servers [1]: The best defense against the poisoning attacks is to properly deploy and validate DNSSEC; DNSSEC provides security not only against off-path attacker but even against MitM attacker. We hope that our results will help motivate administrators to adopt DNSSEC. However, full DNSSEC deployment make take significant time, and until that happens, we recommend short-term, non-cryptographic defenses. We recommend to support full port randomisation, according to practices recommended in [2], and to avoid per-destination sequential port allocation, which we show may be vulnerable to derandomisation attacks. Joint work between Hannes Frederic Sowa and Daniel Borkmann. [1] https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf [2] http://arxiv.org/pdf/1205.5190v1.pdf Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> --- Daniel will follow-up with the user-space changes tomorrow. include/uapi/linux/netfilter/nf_nat.h | 12 ++++++++---- net/netfilter/nf_nat_core.c | 4 ++-- net/netfilter/nf_nat_proto_common.c | 10 ++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h index bf0cc37..1ad3659 100644 --- a/include/uapi/linux/netfilter/nf_nat.h +++ b/include/uapi/linux/netfilter/nf_nat.h @@ -4,10 +4,14 @@ #include <linux/netfilter.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> -#define NF_NAT_RANGE_MAP_IPS 1 -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 -#define NF_NAT_RANGE_PROTO_RANDOM 4 -#define NF_NAT_RANGE_PERSISTENT 8 +#define NF_NAT_RANGE_MAP_IPS (1 << 0) +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) +#define NF_NAT_RANGE_PERSISTENT (1 << 3) +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) + +#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ + (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) struct nf_nat_ipv4_range { unsigned int flags; diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 63a8154..d3f5cd6 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -315,7 +315,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, * manips not an issue. */ if (maniptype == NF_NAT_MANIP_SRC && - !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { + !(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) { /* try the original tuple first */ if (in_range(l3proto, l4proto, orig_tuple, range)) { if (!nf_nat_used_tuple(orig_tuple, ct)) { @@ -339,7 +339,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, */ /* Only bother mapping if it's not already in range and unique */ - if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { + if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) { if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { if (l4proto->in_range(tuple, maniptype, &range->min_proto, diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 9baaf73..83a72a2 100644 --- a/net/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c @@ -74,22 +74,24 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, range_size = ntohs(range->max_proto.all) - min + 1; } - if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) { off = l3proto->secure_port(tuple, maniptype == NF_NAT_MANIP_SRC ? tuple->dst.u.all : tuple->src.u.all); - else + } else if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) { + off = prandom_u32(); + } else { off = *rover; + } for (i = 0; ; ++off) { *portptr = htons(min + off % range_size); if (++i != range_size && nf_nat_used_tuple(tuple, ct)) continue; - if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) + if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) *rover = off; return; } - return; } EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple); -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-20 21:40 ` [PATCH v2 -next] netfilter: don't use per-destination " Hannes Frederic Sowa @ 2013-12-21 12:17 ` Pablo Neira Ayuso 2013-12-21 12:26 ` Hannes Frederic Sowa 2013-12-22 3:15 ` [PATCH iptables] iptables: snat: add randomize-full support Hannes Frederic Sowa 2014-01-03 22:52 ` [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode Pablo Neira Ayuso 2 siblings, 1 reply; 13+ messages in thread From: Pablo Neira Ayuso @ 2013-12-21 12:17 UTC (permalink / raw) To: Daniel Borkmann, netfilter-devel, Hannes Frederic Sowa, netdev, kaber On Fri, Dec 20, 2013 at 10:40:29PM +0100, Hannes Frederic Sowa wrote: > From: Daniel Borkmann <dborkman@redhat.com> > > We currently use prandom_u32() for allocation of ports in tcp bind(0) > and udp code. In case of plain SNAT we try to keep the ports as is > or increment on collision. > > SNAT --random mode does use per-destination incrementing port > allocation. As a recent paper pointed out in [1] that this mode of > port allocation makes it possible to an attacker to find the randomly > allocated ports through a timing side-channel in a socket overloading > attack conducted through an off-path attacker. > > So, NF_NAT_RANGE_PROTO_RANDOM actually weakens the port randomization > in regard to the attack described in this paper. As we need to keep > compatibility, add another flag called NF_NAT_RANGE_PROTO_RANDOM_FULLY > that would replace the NF_NAT_RANGE_PROTO_RANDOM hash-based port > selection algorithm with a simple prandom_u32() in order to mitigate > this attack vector. Note that the lfsr113's internal state is > periodically reseeded by the kernel through a local secure entropy > source. > > More details can be found in [1], the basic idea is to send bursts > of packets to a socket to overflow its receive queue and measure > the latency to detect a possible retransmit when the port is found. > Because of increasing ports to given destination and port, further > allocations can be predicted. This information could then be used by > an attacker for e.g. for cache-poisoning, NS pinning, and degradation > of service attacks against DNS servers [1]: > > The best defense against the poisoning attacks is to properly > deploy and validate DNSSEC; DNSSEC provides security not only > against off-path attacker but even against MitM attacker. We hope > that our results will help motivate administrators to adopt DNSSEC. > However, full DNSSEC deployment make take significant time, and > until that happens, we recommend short-term, non-cryptographic > defenses. We recommend to support full port randomisation, > according to practices recommended in [2], and to avoid > per-destination sequential port allocation, which we show may be > vulnerable to derandomisation attacks. > > Joint work between Hannes Frederic Sowa and Daniel Borkmann. > > [1] https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf > [2] http://arxiv.org/pdf/1205.5190v1.pdf > > Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> > Signed-off-by: Daniel Borkmann <dborkman@redhat.com> > --- > > Daniel will follow-up with the user-space changes tomorrow. > > include/uapi/linux/netfilter/nf_nat.h | 12 ++++++++---- > net/netfilter/nf_nat_core.c | 4 ++-- > net/netfilter/nf_nat_proto_common.c | 10 ++++++---- > 3 files changed, 16 insertions(+), 10 deletions(-) > > diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h > index bf0cc37..1ad3659 100644 > --- a/include/uapi/linux/netfilter/nf_nat.h > +++ b/include/uapi/linux/netfilter/nf_nat.h This is exposed to userspace. > @@ -4,10 +4,14 @@ > #include <linux/netfilter.h> > #include <linux/netfilter/nf_conntrack_tuple_common.h> > > -#define NF_NAT_RANGE_MAP_IPS 1 > -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 > -#define NF_NAT_RANGE_PROTO_RANDOM 4 > -#define NF_NAT_RANGE_PERSISTENT 8 > +#define NF_NAT_RANGE_MAP_IPS (1 << 0) > +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) > +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) > +#define NF_NAT_RANGE_PERSISTENT (1 << 3) > +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) So you cannot change it. It would break old iptables binaries. BTW, please send me the userspace part. Thanks! ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-21 12:17 ` Pablo Neira Ayuso @ 2013-12-21 12:26 ` Hannes Frederic Sowa 2013-12-21 12:27 ` Pablo Neira Ayuso 0 siblings, 1 reply; 13+ messages in thread From: Hannes Frederic Sowa @ 2013-12-21 12:26 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: Daniel Borkmann, netfilter-devel, netdev, kaber On Sat, Dec 21, 2013 at 01:17:59PM +0100, Pablo Neira Ayuso wrote: > > diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h > > index bf0cc37..1ad3659 100644 > > --- a/include/uapi/linux/netfilter/nf_nat.h > > +++ b/include/uapi/linux/netfilter/nf_nat.h > > This is exposed to userspace. > > > @@ -4,10 +4,14 @@ > > #include <linux/netfilter.h> > > #include <linux/netfilter/nf_conntrack_tuple_common.h> > > > > -#define NF_NAT_RANGE_MAP_IPS 1 > > -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 > > -#define NF_NAT_RANGE_PROTO_RANDOM 4 > > -#define NF_NAT_RANGE_PERSISTENT 8 > > +#define NF_NAT_RANGE_MAP_IPS (1 << 0) > > +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) > > +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) > > +#define NF_NAT_RANGE_PERSISTENT (1 << 3) > > +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) > > So you cannot change it. It would break old iptables binaries. There are no semantic changes besides the addition of NF_NAT_RANGE_PROTO_RANDOM_FULLY. Otherwise just the notation is changed, which looks sane to me. > BTW, please send me the userspace part. Daniel has the patch ready, I think he will submit it later today. Thanks, Hannes ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-21 12:26 ` Hannes Frederic Sowa @ 2013-12-21 12:27 ` Pablo Neira Ayuso 2013-12-21 16:25 ` Daniel Borkmann 0 siblings, 1 reply; 13+ messages in thread From: Pablo Neira Ayuso @ 2013-12-21 12:27 UTC (permalink / raw) To: Daniel Borkmann, netfilter-devel, netdev, kaber On Sat, Dec 21, 2013 at 01:26:17PM +0100, Hannes Frederic Sowa wrote: > On Sat, Dec 21, 2013 at 01:17:59PM +0100, Pablo Neira Ayuso wrote: > > > diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h > > > index bf0cc37..1ad3659 100644 > > > --- a/include/uapi/linux/netfilter/nf_nat.h > > > +++ b/include/uapi/linux/netfilter/nf_nat.h > > > > This is exposed to userspace. > > > > > @@ -4,10 +4,14 @@ > > > #include <linux/netfilter.h> > > > #include <linux/netfilter/nf_conntrack_tuple_common.h> > > > > > > -#define NF_NAT_RANGE_MAP_IPS 1 > > > -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 > > > -#define NF_NAT_RANGE_PROTO_RANDOM 4 > > > -#define NF_NAT_RANGE_PERSISTENT 8 > > > +#define NF_NAT_RANGE_MAP_IPS (1 << 0) > > > +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) > > > +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) > > > +#define NF_NAT_RANGE_PERSISTENT (1 << 3) > > > +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) > > > > So you cannot change it. It would break old iptables binaries. > > There are no semantic changes besides the addition of > NF_NAT_RANGE_PROTO_RANDOM_FULLY. Otherwise just the notation is changed, > which looks sane to me. My fault sorry. I overlooked that you were just converting from numeric to flag notation. This is fine. > > BTW, please send me the userspace part. > > Daniel has the patch ready, I think he will submit it later today. Thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-21 12:27 ` Pablo Neira Ayuso @ 2013-12-21 16:25 ` Daniel Borkmann 0 siblings, 0 replies; 13+ messages in thread From: Daniel Borkmann @ 2013-12-21 16:25 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel, netdev, kaber On 12/21/2013 01:27 PM, Pablo Neira Ayuso wrote: > On Sat, Dec 21, 2013 at 01:26:17PM +0100, Hannes Frederic Sowa wrote: >> On Sat, Dec 21, 2013 at 01:17:59PM +0100, Pablo Neira Ayuso wrote: >>>> diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h >>>> index bf0cc37..1ad3659 100644 >>>> --- a/include/uapi/linux/netfilter/nf_nat.h >>>> +++ b/include/uapi/linux/netfilter/nf_nat.h >>> >>> This is exposed to userspace. >>> >>>> @@ -4,10 +4,14 @@ >>>> #include <linux/netfilter.h> >>>> #include <linux/netfilter/nf_conntrack_tuple_common.h> >>>> >>>> -#define NF_NAT_RANGE_MAP_IPS 1 >>>> -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 >>>> -#define NF_NAT_RANGE_PROTO_RANDOM 4 >>>> -#define NF_NAT_RANGE_PERSISTENT 8 >>>> +#define NF_NAT_RANGE_MAP_IPS (1 << 0) >>>> +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) >>>> +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) >>>> +#define NF_NAT_RANGE_PERSISTENT (1 << 3) >>>> +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) >>> >>> So you cannot change it. It would break old iptables binaries. >> >> There are no semantic changes besides the addition of >> NF_NAT_RANGE_PROTO_RANDOM_FULLY. Otherwise just the notation is changed, >> which looks sane to me. > > My fault sorry. I overlooked that you were just converting from > numeric to flag notation. Yes, this was just for readability. > This is fine. > >>> BTW, please send me the userspace part. >> >> Daniel has the patch ready, I think he will submit it later today. I was most of the part on travel today, but I'll see if I can finish the user space part tonight and send it out. Thanks, Daniel ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH iptables] iptables: snat: add randomize-full support 2013-12-20 21:40 ` [PATCH v2 -next] netfilter: don't use per-destination " Hannes Frederic Sowa 2013-12-21 12:17 ` Pablo Neira Ayuso @ 2013-12-22 3:15 ` Hannes Frederic Sowa 2014-01-03 23:43 ` Pablo Neira Ayuso 2014-01-03 22:52 ` [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode Pablo Neira Ayuso 2 siblings, 1 reply; 13+ messages in thread From: Hannes Frederic Sowa @ 2013-12-22 3:15 UTC (permalink / raw) To: Pablo Neira Ayuso, Daniel Borkmann, netfilter-devel, netdev, kaber From: Daniel Borkmann <dborkman@redhat.com> This patch provides the user space part for dnat in order to make randomize-full support available in {ip,nf}tables. It allows for enabling full port randomization that was motivated in [1] and introduced to the kernel in [2]. Joint work between Hannes Frederic Sowa and Daniel Borkmann. [1] https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf [2] http://patchwork.ozlabs.org/patch/304306/ Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> --- extensions/libip6t_SNAT.c | 18 ++++++++++++++---- extensions/libipt_SNAT.c | 18 ++++++++++++++---- extensions/libxt_SNAT.man | 7 ++++++- include/linux/netfilter/nf_nat.h | 12 ++++++++---- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c index 7382ad0..8eb50b8 100644 --- a/extensions/libip6t_SNAT.c +++ b/extensions/libip6t_SNAT.c @@ -18,11 +18,13 @@ enum { O_TO_SRC = 0, O_RANDOM, + O_RANDOM_FULLY, O_PERSISTENT, O_X_TO_SRC, - F_TO_SRC = 1 << O_TO_SRC, - F_RANDOM = 1 << O_RANDOM, - F_X_TO_SRC = 1 << O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_RANDOM_FULLY = 1 << O_RANDOM_FULLY, + F_X_TO_SRC = 1 << O_X_TO_SRC, }; static void SNAT_help(void) @@ -31,13 +33,14 @@ static void SNAT_help(void) "SNAT target options:\n" " --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n" " Address to map source to.\n" -"[--random] [--persistent]\n"); +"[--random] [--random-fully] [--persistent]\n"); } static const struct xt_option_entry SNAT_opts[] = { {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, .flags = XTOPT_MAND | XTOPT_MULTI}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, XTOPT_TABLEEND, }; @@ -180,10 +183,13 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; + static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY; struct nf_nat_range *range = cb->data; if ((cb->xflags & f) == f) range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + if ((cb->xflags & r) == r) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; } static void print_range(const struct nf_nat_range *range) @@ -215,6 +221,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, print_range(range); if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" random-fully"); if (range->flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } @@ -227,6 +235,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) print_range(range); if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" --random-fully"); if (range->flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 1a24f3d..78d2c2b 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -11,11 +11,13 @@ enum { O_TO_SRC = 0, O_RANDOM, + O_RANDOM_FULLY, O_PERSISTENT, O_X_TO_SRC, - F_TO_SRC = 1 << O_TO_SRC, - F_RANDOM = 1 << O_RANDOM, - F_X_TO_SRC = 1 << O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_RANDOM_FULLY = 1 << O_RANDOM_FULLY, + F_X_TO_SRC = 1 << O_X_TO_SRC, }; /* Source NAT data consists of a multi-range, indicating where to map @@ -32,13 +34,14 @@ static void SNAT_help(void) "SNAT target options:\n" " --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n" " Address to map source to.\n" -"[--random] [--persistent]\n"); +"[--random] [--random-fully] [--persistent]\n"); } static const struct xt_option_entry SNAT_opts[] = { {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, .flags = XTOPT_MAND | XTOPT_MULTI}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, XTOPT_TABLEEND, }; @@ -185,10 +188,13 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; + static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY; struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; + if ((cb->xflags & r) == r) + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; } static void print_range(const struct nf_nat_ipv4_range *r) @@ -222,6 +228,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, print_range(&info->mr.range[i]); if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" random-fully"); if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } @@ -237,6 +245,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) print_range(&info->mr.range[i]); if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" --random-fully"); if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } diff --git a/extensions/libxt_SNAT.man b/extensions/libxt_SNAT.man index f0620a2..8cd0b80 100644 --- a/extensions/libxt_SNAT.man +++ b/extensions/libxt_SNAT.man @@ -29,7 +29,12 @@ anymore. \fB\-\-random\fP If option \fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.21). +is used then port mapping will be randomized through a hash-based algorithm (kernel >= 2.6.21). +.TP +\fB\-\-random-fully\fP +If option +\fB\-\-random-fully\fP +is used then port mapping will be fully randomized through a PRNG (kernel >= 3.14). .TP \fB\-\-persistent\fP Gives a client the same source-/destination-address for each connection. diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h index bf0cc37..1ad3659 100644 --- a/include/linux/netfilter/nf_nat.h +++ b/include/linux/netfilter/nf_nat.h @@ -4,10 +4,14 @@ #include <linux/netfilter.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> -#define NF_NAT_RANGE_MAP_IPS 1 -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 -#define NF_NAT_RANGE_PROTO_RANDOM 4 -#define NF_NAT_RANGE_PERSISTENT 8 +#define NF_NAT_RANGE_MAP_IPS (1 << 0) +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) +#define NF_NAT_RANGE_PERSISTENT (1 << 3) +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) + +#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ + (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) struct nf_nat_ipv4_range { unsigned int flags; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH iptables] iptables: snat: add randomize-full support 2013-12-22 3:15 ` [PATCH iptables] iptables: snat: add randomize-full support Hannes Frederic Sowa @ 2014-01-03 23:43 ` Pablo Neira Ayuso 0 siblings, 0 replies; 13+ messages in thread From: Pablo Neira Ayuso @ 2014-01-03 23:43 UTC (permalink / raw) To: Daniel Borkmann, netfilter-devel, netdev, kaber On Sun, Dec 22, 2013 at 04:15:38AM +0100, Hannes Frederic Sowa wrote: > From: Daniel Borkmann <dborkman@redhat.com> > > This patch provides the user space part for dnat in order to make > randomize-full support available in {ip,nf}tables. It allows for > enabling full port randomization that was motivated in [1] and > introduced to the kernel in [2]. > > Joint work between Hannes Frederic Sowa and Daniel Borkmann. Applied to iptables-next, thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2013-12-20 21:40 ` [PATCH v2 -next] netfilter: don't use per-destination " Hannes Frederic Sowa 2013-12-21 12:17 ` Pablo Neira Ayuso 2013-12-22 3:15 ` [PATCH iptables] iptables: snat: add randomize-full support Hannes Frederic Sowa @ 2014-01-03 22:52 ` Pablo Neira Ayuso 2014-01-03 23:11 ` Daniel Borkmann 2 siblings, 1 reply; 13+ messages in thread From: Pablo Neira Ayuso @ 2014-01-03 22:52 UTC (permalink / raw) To: Daniel Borkmann, netfilter-devel, netdev, kaber On Fri, Dec 20, 2013 at 10:40:29PM +0100, Hannes Frederic Sowa wrote: > From: Daniel Borkmann <dborkman@redhat.com> > > We currently use prandom_u32() for allocation of ports in tcp bind(0) > and udp code. In case of plain SNAT we try to keep the ports as is > or increment on collision. > > SNAT --random mode does use per-destination incrementing port > allocation. As a recent paper pointed out in [1] that this mode of > port allocation makes it possible to an attacker to find the randomly > allocated ports through a timing side-channel in a socket overloading > attack conducted through an off-path attacker. > > So, NF_NAT_RANGE_PROTO_RANDOM actually weakens the port randomization > in regard to the attack described in this paper. As we need to keep > compatibility, add another flag called NF_NAT_RANGE_PROTO_RANDOM_FULLY > that would replace the NF_NAT_RANGE_PROTO_RANDOM hash-based port > selection algorithm with a simple prandom_u32() in order to mitigate > this attack vector. Note that the lfsr113's internal state is > periodically reseeded by the kernel through a local secure entropy > source. > > More details can be found in [1], the basic idea is to send bursts > of packets to a socket to overflow its receive queue and measure > the latency to detect a possible retransmit when the port is found. > Because of increasing ports to given destination and port, further > allocations can be predicted. This information could then be used by > an attacker for e.g. for cache-poisoning, NS pinning, and degradation > of service attacks against DNS servers [1]: > > The best defense against the poisoning attacks is to properly > deploy and validate DNSSEC; DNSSEC provides security not only > against off-path attacker but even against MitM attacker. We hope > that our results will help motivate administrators to adopt DNSSEC. > However, full DNSSEC deployment make take significant time, and > until that happens, we recommend short-term, non-cryptographic > defenses. We recommend to support full port randomisation, > according to practices recommended in [2], and to avoid > per-destination sequential port allocation, which we show may be > vulnerable to derandomisation attacks. > > Joint work between Hannes Frederic Sowa and Daniel Borkmann. Applied, thanks. I have renamed the title of this patch to: "add full port randomization support" which I though a bit more descriptive with the final patch that has settled down, just in case you look for it in the nf-next tree. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode 2014-01-03 22:52 ` [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode Pablo Neira Ayuso @ 2014-01-03 23:11 ` Daniel Borkmann 0 siblings, 0 replies; 13+ messages in thread From: Daniel Borkmann @ 2014-01-03 23:11 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel, netdev, kaber On 01/03/2014 11:52 PM, Pablo Neira Ayuso wrote: > On Fri, Dec 20, 2013 at 10:40:29PM +0100, Hannes Frederic Sowa wrote: >> From: Daniel Borkmann <dborkman@redhat.com> >> >> We currently use prandom_u32() for allocation of ports in tcp bind(0) >> and udp code. In case of plain SNAT we try to keep the ports as is >> or increment on collision. >> >> SNAT --random mode does use per-destination incrementing port >> allocation. As a recent paper pointed out in [1] that this mode of >> port allocation makes it possible to an attacker to find the randomly >> allocated ports through a timing side-channel in a socket overloading >> attack conducted through an off-path attacker. >> >> So, NF_NAT_RANGE_PROTO_RANDOM actually weakens the port randomization >> in regard to the attack described in this paper. As we need to keep >> compatibility, add another flag called NF_NAT_RANGE_PROTO_RANDOM_FULLY >> that would replace the NF_NAT_RANGE_PROTO_RANDOM hash-based port >> selection algorithm with a simple prandom_u32() in order to mitigate >> this attack vector. Note that the lfsr113's internal state is >> periodically reseeded by the kernel through a local secure entropy >> source. >> >> More details can be found in [1], the basic idea is to send bursts >> of packets to a socket to overflow its receive queue and measure >> the latency to detect a possible retransmit when the port is found. >> Because of increasing ports to given destination and port, further >> allocations can be predicted. This information could then be used by >> an attacker for e.g. for cache-poisoning, NS pinning, and degradation >> of service attacks against DNS servers [1]: >> >> The best defense against the poisoning attacks is to properly >> deploy and validate DNSSEC; DNSSEC provides security not only >> against off-path attacker but even against MitM attacker. We hope >> that our results will help motivate administrators to adopt DNSSEC. >> However, full DNSSEC deployment make take significant time, and >> until that happens, we recommend short-term, non-cryptographic >> defenses. We recommend to support full port randomisation, >> according to practices recommended in [2], and to avoid >> per-destination sequential port allocation, which we show may be >> vulnerable to derandomisation attacks. >> >> Joint work between Hannes Frederic Sowa and Daniel Borkmann. > > Applied, thanks. > > I have renamed the title of this patch to: "add full port > randomization support" which I though a bit more descriptive with the > final patch that has settled down, just in case you look for it in the > nf-next tree. That's fine, thanks a lot Pablo! ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2014-01-03 23:43 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-12-19 13:40 [PATCH] nf-nat: don't use per destination incrementing ports in nat random mode Hannes Frederic Sowa 2013-12-19 23:21 ` Daniel Borkmann 2013-12-20 0:48 ` [PATCH next v2] " Hannes Frederic Sowa 2013-12-20 8:01 ` Pablo Neira Ayuso 2013-12-20 21:40 ` [PATCH v2 -next] netfilter: don't use per-destination " Hannes Frederic Sowa 2013-12-21 12:17 ` Pablo Neira Ayuso 2013-12-21 12:26 ` Hannes Frederic Sowa 2013-12-21 12:27 ` Pablo Neira Ayuso 2013-12-21 16:25 ` Daniel Borkmann 2013-12-22 3:15 ` [PATCH iptables] iptables: snat: add randomize-full support Hannes Frederic Sowa 2014-01-03 23:43 ` Pablo Neira Ayuso 2014-01-03 22:52 ` [PATCH v2 -next] netfilter: don't use per-destination incrementing ports in nat random mode Pablo Neira Ayuso 2014-01-03 23:11 ` Daniel Borkmann
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).