diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4 --- a/share/man/man4/inet.4 +++ b/share/man/man4/inet.4 @@ -219,6 +219,14 @@ .Xr pfil 4 filters may override and bypass this check. Disabled by default. +.It Va ip.source_address_validation +Boolean: perform source address validation for packets destined for the local +host. +Consider this as following Section 3.2 of RFC3704/BCP84, where we treat local +host as our own infrastructure. +This has no effect on packets to be forwarded, so don't consider it as +anti-spoof feature for a router. +Enabled by default. .It Va ip.rfc6864 Boolean: control IP IDs generation behaviour. True value enables RFC6864 support, which specifies that IP ID field of diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -124,6 +124,12 @@ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_strong_es), false, "Packet's IP destination address must match address on arrival interface"); +VNET_DEFINE_STATIC(bool, ip_sav) = true; +#define V_ip_sav VNET(ip_sav) +SYSCTL_BOOL(_net_inet_ip, OID_AUTO, source_address_validation, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_sav), true, + "Drop incoming packets with source address that is a local address"); + VNET_DEFINE(pfil_head_t, inet_pfil_head); /* Packet filter hooks */ static struct netisr_handler ip_nh = { @@ -683,6 +689,16 @@ goto bad; } + /* + * net.inet.ip.source_address_validation: drop incoming + * packets that pretend to be ours. + */ + if (V_ip_sav && !(ifp->if_flags & IFF_LOOPBACK) && + __predict_false(in_localip_fib(ip->ip_src, ifp->if_fib))) { + IPSTAT_INC(ips_badaddr); + goto bad; + } + counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); counter_u64_add(ia->ia_ifa.ifa_ibytes, m->m_pkthdr.len); goto ours;