Patch for linux kernel 2.2.14 to discard packets that many OS detection tools use to query the TCP/IP stack.
c84594838465fe09706a766e9b8530454728fe6dcbf3ef3079659c0e2e691eb2
diff -urP linux/Documentation/Configure.help linux/Documentation/Configure.help
--- linux/Documentation/Configure.help Tue Jan 4 13:12:10 2000
+++ linux/Documentation/Configure.help Thu Feb 10 17:29:48 2000
@@ -12039,7 +12039,40 @@
If you do not have any Quicknet telephony cards, you can safely
ignore this option.
-
+
+Deny packets with SYN and FIN set.
+CONFIG_TCPIP_STACK_SYNFIN
+ This will DENY all incoming packets with the SYN & FIN flags set. Much
+ like the option TCP_DROP_SYNFIN in the FreeBSD kernel config. This
+ breaks RFC 1644 but say Y if security is more important.
+
+Drop packets without SYN, FIN or RST
+CONFIG_TCPIP_STACK_BOGUS
+ All incoming TCP packets must have either SYN, FIN or RST set, or the
+ packet will be dropped. Say Y if security is more important.
+
+Deny packets looking for ACK values
+CONFIG_TCPIP_STACK_ACK
+ Typlicly OS detection tools will send packets to an open port looking for
+ the ACK to be the same as the ISN, or ISN++. This will deny incoming TCP
+ packets with FIN, PSH and URG set, thus blocking packets with SYN,
+ FIN, URG and PSH also. Packets of these structure are use in OS detection
+ utilites such as nmap (test 3 & 7). Say Y if security is more important.
+
+Block outgoing ICMP Port Unreachable Messages
+CONFIG_TCPIP_STACK_ICMP_PU
+ Instead of limiting the rate that the kernel sends destination port
+ unreachable messages, totaly block them. Setting this will block all UDP
+ portscans, and block packets used for OS detection (nmap's PU test). This
+ breaks allot of RFC's, as do many of these TCPIP configurable stack
+ options. Say N if you plan to do this with ipchains, otherwise say Y.
+
+Log all packets with bad flags
+CONFIG_TCPIP_STACK_LOG
+ This would probably be a good idea if you are interested in knowing what
+ is going on, on your system. Any TCP packets you set to deny above will
+ be logged, the logs will also include the flags used.
+
#
# A couple of things I keep forgetting:
# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
diff -urP linux/arch/i386/config.in linux/arch/i386/config.in
--- linux/arch/i386/config.in Tue Jan 4 13:12:11 2000
+++ linux/arch/i386/config.in Thu Feb 10 17:29:48 2000
@@ -207,3 +207,12 @@
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+mainmenu_option next_comment
+comment 'TCP/IP stack options'
+
+bool 'Deny packets with SYN and FIN set' CONFIG_TCPIP_STACK_SYNFIN
+bool 'Drop packets without SYN, FIN or RST' CONFIG_TCPIP_STACK_BOGUS
+bool 'Deny packets looking for ACK values' CONFIG_TCPIP_STACK_ACK
+bool 'Block outgoing ICMP Port Unreachable Messages' CONFIG_TCPIP_STACK_ICMP_PU
+bool 'Log all packets with bad tcp flags' CONFIG_TCPIP_STACK_LOG
+endmenu
diff -urP linux/arch/i386/defconfig linux/arch/i386/defconfig
--- linux/arch/i386/defconfig Wed Aug 25 20:29:46 1999
+++ linux/arch/i386/defconfig Thu Feb 10 17:29:48 2000
@@ -354,6 +354,15 @@
# CONFIG_SOUND is not set
#
+# TCP/IP stack
+#
+CONFIG_TCPIP_STACK_SYNFIN=y
+CONFIG_TCPIP_STACK_BOGUS=y
+CONFIG_TCPIP_STACK_ACK=y
+CONFIG_TCPIP_STACK_ICMP_PU=n
+CONFIG_TCPIP_STACK_LOG=y
+
+#
# Kernel hacking
#
# CONFIG_MAGIC_SYSRQ is not set
diff -urP linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- linux/net/ipv4/tcp_ipv4.c Tue Jan 4 13:12:27 2000
+++ linux/net/ipv4/tcp_ipv4.c Thu Feb 10 17:34:59 2000
@@ -1708,6 +1708,21 @@
if (len < sizeof(struct tcphdr))
goto bad_packet;
+#ifdef CONFIG_TCPIP_STACK_SYNFIN
+ if(th->fin && th->syn)
+ goto tcp_bad_flag;
+#endif
+
+#ifdef CONFIG_TCPIP_STACK_BOGUS
+ if(!(th->ack || th->syn || th->rst))
+ goto tcp_bad_flag;
+#endif
+
+#ifdef CONFIG_TCPIP_STACK_ACK
+ if(th->fin && th->psh && th->urg)
+ goto tcp_bad_flag;
+#endif
+
/* Try to use the device checksum if provided. */
switch (skb->ip_summed) {
case CHECKSUM_NONE:
@@ -1768,6 +1783,31 @@
__skb_queue_tail(&sk->back_log, skb);
return 0;
+
+#ifdef CONFIG_TCPIP_STACK_LOG
+
+tcp_bad_flag:
+ printk(KERN_INFO
+ "Packet log: badflag DENY %s PROTO=TCP %d.%d.%d.%d:%d "
+ "%d.%d.%d.%d:%d L=%hu:%u:%u S=0x%2.2hX I=%hu:%u:%u "
+ "T=%hu %c%c%c%c%c%c\n",
+ skb->dev->name, NIPQUAD(skb->nh.iph->saddr), ntohs(th->source),
+ NIPQUAD(skb->nh.iph->daddr), ntohs(th->dest),
+ ntohs(skb->nh.iph->tot_len), skb->len, skb->len - th->doff*4,
+ skb->nh.iph->tos, ntohs(skb->nh.iph->id), ntohl(th->seq),
+ ntohl(th->ack_seq), skb->nh.iph->ttl,
+ th->ack ? 'A' : '.',
+ th->syn ? 'S' : '.',
+ th->fin ? 'F' : '.',
+ th->rst ? 'R' : '.',
+ th->psh ? 'P' : '.',
+ th->urg ? 'U' : '.' );
+ goto bad_packet;
+
+#else
+tcp_bad_flag:
+ goto bad_packet;
+#endif
no_tcp_socket:
tcp_v4_send_reset(skb);
diff -urP linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- linux/net/ipv4/udp.c Mon Aug 9 15:05:10 1999
+++ linux/net/ipv4/udp.c Thu Feb 10 17:29:48 2000
@@ -1131,9 +1131,12 @@
(unsigned short)csum_fold(csum_partial((char*)uh, ulen, skb->csum)))
goto csum_error;
#endif
- udp_statistics.UdpNoPorts++;
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+ udp_statistics.UdpNoPorts++;
+#ifdef CONFIG_TCPIP_STACK_ICMP_PU
+#else
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+#endif
/*
* Hmm. We got an UDP broadcast to a port to which we
* don't wanna listen. Ignore it.