Skip site navigation (1)Skip section navigation (2)
Date:      27 Jul 1999 13:26:21 +0200
From:      Dag-Erling Smorgrav <des@yes.no>
To:        net@freebsd.org
Subject:   TCP/IP hardening, take two
Message-ID:  <xzpemhubag2.fsf@des.follo.net>

next in thread | raw e-mail | index | archive | help
I cleaned up the previously posted patches, tested them a little more,
and added a sysctl knob for logging SYN+FIN packets (before optionally
dropping them).

A FreeBSD 4.0-CURRENT machine with these patches and no firewall looks
like this to nmap (with tcp.drop_synfin and tcp.restrict_rst enabled):

| Starting nmap V. 2.12 by Fyodor (fyodor@dhp.com, www.insecure.org/nmap/)
| Interesting ports on destmp.follo.net (195.204.143.235):
| (Not showing ports in state: filtered)
| Port    State       Protocol  Service
| 22      open        tcp        ssh             
| 
| TCP Sequence Prediction: Class=random positive increments
|                          Difficulty=38742 (Worthy challenge)
| No OS matches for host (see http://www.insecure.org/cgi-bin/nmap-submit.cgi).
| TCP/IP fingerprint:
| TSeq(Class=RI%gcd=2%SI=1429)
| TSeq(Class=RI%gcd=1%SI=1026)
| TSeq(Class=RI%gcd=1%SI=9756)
| T1(Resp=Y%DF=Y%W=402E%ACK=S++%Flags=AS%Ops=M)
| T2(Resp=N)
| T3(Resp=N)
| T4(Resp=N)
| T5(Resp=N)
| T6(Resp=N)
| T7(Resp=N)
| PU(Resp=Y%DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=F%RIPCK=F%UCK=0%ULEN=134%DAT=E)
| 
| 
| Nmap run completed -- 1 IP address (1 host up) scanned in 75 seconds

Note: The TCP sequence prediction difficulty rating is meaningless,
Successive nmap runs show ratings from approx. 5000 to approx. 40000
for the same computer with the same software.
 
DES
-- 
Dag-Erling Smorgrav - des@yes.no

Index: etc/defaults/rc.conf
===================================================================
RCS file: /home/ncvs/src/etc/defaults/rc.conf,v
retrieving revision 1.23
diff -u -r1.23 rc.conf
--- rc.conf	1999/07/26 10:49:33	1.23
+++ rc.conf	1999/07/27 11:18:30
@@ -48,6 +48,12 @@
 tcp_extensions="NO"		# Set to Yes to turn on RFC1323 extensions.
 log_in_vain="NO"		# Disallow bad connection logging (or YES).
 tcp_keepalive="YES"		# Kill dead TCP connections (or NO).
+tcp_drop_synfin="NO"		# Set to YES to drop TCP packets with SYN+FIN
+				# NOTE: this breaks rfc1644 extensions (T/TCP)
+tcp_log_synfin="NO"		# Set to YES to log TCP packets with SYN+FIN
+tcp_restrict_rst="NO"		# Set to YES to restrict emission of RST
+icmp_dropredirect="NO"		# Set to YES to ignore ICMP REDIRECT packets
+icmp_logredirect="NO"		# Set to YES to log ICMP REDIRECT packets
 network_interfaces="auto"	# List of network interfaces (or "auto").
 ifconfig_lo0="inet 127.0.0.1"	# default loopback device configuration.
 #ifconfig_lo0_alias0="inet 127.0.0.254 netmask 0xffffffff" # Sample alias entry.
Index: etc/rc.network
===================================================================
RCS file: /home/ncvs/src/etc/rc.network,v
retrieving revision 1.52
diff -u -r1.52 rc.network
--- rc.network	1999/07/26 15:17:23	1.52
+++ rc.network	1999/07/27 11:18:30
@@ -197,6 +197,16 @@
 	    echo -n ' broadcast ping responses=YES'
 	    sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null
     fi
+    
+    if [ "X$icmp_dropredirect" = X"YES" ]; then
+	    echo -n ' ignore ICMP redirect=YES'
+	    sysctl -w net.inet.icmp.dropredirect=1 >/dev/null
+    fi
+    
+    if [ "X$icmp_logredirect" = X"YES" ]; then
+	    echo -n ' log ICMP redirect=YES'
+	    sysctl -w net.inet.icmp.logredirect=1 >/dev/null
+    fi
 
     if [ "X$gateway_enable" = X"YES" ]; then
 	    echo -n ' IP gateway=YES'
@@ -216,6 +226,21 @@
     if [ "X$tcp_keepalive" = X"YES" ]; then
 	    echo -n ' TCP keepalive=YES'
 	    sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null
+    fi
+
+    if [ "X$tcp_drop_synfin" = X"YES" ]; then
+	    echo -n ' drop SYN+FIN packets=YES'
+	    sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null
+    fi
+
+    if [ "X$tcp_log_synfin" = X"YES" ]; then
+	    echo -n ' log SYN+FIN packets=YES'
+	    sysctl -w net.inet.tcp.log_synfin=1 >/dev/null
+    fi
+
+    if [ "X$tcp_restrict_rst" = X"YES" ]; then
+	    echo -n ' restrict TCP reset=YES'
+	    sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null
     fi
 
     if [ "X$ipxgateway_enable" = X"YES" ]; then
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.144
diff -u -r1.144 options
--- options	1999/07/05 20:19:34	1.144
+++ options	1999/07/27 11:18:30
@@ -207,6 +207,8 @@
 INET			opt_inet.h
 IPDIVERT
 DUMMYNET		opt_ipdn.h
+IPFILTER		opt_ipfilter.h
+IPFILTER_LOG		opt_ipfilter.h
 IPFIREWALL		opt_ipfw.h
 IPFIREWALL_VERBOSE	opt_ipfw.h
 IPFIREWALL_VERBOSE_LIMIT	opt_ipfw.h
@@ -220,11 +222,11 @@
 PPP_BSDCOMP		opt_ppp.h
 PPP_DEFLATE		opt_ppp.h
 PPP_FILTER		opt_ppp.h
+SLIP_IFF_OPTS		opt_slip.h
 TCP_COMPAT_42		opt_compat.h
 TCPDEBUG
-IPFILTER		opt_ipfilter.h
-IPFILTER_LOG		opt_ipfilter.h
-SLIP_IFF_OPTS		opt_slip.h
+TCP_DROP_SYNFIN		opt_tcp_input.h
+TCP_RESTRICT_RST	opt_tcp_input.h
 
 # ATM (HARP version)
 ATM_CORE		opt_atm.h
Index: sys/i386/conf/LINT
===================================================================
RCS file: /home/ncvs/src/sys/i386/conf/LINT,v
retrieving revision 1.620
diff -u -r1.620 LINT
--- LINT	1999/07/26 05:47:17	1.620
+++ LINT	1999/07/27 11:18:30
@@ -469,6 +469,20 @@
 options 	IPSTEALTH		#support for stealth forwarding
 options 	TCPDEBUG
 
+# The following options add sysctl variables for controlling how certain
+# TCP packets are handled.
+# 
+# TCP_DROP_SYNFIN adds support for ignoring TCP packets with SYN+FIN. This
+# prevents nmap et al. from identifying the TCP/IP stack, but breaks support
+# for RFC1644 extensions and is not recommended for web servers.
+# 
+# TCP_RESTRICT_RST adds support for blocking the emission of TCP RST packets.
+# This is useful on systems which are exposed to SYN floods (e.g. IRC servers)
+# or any system which one does not want to be easily portscannable.
+# 
+options 	TCP_DROP_SYNFIN		#drop TCP packets with SYN+FIN
+options 	TCP_RESTRICT_RST	#restrict emission of TCP RST
+
 # ICMP_BANDLIM enables icmp error response bandwidth limiting.   You
 # typically want this option as it will help protect the machine from
 # D.O.S. packet attacks.
Index: sys/netinet/ip_icmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.34
diff -u -r1.34 ip_icmp.c
--- ip_icmp.c	1999/03/06 23:10:42	1.34
+++ ip_icmp.c	1999/07/27 11:18:30
@@ -69,6 +69,14 @@
 SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
 	&icmpmaskrepl, 0, "");
 
