diff -urP linux/Documentation/Configure.help linux/Documentation/Configure.help --- linux/Documentation/Configure.help Mon Sep 4 13:39:15 2000 +++ linux/Documentation/Configure.help Tue Sep 5 10:40:45 2000 @@ -1225,6 +1225,32 @@ If unsure, say Y. +IP: TCP stack options +CONFIG_NET_STEALTH + If you say Y here, note that these options are now enabled by + default; you can disable them by executing the commands + + echo 0 >/proc/sys/net/ipv4/tcp_ignore_ack + echo 0 >/proc/sys/net/ipv4/tcp_ignore_bogus + echo 0 >/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. Due to the nightmare of adding + sysctl to a module, all module based sysctl options are in + /proc/net instead of /proc/sys/net/ipv4 for now. + + 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. + + note, if you said M to TCP stack options, these will be set Y by + default. + 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 Tue Sep 5 10:40:49 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 Tue Sep 5 10:40:49 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 May 3 20:16:30 2000 +++ linux/arch/i386/defconfig Tue Sep 5 10:40:49 2000 @@ -119,6 +119,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 Tue Sep 5 10:40:49 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 Tue Sep 5 10:40:49 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 Wed May 3 20:16:32 2000 +++ linux/arch/sparc/defconfig Tue Sep 5 10:40:49 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 Mon Sep 4 13:39:16 2000 +++ linux/arch/sparc64/defconfig Tue Sep 5 10:40:49 2000 @@ -145,6 +145,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 Wed Jun 7 17:26:44 2000 +++ linux/include/linux/sysctl.h Tue Sep 5 10:44:18 2000 @@ -228,7 +228,11 @@ NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64, NET_IPV4_IGMP_MAX_MEMBERSHIPS=65, NET_IPV4_ALWAYS_DEFRAG=67, - NET_IPV4_IP_MASQ_UDP_DLOOSE=68 + NET_IPV4_IP_MASQ_UDP_DLOOSE=68, + NET_TCP_STACK_SYNFIN=69, + NET_TCP_STACK_BOGUS=70, + NET_TCP_STACK_ACK=71 + }; enum { diff -urP linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- linux/net/ipv4/Config.in Wed Jun 7 17:26:44 2000 +++ linux/net/ipv4/Config.in Tue Sep 5 10:45:02 2000 @@ -74,6 +74,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 Tue Sep 5 10:45:02 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 Tue Sep 5 10:46:29 2000 @@ -0,0 +1,264 @@ +/* Stealth module by Derek Callaway -- S@IRC + * Original patch by Sean Trifero -- solar@IRC + * $Id: stealth.c,v 1.3 2000/03/22 15:04:44 super Exp $ + */ + +#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) + +/* kernel space variables */ +static char kmsg[3][3] = { "1\n\0", "1\n\0", "1\n\0" }; +static char *tcp_ignore_ack = kmsg[0]; +static char *tcp_ignore_bogus = kmsg[1]; +static char *tcp_ignore_synfin = kmsg[2]; + +/* structures from linux/net/ipv4/ip_fw.c */ + +/* 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); + /* Check for those nasty unused bit fields. */ + if ((*tcp_ignore_bogus != '0') && (tcp->res1 || tcp->res2)) + { + /* I know goto statement should be avoided but I + * seriously doubt that this will evolve into + * spaghetti code. Furthermore, these jumps are + * extremely localized. */ + goto tcp_bad_flags; + } + switch (tcp->fin) + { + case 0: + goto done; + default: + if (((*tcp_ignore_synfin != '0') && (tcp->syn)) + || ((*tcp_ignore_ack != '0') && (tcp->psh) && (tcp->urg))) + { + goto tcp_bad_flags; + } + } + if ((*tcp_ignore_bogus != '0') && (!(tcp->ack || tcp->syn || tcp->rst))) + { + goto tcp_bad_flags; + } + goto done; +tcp_bad_flags: +#ifdef CONFIG_TCPIP_STACK_LOG + 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%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->res1 ? '1' : '.', skb->h.th->res2 ? '2' : '.', + 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' : '.'); +} +#endif +/* FW_BLOCK acts like ipchains -j DENY */ +return (FW_BLOCK); +done: +/* FW_SKIP allows the next chain to evaluate the traffic. */ +return (FW_SKIP); +} + +static ssize_t +module_output (struct file *file, char *buf, size_t len, loff_t * offset) +{ + static unsigned short done = 0; + unsigned short x = 0; + /* user land storage */ + char umsg[2] = { 0 }; + switch (file->f_dentry->d_name.name[11]) + { + case 'a': + x = 0; + break; + case 'b': + x = 1; + break; + case 's': + x = 2; + } + if (done) + return (done = 0); + umsg[0] = kmsg[x][0], umsg[1] = '\n'; + put_user (umsg[0], buf); + put_user (umsg[1], buf + 1); + put_user (umsg[2], buf + 2); + return (done = 2); +} + +static ssize_t +module_input (struct file *file, const char *buf, size_t length, + loff_t * offset) +{ + unsigned short x = 0; + switch (file->f_dentry->d_name.name[11]) + { + case 'a': + x = 0; + break; + case 'b': + x = 1; + break; + case 's': + x = 2; + } + get_user (kmsg[x][0], buf); + kmsg[x][1] = 0; + return (2); +} + +static int +module_permission (struct inode *inode, int op) +{ + if (op == 4 || (op == 2 && current->euid == 0)) + return (0); + return (-EACCES); +} + +int +module_open (struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + return (0); +} + +int +module_close (struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return (0); +} + +/* */ + +static struct file_operations fops = + { NULL, module_output, module_input, NULL, NULL, NULL, NULL, module_open, + NULL, module_close }; +static struct inode_operations iops = + { &fops, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, module_permission }; + +/* */ + +static struct proc_dir_entry bogus = + { 0, 16, "tcp_ignore_bogus", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 0, &iops, + NULL }; +static struct proc_dir_entry synfin = + { 0, 17, "tcp_ignore_synfin", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 0, + &iops, NULL }; +static struct proc_dir_entry ack = + { 0, 14, "tcp_ignore_ack", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 0, &iops, + NULL }; + +int +init_module (void) +{ + proc_net_register (&bogus); + proc_net_register (&synfin); + proc_net_register (&ack); + register_firewall (PF_INET, &ipfw_ops); + return (0); +} + +void +cleanup_module (void) +{ + proc_net_unregister (bogus.low_ino); + proc_net_unregister (synfin.low_ino); + proc_net_unregister (ack.low_ino); + unregister_firewall (PF_INET, &ipfw_ops); +} diff -urP linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- linux/net/ipv4/sysctl_net_ipv4.c Wed Jun 7 17:26:44 2000 +++ linux/net/ipv4/sysctl_net_ipv4.c Tue Sep 5 10:55:08 2000 @@ -64,6 +64,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; @@ -175,6 +178,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 Mon Sep 4 13:39:29 2000 +++ linux/net/ipv4/tcp_input.c Tue Sep 5 10:50:03 2000 @@ -65,11 +65,21 @@ #include #ifdef CONFIG_SYSCTL -#define SYNC_INIT 0 /* let the user enable it */ +#define SYNC_INIT 0 /* let the user enable this */ #else #define SYNC_INIT 1 #endif +#ifdef CONFIG_NET_STEALTH +#define TCP_SYNFIN 1 +#define TCP_BOGUS 1 +#define TCP_ACK 1 +#else +#define TCP_SYNFIN 0 +#define TCP_BOGUS 0 +#define TCP_ACK 0 +#endif + extern int sysctl_tcp_fin_timeout; /* These are on by default so the code paths get tested. @@ -80,6 +90,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 Mon Sep 4 13:39:29 2000 +++ linux/net/ipv4/tcp_ipv4.c Tue Sep 5 10:58:16 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; @@ -1745,6 +1748,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) || th->res1 || th->res2) + 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, @@ -1778,6 +1796,32 @@ __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%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->res1 ? '1' : '.', + th->res2 ? '2' : '.', + 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);