diff --git a/share/man/man4/blackhole.4 b/share/man/man4/blackhole.4 --- a/share/man/man4/blackhole.4 +++ b/share/man/man4/blackhole.4 @@ -10,7 +10,7 @@ .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" -.Dd May 22, 2024 +.Dd May 25, 2024 .Dt BLACKHOLE 4 .Os .Sh NAME @@ -21,7 +21,7 @@ attempts .Sh SYNOPSIS .Cd sysctl net.inet.sctp.blackhole Ns Op = Ns Brq "0 | 1 | 2" -.Cd sysctl net.inet.tcp.blackhole Ns Op = Ns Brq "0 | 1 | 2" +.Cd sysctl net.inet.tcp.blackhole Ns Op = Ns Brq "0 | 1 | 2 | 3" .Cd sysctl net.inet.tcp.blackhole_local Ns Op = Ns Brq "0 | 1" .Cd sysctl net.inet.udp.blackhole Ns Op = Ns Brq "0 | 1" .Cd sysctl net.inet.udp.blackhole_local Ns Op = Ns Brq "0 | 1" @@ -30,7 +30,8 @@ .Nm .Xr sysctl 8 MIB is used to control system behaviour when connection requests -are received on SCTP, TCP, or UDP ports where there is no socket listening. +are received on SCTP, TCP, or UDP ports where there is no socket listening +or unexpected packets are received on listening sockets. .Pp The blackhole behaviour is useful to slow down an attacker who is port-scanning a system in an attempt to detect vulnerable services. @@ -61,6 +62,9 @@ as a blackhole. By setting the MIB value to two, any segment arriving on a closed port is dropped without returning a RST. +Setting the MIB value to three, any segment arriving on a closed port +or an unexpected segment on a listening port is dropped without sending a +RST in reply. This provides some degree of protection against stealth port scans. .Ss UDP Enabling blackhole behaviour turns off the sending diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -915,23 +915,6 @@ log(LOG_INFO, "%s; %s: Connection attempt " "to closed port\n", s, __func__); } - /* - * When blackholing do not respond with a RST but - * completely ignore the segment and drop it. - */ - if (((V_blackhole == 1 && (thflags & TH_SYN)) || - V_blackhole == 2) && (V_blackhole_local || ( -#ifdef INET6 - isipv6 ? !in6_localaddr(&ip6->ip6_src) : -#endif -#ifdef INET - !in_localip(ip->ip_src) -#else - true -#endif - ))) - goto dropunlock; - rstreason = BANDLIM_RST_CLOSEDPORT; goto dropwithreset; } @@ -1410,15 +1393,27 @@ return (IPPROTO_DONE); dropwithreset: + /* + * When blackholing do not respond with a RST but + * completely ignore the segment and drop it. + */ + if (((rstreason == BANDLIM_RST_OPENPORT && V_blackhole == 3) || + (rstreason == BANDLIM_RST_CLOSEDPORT && + ((V_blackhole == 1 && (thflags & TH_SYN)) || V_blackhole > 1))) && + (V_blackhole_local || ( +#ifdef INET6 + isipv6 ? !in6_localaddr(&ip6->ip6_src) : +#endif +#ifdef INET + !in_localip(ip->ip_src) +#else + true +#endif + ))) + goto dropunlock; TCP_PROBE5(receive, NULL, tp, m, tp, th); - - if (inp != NULL) { - tcp_dropwithreset(m, th, tp, tlen, rstreason); - INP_UNLOCK(inp); - } else - tcp_dropwithreset(m, th, NULL, tlen, rstreason); + tcp_dropwithreset(m, th, tp, tlen, rstreason); m = NULL; /* mbuf chain got consumed. */ - goto drop; dropunlock: if (m != NULL)