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 Wed Feb 23 20:15:15 2000 @@ -1220,6 +1220,28 @@ If unsure, say Y. +IP: TCP stack options (not enabled per default) +CONFIG_NET_STEALTH + If you say Y here, note that these options are not enabled by + default; you can enable them by saying Y to "/proc filesystem + support" and "Sysctl support" below and executing the commands + + echo 1 >/proc/sys/net/ipv4/tcp_ignore_ack + echo 1 >/proc/sys/net/ipv4/tcp_ignore_bogus + echo 1 >/proc/sys/net/ipv4/tcp_ignore_synfin + + at boot time after the proc filesystem has been mounted. + + If you say M here, a module will be built that when inserted will + deny the same packets as above, but without the sysctl options. + + If security is more important, say Y or M. + +Log all droped packets +CONFIG_NET_STEALTH_LOG + This turns on a logging facility that logs all tcp packets with + bad flags. If you said Y to "TCP stack options", say Y. + Sun floppy controller support CONFIG_BLK_DEV_SUNFD This is support for floppy drives on Sun SPARC workstations. Say Y diff -urP linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- linux/arch/alpha/defconfig Tue Jan 4 13:12:10 2000 +++ linux/arch/alpha/defconfig Wed Feb 23 22:21:20 2000 @@ -102,6 +102,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/arch/arm/defconfig linux/arch/arm/defconfig --- linux/arch/arm/defconfig Thu Feb 25 13:46:46 1999 +++ linux/arch/arm/defconfig Wed Feb 23 22:22:16 2000 @@ -93,6 +93,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) 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 Wed Feb 23 22:23:08 2000 @@ -117,6 +117,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/arch/m68k/defconfig linux/arch/m68k/defconfig --- linux/arch/m68k/defconfig Thu Feb 25 13:46:46 1999 +++ linux/arch/m68k/defconfig Wed Feb 23 22:23:54 2000 @@ -89,6 +89,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/arch/mips/defconfig linux/arch/mips/defconfig --- linux/arch/mips/defconfig Mon Aug 9 15:04:38 1999 +++ linux/arch/mips/defconfig Wed Feb 23 22:24:35 2000 @@ -101,6 +101,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- linux/arch/sparc/defconfig Tue Oct 26 20:53:39 1999 +++ linux/arch/sparc/defconfig Wed Feb 23 22:25:44 2000 @@ -114,6 +114,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- linux/arch/sparc64/defconfig Tue Jan 4 13:12:13 2000 +++ linux/arch/sparc64/defconfig Wed Feb 23 22:26:34 2000 @@ -144,6 +144,8 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set +CONFIG_NET_STEALTH=y +CONFIG_NET_STEALTH_LOG=y # # (it is safe to leave these untouched) diff -urP linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- linux/include/linux/sysctl.h Tue Jan 4 13:12:25 2000 +++ linux/include/linux/sysctl.h Wed Feb 23 20:44:21 2000 @@ -227,7 +227,10 @@ NET_IPV4_ICMP_ECHOREPLY_RATE=63, NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64, NET_IPV4_IGMP_MAX_MEMBERSHIPS=65, - NET_IPV4_ALWAYS_DEFRAG=67 + NET_IPV4_ALWAYS_DEFRAG=67, + NET_TCP_STACK_SYNFIN=68, + NET_TCP_STACK_BOGUS=69, + NET_TCP_STACK_ACK=70 }; enum { diff -urP linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- linux/net/ipv4/Config.in Tue Oct 26 20:53:42 1999 +++ linux/net/ipv4/Config.in Wed Feb 23 22:34:23 2000 @@ -73,6 +73,10 @@ fi fi bool 'IP: TCP syncookie support (not enabled per default)' CONFIG_SYN_COOKIES +tristate 'IP: TCP stack options (not enabled per default)' CONFIG_NET_STEALTH +if [ "$CONFIG_NET_STEALTH" = "y" ]; then + bool 'Log all droped packets' CONFIG_NET_STEALTH_LOG +fi comment '(it is safe to leave these untouched)' #bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP tristate 'IP: Reverse ARP' CONFIG_INET_RARP diff -urP linux/net/ipv4/Makefile linux/net/ipv4/Makefile --- linux/net/ipv4/Makefile Mon Jan 4 18:31:35 1999 +++ linux/net/ipv4/Makefile Wed Feb 23 20:36:18 2000 @@ -58,6 +58,10 @@ MX_OBJS += ip_gre.o endif endif + +ifeq ($(CONFIG_NET_STEALTH),m) +M_OBJS += stealth.o +endif ifeq ($(CONFIG_IP_MASQUERADE),y) IPV4X_OBJS += ip_masq.o ip_masq_app.o diff -urP linux/net/ipv4/stealth.c linux/net/ipv4/stealth.c --- linux/net/ipv4/stealth.c Wed Dec 31 19:00:00 1969 +++ linux/net/ipv4/stealth.c Wed Feb 23 22:11:13 2000 @@ -0,0 +1,158 @@ +/* Stealth module by Derek Callaway -- S@IRC + * Original patch by Sean Trifero -- solar@IRC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __SMP__ +#define SLOT_NUMBER() (cpu_number_map[smp_processor_id()]*2 + !in_interrupt()) +#else +#define SLOT_NUMBER() (!in_interrupt()) +#endif + +#define STEALTH_INPUT_CHAIN stealth_chains +#define STEALTH_FORWARD_CHAIN (stealth_chains->next) +#define STEALTH_OUTPUT_CHAIN (stealth_chains->next->next) + +char *dev; +MODULE_PARM (dev, "s"); +struct device *d; + +/* Head of linked list of fw rules */ +struct ip_counters +{ + __u64 pcnt, bcnt; /* Packet and byte counters */ +}; + +struct ip_reent +{ + struct ip_chain *prevchain; /* Pointer to referencing chain */ + struct ip_fwkernel *prevrule; /* Pointer to referencing rule */ + struct ip_counters counters; +}; + + +struct ip_chain +{ + ip_chainlabel label; /* Defines the label for each block */ + struct ip_chain *next; /* Pointer to next block */ + struct ip_fwkernel *chain; /* Pointer to first rule in block */ + __u32 refcount; /* Number of refernces to block */ + int policy; /* Default rule for chain. Only * + * used in built in chains */ + struct ip_reent reent[0]; /* Actually several of these */ +}; + +static struct ip_chain *stealth_chains; + +int stealth_check (struct iphdr *, const char *, __u16 *, struct ip_chain *, + struct sk_buff *, unsigned int, int); + +int +stealth_input_check (struct firewall_ops *this, int pf, struct device *dev, + void *phdr, void *arg, struct sk_buff **pskb) +{ + return stealth_check (phdr, dev->name, + arg, STEALTH_INPUT_CHAIN, *pskb, SLOT_NUMBER (), 0); +} + +int +stealth_output_check (struct firewall_ops *this, int pf, struct device *dev, + void *phdr, void *arg, struct sk_buff **pksb) +{ + return (FW_SKIP); +} + +int +stealth_forward_check (struct firewall_ops *this, int pf, struct device *dev, + void *phdr, void *arg, struct sk_buff **pksb) +{ + return (FW_SKIP); +} + + +struct firewall_ops ipfw_ops = { + NULL, + stealth_output_check, + stealth_input_check, + stealth_forward_check, + PF_INET, + 31337 /* This priority should be adequate. */ +}; + +int +stealth_check (struct iphdr *ip, + const char *rif, + __u16 * redirport, + struct ip_chain *chain, + struct sk_buff *skb, unsigned int slot, int testing) +{ + struct tcphdr *tcp; + if (ip->protocol != IPPROTO_TCP) + { + /* Not a TCP packet, don't worry about it. */ + return (FW_SKIP); + } + tcp = (struct tcphdr *) ((__u32 *) ip + ip->ihl); + switch (tcp->fin) + { + case 0: + /* I know goto statements should be avoided but I + * seriously doubt that this will evolve into + * spaghetti code. Futhermore, these jumps are + * extremely localized. */ + goto done; + default: + if ((tcp->syn) || (tcp->psh && tcp->urg)) + { + goto tcp_bad_flags; + } + } + if (!(tcp->ack || tcp->syn || tcp->rst)) + { + goto tcp_bad_flags; + } + goto done; +tcp_bad_flags: + 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 (skb->h.th->source), NIPQUAD (skb->nh.iph->daddr), + ntohs (skb->h.th->dest), ntohs (skb->nh.iph->tot_len), skb->len, + skb->len - skb->h.th->doff * 4, skb->nh.iph->tos, + ntohs (skb->nh.iph->id), ntohl (skb->h.th->seq), + ntohl (skb->h.th->ack_seq), skb->nh.iph->ttl, + skb->h.th->ack ? 'A' : '.', skb->h.th->syn ? 'S' : '.', + skb->h.th->fin ? 'F' : '.', skb->h.th->rst ? 'R' : '.', + skb->h.th->psh ? 'P' : '.', skb->h.th->urg ? 'U' : '.'); + return (FW_BLOCK); +done: + return (FW_SKIP); +} + +int +init_module (void) +{ + printk ("Stealth initiated...\n"); + register_firewall (PF_INET, &ipfw_ops); + return (0); +} + +void +cleanup_module (void) +{ + unregister_firewall (PF_INET, &ipfw_ops); + printk ("Stealth removed.\n"); +} diff -urP linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- linux/net/ipv4/sysctl_net_ipv4.c Tue Oct 26 20:53:42 1999 +++ linux/net/ipv4/sysctl_net_ipv4.c Wed Feb 23 20:17:26 2000 @@ -63,6 +63,9 @@ extern int sysctl_tcp_rfc1337; extern int sysctl_tcp_syn_taildrop; extern int sysctl_max_syn_backlog; +extern int sysctl_tcp_ignore_synfin; +extern int sysctl_tcp_ignore_bogus; +extern int sysctl_tcp_ignore_ack; /* From icmp.c */ extern int sysctl_icmp_destunreach_time; @@ -172,6 +175,14 @@ #ifdef CONFIG_SYN_COOKIES {NET_TCP_SYNCOOKIES, "tcp_syncookies", &sysctl_tcp_syncookies, sizeof(int), 0644, NULL, &proc_dointvec}, +#endif +#ifdef CONFIG_NET_STEALTH + {NET_TCP_STACK_SYNFIN, "tcp_ignore_synfin", + &sysctl_tcp_ignore_synfin, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_TCP_STACK_BOGUS, "tcp_ignore_bogus", + &sysctl_tcp_ignore_bogus, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_TCP_STACK_ACK, "tcp_ignore_ack", + &sysctl_tcp_ignore_ack, sizeof(int), 0644, NULL, &proc_dointvec}, #endif {NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg, sizeof(int), 0644, NULL, &proc_dointvec}, diff -urP linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- linux/net/ipv4/tcp_input.c Tue Jan 4 13:12:27 2000 +++ linux/net/ipv4/tcp_input.c Wed Feb 23 19:56:52 2000 @@ -64,9 +64,15 @@ #include #ifdef CONFIG_SYSCTL -#define SYNC_INIT 0 /* let the user enable it */ +#define SYNC_INIT 0 /* let the user enable these */ +#define TCP_SYNFIN 0 +#define TCP_BOGUS 0 +#define TCP_ACK 0 #else #define SYNC_INIT 1 +#define TCP_SYNFIN 1 +#define TCP_BOGUS 1 +#define TCP_ACK 1 #endif extern int sysctl_tcp_fin_timeout; @@ -79,6 +85,10 @@ int sysctl_tcp_sack = 1; int sysctl_tcp_syncookies = SYNC_INIT; +int sysctl_tcp_ignore_synfin = TCP_SYNFIN; +int sysctl_tcp_ignore_bogus = TCP_BOGUS; +int sysctl_tcp_ignore_ack = TCP_ACK; + int sysctl_tcp_stdurg; int sysctl_tcp_rfc1337; 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 Wed Feb 23 21:16:02 2000 @@ -67,6 +67,9 @@ extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_syncookies; +extern int sysctl_tcp_ignore_synfin; +extern int sysctl_tcp_ignore_bogus; +extern int sysctl_tcp_ignore_ack; extern int sysctl_ip_dynaddr; extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; @@ -1735,6 +1738,21 @@ len < (th->doff * 4)) goto bad_packet; + if(sysctl_tcp_ignore_synfin) { + if(th->fin && th->syn) + goto tcp_bad_flags; + } + + if(sysctl_tcp_ignore_bogus) { + if(!(th->ack || th->syn || th->rst)) + goto tcp_bad_flags; + } + + if(sysctl_tcp_ignore_ack) { + if(th->fin && th->psh && th->urg) + goto tcp_bad_flags; + } + #ifdef CONFIG_IP_TRANSPARENT_PROXY if (IPCB(skb)->redirport) sk = tcp_v4_proxy_lookup(th->dest, skb->nh.iph->saddr, th->source, @@ -1768,6 +1786,30 @@ __skb_queue_tail(&sk->back_log, skb); return 0; + +#ifdef CONFIG_NET_STEALTH_LOG +tcp_bad_flags: + 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_flags: + goto bad_packet; +#endif no_tcp_socket: tcp_v4_send_reset(skb);