+static int	logredirect = 0;
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, logredirect, CTLFLAG_RW, 
+	&logredirect, 0, "");
+
+static int	dropredirect = 0;
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, dropredirect, CTLFLAG_RW, 
+	&dropredirect, 0, "");
+
 #ifdef ICMP_BANDLIM 
  
 /*    
@@ -92,8 +100,8 @@
  */
 
 static int	icmpbmcastecho = 0;
-SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho,
-	   0, "");
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW,
+	&icmpbmcastecho, 0, "");
 
 
 #ifdef ICMPPRINTFS
@@ -462,6 +470,23 @@
 		return;
 
 	case ICMP_REDIRECT:
+		if (logredirect) {
+			u_long src, dst, gw;
+
+			src = ntohl(ip->ip_src.s_addr);
+			dst = ntohl(icp->icmp_ip.ip_dst.s_addr);
+			gw = ntohl(icp->icmp_gwaddr.s_addr);
+			printf("icmp_redirect from %d.%d.%d.%d: "
+			       "%d.%d.%d.%d => %d.%d.%d.%d\n",
+			       (int)(src >> 24), (int)((src & 0xff0000) >> 16),
+			       (int)((src & 0xff00) >> 8), (int)(src & 0xff),
+			       (int)(dst >> 24), (int)((dst & 0xff0000) >> 16),
+			       (int)((dst & 0xff00) >> 8), (int)(dst & 0xff),
+			       (int)(gw >> 24), (int)((gw & 0xff0000) >> 16),
+			       (int)((gw & 0xff00) >> 8), (int)(gw & 0xff));
+		}
+		if (dropredirect)
+			break;
 		if (code > 3)
 			goto badcode;
 		if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.87
