From owner-svn-src-all@freebsd.org Thu Dec 12 13:28:47 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 09F861D15B4; Thu, 12 Dec 2019 13:28:47 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47YZPp6XhPz4XM8; Thu, 12 Dec 2019 13:28:46 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D6FE72460F; Thu, 12 Dec 2019 13:28:46 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xBCDSkQN077823; Thu, 12 Dec 2019 13:28:46 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xBCDSkkt077821; Thu, 12 Dec 2019 13:28:46 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201912121328.xBCDSkkt077821@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Thu, 12 Dec 2019 13:28:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355650 - in head/sys: modules/ipfw_nat64 netpfil/ipfw/nat64 X-SVN-Group: head X-SVN-Commit-Author: ae X-SVN-Commit-Paths: in head/sys: modules/ipfw_nat64 netpfil/ipfw/nat64 X-SVN-Commit-Revision: 355650 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Dec 2019 13:28:47 -0000 Author: ae Date: Thu Dec 12 13:28:46 2019 New Revision: 355650 URL: https://svnweb.freebsd.org/changeset/base/355650 Log: Follow RFC 4443 p2.2 and always use own addresses for reflected ICMPv6 datagrams. Previously destination address from original datagram was used. That looked confusing, especially in the traceroute6 output. Also honor IPSTEALTH kernel option and do TTL/HLIM decrementing only when stealth mode is disabled. Reported by: Marco van Tol Reviewed by: melifaro MFC after: 2 weeks Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D22631 Modified: head/sys/modules/ipfw_nat64/Makefile head/sys/netpfil/ipfw/nat64/nat64_translate.c Modified: head/sys/modules/ipfw_nat64/Makefile ============================================================================== --- head/sys/modules/ipfw_nat64/Makefile Thu Dec 12 13:21:43 2019 (r355649) +++ head/sys/modules/ipfw_nat64/Makefile Thu Dec 12 13:28:46 2019 (r355650) @@ -7,6 +7,7 @@ SRCS= ip_fw_nat64.c nat64_translate.c SRCS+= nat64clat.c nat64clat_control.c SRCS+= nat64lsn.c nat64lsn_control.c SRCS+= nat64stl.c nat64stl_control.c +SRCS+= opt_ipstealth.h CFLAGS+= -I${SRCTOP}/sys/contrib/ck/include Modified: head/sys/netpfil/ipfw/nat64/nat64_translate.c ============================================================================== --- head/sys/netpfil/ipfw/nat64/nat64_translate.c Thu Dec 12 13:21:43 2019 (r355649) +++ head/sys/netpfil/ipfw/nat64/nat64_translate.c Thu Dec 12 13:28:46 2019 (r355650) @@ -29,6 +29,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ipstealth.h" + #include #include #include @@ -101,14 +103,39 @@ static const struct nat64_methods nat64_direct = { .output = nat64_direct_output, .output_one = nat64_direct_output_one }; -VNET_DEFINE_STATIC(const struct nat64_methods *, nat64out) = &nat64_netisr; -#define V_nat64out VNET(nat64out) +/* These variables should be initialized explicitly on module loading */ +VNET_DEFINE_STATIC(const struct nat64_methods *, nat64out); +VNET_DEFINE_STATIC(const int *, nat64ipstealth); +VNET_DEFINE_STATIC(const int *, nat64ip6stealth); +#define V_nat64out VNET(nat64out) +#define V_nat64ipstealth VNET(nat64ipstealth) +#define V_nat64ip6stealth VNET(nat64ip6stealth) + +static const int stealth_on = 1; +#ifndef IPSTEALTH +static const int stealth_off = 0; +#endif + void nat64_set_output_method(int direct) { - V_nat64out = direct != 0 ? &nat64_direct: &nat64_netisr; + if (direct != 0) { + V_nat64out = &nat64_direct; +#ifdef IPSTEALTH + /* Honor corresponding variables, if IPSTEALTH is defined */ + V_nat64ipstealth = &V_ipstealth; + V_nat64ip6stealth = &V_ip6stealth; +#else + /* otherwise we need to decrement HLIM/TTL for direct case */ + V_nat64ipstealth = V_nat64ip6stealth = &stealth_off; +#endif + } else { + V_nat64out = &nat64_netisr; + /* Leave TTL/HLIM decrementing to forwarding code */ + V_nat64ipstealth = V_nat64ip6stealth = &stealth_on; + } } int @@ -486,8 +513,7 @@ nat64_init_ip4hdr(const struct ip6_hdr *ip6, const str ip->ip_tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; ip->ip_len = htons(sizeof(*ip) + plen); ip->ip_ttl = ip6->ip6_hlim; - /* Forwarding code will decrement TTL for netisr based output. */ - if (V_nat64out == &nat64_direct) + if (*V_nat64ip6stealth == 0) ip->ip_ttl -= IPV6_HLIMDEC; ip->ip_sum = 0; ip->ip_p = (proto == IPPROTO_ICMPV6) ? IPPROTO_ICMP: proto; @@ -623,18 +649,18 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint struct icmp6_hdr *icmp6; struct ip6_hdr *ip6, *oip6; struct mbuf *n; - int len, plen; + int len, plen, proto; len = 0; - plen = nat64_getlasthdr(m, &len); - if (plen < 0) { + proto = nat64_getlasthdr(m, &len); + if (proto < 0) { DPRINTF(DP_DROPS, "mbuf isn't contigious"); goto freeit; } /* * Do not send ICMPv6 in reply to ICMPv6 errors. */ - if (plen == IPPROTO_ICMPV6) { + if (proto == IPPROTO_ICMPV6) { if (m->m_len < len + sizeof(*icmp6)) { DPRINTF(DP_DROPS, "mbuf isn't contigious"); goto freeit; @@ -646,6 +672,21 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint "ICMPv6 errors"); goto freeit; } + /* + * If there are extra headers between IPv6 and ICMPv6, + * strip off them. + */ + if (len > sizeof(struct ip6_hdr)) { + /* + * NOTE: ipfw_chk already did m_pullup() and it is + * expected that data is contigious from the start + * of IPv6 header up to the end of ICMPv6 header. + */ + bcopy(mtod(m, caddr_t), + mtodo(m, len - sizeof(struct ip6_hdr)), + sizeof(struct ip6_hdr)); + m_adj(m, len - sizeof(struct ip6_hdr)); + } } /* if (icmp6_ratelimit(&ip6->ip6_src, type, code)) @@ -687,7 +728,19 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint n->m_len = n->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; oip6 = mtod(n, struct ip6_hdr *); - oip6->ip6_src = ip6->ip6_dst; + /* + * Make IPv6 source address selection for reflected datagram. + * nat64_check_ip6() doesn't allow scoped addresses, therefore + * we use zero scopeid. + */ + if (in6_selectsrc_addr(M_GETFIB(n), &ip6->ip6_src, 0, + n->m_pkthdr.rcvif, &oip6->ip6_src, NULL) != 0) { + /* + * Failed to find proper source address, drop the packet. + */ + m_freem(n); + goto freeit; + } oip6->ip6_dst = ip6->ip6_src; oip6->ip6_nxt = IPPROTO_ICMPV6; oip6->ip6_flow = 0; @@ -1182,7 +1235,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s ip = mtod(m, struct ip*); - if (ip->ip_ttl <= IPTTLDEC) { + if (*V_nat64ipstealth == 0 && ip->ip_ttl <= IPTTLDEC) { nat64_icmp_reflect(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, &cfg->stats, logdata); return (NAT64RETURN); @@ -1229,8 +1282,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s ip6.ip6_flow = htonl(ip->ip_tos << 20); ip6.ip6_vfc |= IPV6_VERSION; ip6.ip6_hlim = ip->ip_ttl; - /* Forwarding code will decrement TTL for netisr based output. */ - if (V_nat64out == &nat64_direct) + if (*V_nat64ipstealth == 0) ip6.ip6_hlim -= IPTTLDEC; ip6.ip6_plen = htons(plen); ip6.ip6_nxt = (proto == IPPROTO_ICMP) ? IPPROTO_ICMPV6: proto; @@ -1533,7 +1585,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui return (NAT64MFREE); } - if (ip6->ip6_hlim <= IPV6_HLIMDEC) { + if (*V_nat64ip6stealth == 0 && ip6->ip6_hlim <= IPV6_HLIMDEC) { nat64_icmp6_reflect(m, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0, &cfg->stats, logdata); return (NAT64RETURN);