tcp: improve blackhole support

There are two improvements to the TCP blackhole support:
(1) If net.inet.tcp.blackhole is set to 2, also sent no RST whenever
    a segment is received on an existing closed socket or if there is
    a port mismatch when using UDP encapsulation.
(2) If net.inet.tcp.blackhole is set to 3, no RST segment is sent in
    response to incoming segments on closed sockets or in response to
    unexpected segments on listening sockets.
Thanks to gallatin@ for suggesting such an improvement.

Reviewed by:		gallatin
MFC after:		1 week
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D45304
This commit is contained in:
Michael Tuexen 2024-05-24 06:59:13 +02:00
parent 40d951bc59
commit 02d15215ce
2 changed files with 26 additions and 27 deletions

View File

@ -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 @@ MIB for manipulating behaviour in respect of refused SCTP, TCP, or UDP connectio
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 @@ The
.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 @@ is merely dropped, and no RST is sent, making the system appear
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

View File

@ -915,23 +915,6 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port)
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 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port)
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)