diff -u -r1.87 tcp_input.c
--- tcp_input.c	1999/07/18 14:42:48	1.87
+++ tcp_input.c	1999/07/27 11:18:30
@@ -36,6 +36,7 @@
 
 #include "opt_ipfw.h"		/* for ipfw_fwd		*/
 #include "opt_tcpdebug.h"
+#include "opt_tcp_input.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -78,7 +79,7 @@
 
 struct	tcpstat tcpstat;
 SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RD, 
-    &tcpstat , tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
+    &tcpstat, tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
 
 static int log_in_vain = 0;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW, 
@@ -89,6 +90,21 @@
     &tcp_delack_enabled, 0, 
     "Delay ACK to try and piggyback it onto a data packet");
 
+#ifdef TCP_RESTRICT_RST
+static int restrict_rst = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, restrict_rst, CTLFLAG_RW,
+    &restrict_rst, 0, "Restrict RST emission");
+#endif
+
+#ifdef TCP_DROP_SYNFIN
+static int drop_synfin = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW,
+    &drop_synfin, 0, "Drop TCP packets with SYN+FIN set");
+static int log_synfin = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_synfin, CTLFLAG_RW,
+    &log_synfin, 0, "Log TCP packets with SYN+FIN set");
+#endif
+
 u_long	tcp_now;
 struct inpcbhead tcb;
 struct inpcbinfo tcbinfo;
@@ -336,6 +352,28 @@
 	}
 	tiflags = ti->ti_flags;
 
+#ifdef TCP_DROP_SYNFIN
+	/*
+	 * If the drop_synfin option is enabled, drop all packets with
+	 * both the SYN and FIN bits set. This prevents e.g. nmap from
+	 * identifying the TCP/IP stack.
+	 *
+	 * This is incompatible with RFC1644 extensions (T/TCP).
+	 */
+	if (tiflags & TH_SYN && tiflags & TH_FIN) {
+		if (log_synfin) {
+			u_long src;
+
+			src = ntohl(ti->ti_src.s_addr);
+			printf("SYN+FIN from %d.%d.%d.%d\n",
+			       (int)(src >> 24), (int)((src & 0xff0000) >> 16),
+			       (int)((src & 0xff00) >> 8), (int)(src & 0xff));
+		}
+		if (drop_synfin)
+			goto drop;
+	}
+#endif
+
 	/*
 	 * Convert TCP protocol specific fields to host format.
 	 */
@@ -1764,6 +1802,10 @@
 	return;
 
 dropwithreset:
+#ifdef TCP_RESTRICT_RST
+	if (restrict_rst)
+		goto drop;
+#endif
 	/*
 	 * Generate a RST, dropping incoming segment.
 	 * Make ACK acceptable to originator of segment.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?xzpemhubag2.fsf>