diff -uNr linux-2.0.33.pure/Documentation/Configure.help linux-2.0.33/Documentation/Configure.help --- linux-2.0.33.pure/Documentation/Configure.help Wed Dec 10 20:21:47 1997 +++ linux-2.0.33/Documentation/Configure.help Tue Apr 7 01:08:17 1998 @@ -4120,6 +4120,12 @@ removed from the running kernel whenever you want), say M and read Documentation/modules.txt. If unsure, say Y. +ktcp-strobemasker ignore time after flood/strobe +IGNORE_TIME + The amount of time that your system will continue to ignore the evil + evil system after the strobe. Note that this is the time your system + ignores AFTER the other system stops strobing/flooding. + # need an empty line after last entry, for sed script in Configure. # diff -uNr linux-2.0.33.pure/arch/i386/defconfig linux-2.0.33/arch/i386/defconfig --- linux-2.0.33.pure/arch/i386/defconfig Mon Sep 22 15:44:01 1997 +++ linux-2.0.33/arch/i386/defconfig Tue Apr 7 01:08:32 1998 @@ -72,6 +72,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +IGNORE_TIME=10 # # (it is safe to leave these untouched) diff -uNr linux-2.0.33.pure/net/Config.in linux-2.0.33/net/Config.in --- linux-2.0.33.pure/net/Config.in Tue Aug 12 13:30:22 1997 +++ linux-2.0.33/net/Config.in Tue Apr 7 01:08:01 1998 @@ -24,4 +24,7 @@ if [ "$CONFIG_NETLINK" = "y" ]; then bool 'Routing messages' CONFIG_RTNETLINK fi + +int 'post-strobe ignore period (secs)' IGNORE_TIME 10 + endmenu diff -uNr linux-2.0.33.pure/net/ipv4/af_inet.c linux-2.0.33/net/ipv4/af_inet.c --- linux-2.0.33.pure/net/ipv4/af_inet.c Fri Aug 15 14:23:23 1997 +++ linux-2.0.33/net/ipv4/af_inet.c Mon Apr 6 00:36:21 1998 @@ -778,6 +778,9 @@ sk2 = sk1->prot->accept(sk1,flags); if (sk2 == NULL) return sock_error(sk1); + else + printk ( KERN_INFO "TCP connection accepted: ip=%d.%d.%d.%d port=%d uid=%d process=%s[%d]\n", + NIPQUAD(sk2->daddr), sk2->num, current->uid, current->comm, current->pid ); } newsock->data = (void *)sk2; sk2->sleep = newsock->wait; diff -uNr linux-2.0.33.pure/net/ipv4/icmp.c linux-2.0.33/net/ipv4/icmp.c --- linux-2.0.33.pure/net/ipv4/icmp.c Mon Sep 15 11:54:52 1997 +++ linux-2.0.33/net/ipv4/icmp.c Mon Apr 6 21:29:53 1998 @@ -1125,6 +1125,23 @@ } len-=sizeof(struct icmphdr); + switch(icmph->type) { + case ICMP_DEST_UNREACH: + printk(KERN_INFO "ICMP destination unreachable from %d.%d.%d.%d\n", NIPQUAD(saddr)); + break; + case ICMP_SOURCE_QUENCH: + printk(KERN_INFO "ICMP source quench from %d.%d.%d.%d\n", NIPQUAD(saddr)); + break; + case ICMP_REDIRECT: + printk(KERN_INFO "ICMP redirect from %d.%d.%d.%d\n", NIPQUAD(saddr)); + break; + case ICMP_ECHO: + printk(KERN_INFO "ICMP %d-byte ping from %d.%d.%d.%d\n", len, NIPQUAD(saddr)); + break; + case ICMP_INFO_REQUEST: + printk(KERN_INFO "ICMP info request from %d.%d.%d.%d\n", NIPQUAD(saddr)); + break; + } (*icmp_pointers[icmph->type].input)++; (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len); return 0; diff -uNr linux-2.0.33.pure/net/ipv4/tcp_input.c linux-2.0.33/net/ipv4/tcp_input.c --- linux-2.0.33.pure/net/ipv4/tcp_input.c Fri Oct 31 13:34:12 1997 +++ linux-2.0.33/net/ipv4/tcp_input.c Tue Apr 7 11:44:21 1998 @@ -43,6 +43,17 @@ #include #include + +#ifndef IGNORE_TIME +#define IGNORE_TIME 10 +#endif + +#define STROBE_OK 1 +#define STROBE_DENY 2 +#define STROBE_STROBE 3 +extern strobe_check(unsigned long sourceaddr, struct sock * sk, unsigned int port); + + /* * Policy code extracted so it's now separate */ @@ -2311,8 +2322,48 @@ else #endif sk = __tcp_v4_lookup(th, saddr, th->source, daddr, th->dest, dev); - if (!sk) + + +#ifdef CONFIG_IP_TRANSPARENT_PROXY + if (((sk && sk->state == TCP_LISTEN && !th->ack ) || !sk || + (th->syn && !th->ack && !th->rst)) && ntohs(th->dest) <= 1000 && ((r = ip_chk_addr(daddr)) != IS_BROADCAST || r != IS_MULTICAST)) { +#else + if (((sk && sk->state == TCP_LISTEN && !th->ack ) || !sk || + (th->syn && !th->ack && !th->rst)) && ntohs(th->dest) <= 1000 && ip_chk_addr(daddr)==IS_MYADDR) { +#endif + switch(strobe_check(saddr, sk, (ntohs(th->dest)+65537) )) { + case STROBE_DENY: + goto no_tcp_socket; + break; + case STROBE_OK: + break; + case STROBE_STROBE: + printk(KERN_CRIT "possible TCP strobe from %d.%d.%d.%d, rejecting for %d seconds\n", + NIPQUAD(saddr), IGNORE_TIME ); + goto no_tcp_socket; + break; + } + } + + if (!sk) { + /* anything over 1000 is most likely nothing...dont cloud up the logfiles or raise unneeded suspicion*/ +tcpaudit: + if(ntohs(th->dest) <= 1000) { + switch(th->syn) { + case 1: + printk( KERN_INFO "TCP connection rejected from %d.%d.%d.%d, port %d\n", + NIPQUAD(saddr), ntohs(th->dest) ); + break; + case 0: + printk( KERN_INFO "unexpected TCP packet from %d.%d.%d.%d to port %d [syn:%d|fin:%d|rst:%d|ack:%d]\n", + NIPQUAD(saddr), ntohs(th->dest), th->syn, th->fin, th->rst, th->ack); + break; + } + } goto no_tcp_socket; + } + + skb->sk = sk; skb->seq = ntohl(th->seq); skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4; @@ -2334,6 +2385,7 @@ } } + /* * If this socket has got a reset it's to all intents and purposes * really dead. Count closed sockets as dead. @@ -2420,30 +2472,30 @@ } } #endif - tcp_send_reset(daddr,saddr,th,sk->prot,opt,dev,0, 255); + goto tcpaudit; } - /* - * We don't care for RST, and non SYN are absorbed (old segments) - * Broadcast/multicast SYN isn't allowed. Note - bug if you change the - * netmask on a running connection it can go broadcast. Even Sun's have - * this problem so I'm ignoring it - */ - + /* + * We don't care for RST, and non SYN are absorbed (old segments) + * Broadcast/multicast SYN isn't allowed. Note - bug if you change the + * netmask on a running connection it can go broadcast. Even Sun's have + * this problem so I'm ignoring it + */ + #ifdef CONFIG_IP_TRANSPARENT_PROXY - /* - * We may get non-local addresses and still want to - * handle them locally, due to transparent proxying. - * Thus, narrow down the test to what is really meant. - */ - if(th->rst || !th->syn || th->ack || (r = ip_chk_addr(daddr)) == IS_BROADCAST || r == IS_MULTICAST) + /* + * We may get non-local addresses and still want to + * handle them locally, due to transparent proxying. + * Thus, narrow down the test to what is really meant. + */ + if(th->rst || !th->syn || th->ack || (r = ip_chk_addr(daddr)) == IS_BROADCAST || r == IS_MULTICAST) #else - if(th->rst || !th->syn || th->ack || ip_chk_addr(daddr)!=IS_MYADDR) + if(th->rst || !th->syn || th->ack || ip_chk_addr(daddr)!=IS_MYADDR) #endif - { - kfree_skb(skb, FREE_READ); - return 0; - } + { + kfree_skb(skb, FREE_READ); + return 0; + } /* * Guess we need to make a new socket up diff -uNr linux-2.0.33.pure/net/ipv4/udp.c linux-2.0.33/net/ipv4/udp.c --- linux-2.0.33.pure/net/ipv4/udp.c Wed Dec 10 11:14:01 1997 +++ linux-2.0.33/net/ipv4/udp.c Tue Apr 7 17:21:24 1998 @@ -116,6 +116,11 @@ #include #include +extern strobe_check(unsigned long sourceaddr, struct sock * sk, unsigned int port); +#define STROBE_OK 1 +#define STROBE_DENY 2 +#define STROBE_STROBE 3 + /* * Snmp MIB for the UDP layer */ @@ -1089,24 +1094,37 @@ else #endif sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, dev); + if ((addr_type == IS_MULTICAST || addr_type == IS_BROADCAST) && sk == NULL) goto udp_drop; + switch(strobe_check(saddr, sk, ntohs(uh->dest) )) { + case STROBE_OK: + break; + case STROBE_DENY: + goto udp_deny; + case STROBE_STROBE: + printk(KERN_CRIT "possible UDP strobe from %d.%d.%d.%d, rejecting for %d seconds\n", + NIPQUAD(saddr), IGNORE_TIME); + goto udp_deny; + } + - if (sk == NULL) - { - udp_statistics.UdpNoPorts++; - if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST) - { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev); - } - /* - * Hmm. We got an UDP broadcast to a port to which we - * don't wanna listen. Ignore it. - */ - skb->sk = NULL; - kfree_skb(skb, FREE_WRITE); - return(0); - } + if (sk == NULL) { + printk( KERN_INFO "UDP packet rejected from %d.%d.%d.%d, port %d\n", NIPQUAD(saddr), ntohs(uh->dest) ); + goto udp_deny; + } udp_deliver(sk, skb); return 0; + +udp_deny: + udp_statistics.UdpNoPorts++; + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev); + /* + * Hmm. We got an UDP broadcast to a port to which we + * don't wanna listen. Ignore it. + */ +udp_drop: + skb->sk = NULL; + kfree_skb(skb, FREE_WRITE); + return(0); } struct proto udp_prot = { diff -uNr linux-2.0.33.pure/net/ipv4/utils.c linux-2.0.33/net/ipv4/utils.c --- linux-2.0.33.pure/net/ipv4/utils.c Tue Aug 1 02:02:49 1995 +++ linux-2.0.33/net/ipv4/utils.c Tue Apr 7 17:15:47 1998 @@ -41,6 +41,28 @@ #include #include +#ifndef MAX_SYN_SEC +#define MAX_SYN_SEC 3 +#endif + +#ifndef IGNORE_TIME +#define IGNORE_TIME 10 +#endif + +#define MAX_FLOOD 64 /* a good round number */ +#define STROBE_STROBE 3 +#define STROBE_DENY 2 +#define STROBE_OK 1 + +static struct flood { + u32 ip; + unsigned int port; + unsigned int count; + unsigned long timestamp; +} flood_hash[MAX_FLOOD]; + +int strobe_check(unsigned long sourceaddr, struct sock * sk, unsigned int port); + /* * Display an IP address in readable format. @@ -87,5 +109,44 @@ } } return(htonl(l)); +} + +int strobe_check(unsigned long sourceaddr, struct sock * sk, unsigned int port) { + /* for strobe hash table index */ + unsigned int dummy_temp, dummy_temp2; + + cli(); /* Don't know much about race conditions, cli()/sti() actually needed? */ + /* We wouldnt want our flood_hash being changed underneath us. */ + /* this code probably isnt very readable, tried to optimize for speed */ + dummy_temp2 = dummy_temp = sourceaddr % MAX_FLOOD; +restart_fhash: + if ( (flood_hash[dummy_temp].timestamp < xtime.tv_sec) ) { /* simplest case: slot useable and expired */ + if (!sk ) { + flood_hash[dummy_temp].port = port; + flood_hash[dummy_temp].ip = sourceaddr; + flood_hash[dummy_temp].count = 1; + flood_hash[dummy_temp].timestamp = xtime.tv_sec + 4; /* expire this entry in 4 seconds */ + } + } else { /* slot in use */ + if ( flood_hash[dummy_temp].ip != sourceaddr ) { /* handle collision */ + dummy_temp = (dummy_temp + 1) % MAX_FLOOD; + if (dummy_temp != dummy_temp2) goto restart_fhash; + printk(KERN_CRIT "flood hash full, not good...\n"); } + else { /* slot in use by this current ip, increment or deny */ + if ( flood_hash[dummy_temp].count >= MAX_SYN_SEC && ip_chk_addr(sourceaddr) != IS_MYADDR ) { + flood_hash[dummy_temp].timestamp = xtime.tv_sec + IGNORE_TIME; + if (flood_hash[dummy_temp].count == MAX_SYN_SEC) { + flood_hash[dummy_temp].count = MAX_SYN_SEC + 1; /* Takes care of logfile runaway */ + sti(); + return STROBE_STROBE; + } + sti(); + return STROBE_DENY; /* DENY */ + } + if (!sk && flood_hash[dummy_temp].port != port) flood_hash[dummy_temp].count++; + } + } + sti(); + return STROBE_OK; }