Hello,
I've been struggling from morning with this (22:36 now :/) and can't make it work.
So I have 2.4.30 kernel. I try to apply raw patch, which is needed by TRACE. It fails with 3 rejects.
I ask for this on #netfilter. Guy named xkr47 helps me, and changes the patch (which i've attached).
So now it applies cleanly, I apply these patches:
./runme time CLASSIFY CONNMARK mport nf-log raw TRACE
Then I make kernel (using make-kpkg, if that matters). i get this:
rm -f ipv4.o
ld -m elf_i386 -e stext -r -o ipv4.o utils.o route.o inetpeer.o proc.o protocol.o ip_input.o ip_fragment.o ip_forward.o ip_options.o ip_output.o ip_sockglue.o tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o tcp_diag.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o fib_rules.o ip_nat_dumb.o syncookies.o
make[4]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4'
make[3]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4'
/usr/bin/make -C ipv4/netfilter
make[3]: Entering directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
/usr/bin/make all_targets
make[4]: Entering directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
gcc -D__KERNEL__ -I/usr/src/router/linux-2.4.30/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -pipe -mpreferred-stack-boundary=2 -march=i486 -nostdinc -iwithprefix include -DKBUILD_BASENAME=ip_conntrack_standalone -DEXPORT_SYMTAB -c ip_conntrack_standalone.c
ip_conntrack_standalone.c: In function `ip_conntrack_defrag':
ip_conntrack_standalone.c:208: error: too few arguments to function `ip_ct_gather_frags'
make[4]: *** [ip_conntrack_standalone.o] Error 1
make[4]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
make[3]: *** [first_rule] Error 2
make[3]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
make[2]: *** [_subdir_ipv4/netfilter] Error 2
make[2]: Leaving directory `/usr/src/router/linux-2.4.30/net'
make[1]: *** [_dir_net] Error 2
make[1]: Leaving directory `/usr/src/router/linux-2.4.30'
make: *** [stamp-build] Error 2
22:23 fs:/usr/src/router/linux-2.4.30#
As far I figured it out, these extensions modify ip_conntrack_standalone.c:
22:42 fs:/usr/src/patch-o-matic-ng-20050419# grep ip_conntrack_standalone.c * -R | awk {'print $1'} | cut -d / -f 1 | uniq
CONNMARK
connrate
conntrack-acct
conntrack-event-api
conntrack_locking
conntrack_nonat
ctnetlink
ipsec-03-policy-lookup
netfilter-docbook
nf_conntrack
nfnetlink-ctnetlink-0.13
raw
tcp-window-tracking
tproxy
I tried bare minimum I need, but I guess raw patch makes irreversible changes.
I'd greatly appreciaty any help.
diff -Nru linuxor/include/linux/netfilter_ipv4/ip_conntrack.h linux/include/linux/netfilter_ipv4/ip_conntrack.h --- linuxor/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-20 19:12:36.000000000 +0300 +++ linux/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-20 19:19:22.000000000 +0300 @@ -249,6 +249,9 @@ /* Call me when a conntrack is destroyed. */ extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); +/* Fake conntrack entry for untracked connections */ +extern struct ip_conntrack ip_conntrack_untracked; + /* Returns new sk_buff, or NULL */ struct sk_buff * ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); diff -Nru linuxor/include/linux/netfilter_ipv4/ipt_conntrack.h linux/include/linux/netfilter_ipv4/ipt_conntrack.h --- linuxor/include/linux/netfilter_ipv4/ipt_conntrack.h 2004-02-20 20:49:49.000000000 +0200 +++ linux/include/linux/netfilter_ipv4/ipt_conntrack.h 2005-04-20 19:19:51.000000000 +0300 @@ -10,6 +10,7 @@ #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) /* flags, invflags: */ #define IPT_CONNTRACK_STATE 0x01 diff -Nru linuxor/include/linux/netfilter_ipv4/ipt_state.h linux/include/linux/netfilter_ipv4/ipt_state.h --- linuxor/include/linux/netfilter_ipv4/ipt_state.h 2000-07-17 18:25:05.000000000 +0300 +++ linux/include/linux/netfilter_ipv4/ipt_state.h 2005-04-20 19:19:51.000000000 +0300 @@ -4,6 +4,8 @@ #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) #define IPT_STATE_INVALID (1 << 0) +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) + struct ipt_state_info { unsigned int statemask; diff -Nru linuxor/include/linux/netfilter_ipv4.h linux/include/linux/netfilter_ipv4.h --- linuxor/include/linux/netfilter_ipv4.h 2004-02-20 20:48:03.000000000 +0200 +++ linux/include/linux/netfilter_ipv4.h 2005-04-20 19:19:51.000000000 +0300 @@ -51,6 +51,8 @@ enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, + NF_IP_PRI_CONNTRACK_DEFRAG = -400, + NF_IP_PRI_RAW = -300, NF_IP_PRI_CONNTRACK = -200, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, diff -Nru linuxor/net/ipv4/netfilter/ip_conntrack_core.c linux/net/ipv4/netfilter/ip_conntrack_core.c --- linuxor/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-20 19:12:36.000000000 +0300 +++ linux/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-20 19:17:24.000000000 +0300 @@ -65,6 +65,7 @@ struct list_head *ip_conntrack_hash; static kmem_cache_t *ip_conntrack_cachep; static LIST_HEAD(unconfirmed); +struct ip_conntrack ip_conntrack_untracked; extern struct ip_conntrack_protocol ip_conntrack_generic_protocol; @@ -823,6 +824,15 @@ int set_reply; int ret; + /* Never happen */ + if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) { + if (net_ratelimit()) { + printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n", + (*pskb)->nh.iph->protocol, hooknum); + } + return NF_DROP; + } + /* FIXME: Do this right please. --RR */ (*pskb)->nfcache |= NFC_UNKNOWN; @@ -841,21 +851,10 @@ } #endif - /* Previously seen (loopback)? Ignore. Do this before - fragment check. */ + /* Previously seen (loopback or untracked)? Ignore. */ if ((*pskb)->nfct) return NF_ACCEPT; - /* Gather fragments. */ - if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { - *pskb = ip_ct_gather_frags(*pskb, - hooknum == NF_IP_PRE_ROUTING ? - IP_DEFRAG_CONNTRACK_IN : - IP_DEFRAG_CONNTRACK_OUT); - if (!*pskb) - return NF_STOLEN; - } - proto = ip_ct_find_proto((*pskb)->nh.iph->protocol); /* It may be an icmp error... */ @@ -1459,6 +1458,18 @@ /* For use by ipt_REJECT */ ip_ct_attach = ip_conntrack_attach; + + /* Set up fake conntrack: + - to never be deleted, not in any hashes */ + atomic_set(&ip_conntrack_untracked.ct_general.use, 1); + /* - and look it like as a confirmed connection */ + set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status); + /* - and prepare the ctinfo field for REJECT/NAT. */ + ip_conntrack_untracked.infos[IP_CT_NEW].master = + ip_conntrack_untracked.infos[IP_CT_RELATED].master = + ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master = + &ip_conntrack_untracked.ct_general; + return ret; err_free_hash: diff -Nru linuxor/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c --- linuxor/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-04-20 19:12:36.000000000 +0300 +++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-04-20 19:19:51.000000000 +0300 @@ -189,6 +189,26 @@ return ip_conntrack_confirm(*pskb); } +static unsigned int ip_conntrack_defrag(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* Previously seen (loopback)? Ignore. Do this before + fragment check. */ + if ((*pskb)->nfct) + return NF_ACCEPT; + + /* Gather fragments. */ + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { + *pskb = ip_ct_gather_frags(*pskb); + if (!*pskb) + return NF_STOLEN; + } + return NF_ACCEPT; +} + static unsigned int ip_refrag(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, @@ -230,9 +250,15 @@ /* Connection tracking may drop packets, but never alters them, so make it the first hook. */ +static struct nf_hook_ops ip_conntrack_defrag_ops += { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_PRE_ROUTING, + NF_IP_PRI_CONNTRACK_DEFRAG }; static struct nf_hook_ops ip_conntrack_in_ops = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_CONNTRACK }; +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops += { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_LOCAL_OUT, + NF_IP_PRI_CONNTRACK_DEFRAG }; static struct nf_hook_ops ip_conntrack_local_out_ops = { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_CONNTRACK }; @@ -353,10 +379,20 @@ if (!proc) goto cleanup_init; proc->owner = THIS_MODULE; + ret = nf_register_hook(&ip_conntrack_defrag_ops); + if (ret < 0) { + printk("ip_conntrack: can't register pre-routing defrag hook.\n"); + goto cleanup_proc; + } + ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops); + if (ret < 0) { + printk("ip_conntrack: can't register local_out defrag hook.\n"); + goto cleanup_defragops; + } ret = nf_register_hook(&ip_conntrack_in_ops); if (ret < 0) { printk("ip_conntrack: can't register pre-routing hook.\n"); - goto cleanup_proc; + goto cleanup_defraglocalops; } ret = nf_register_hook(&ip_conntrack_local_out_ops); if (ret < 0) { @@ -394,6 +430,10 @@ nf_unregister_hook(&ip_conntrack_local_out_ops); cleanup_inops: nf_unregister_hook(&ip_conntrack_in_ops); + cleanup_defraglocalops: + nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); + cleanup_defragops: + nf_unregister_hook(&ip_conntrack_defrag_ops); cleanup_proc: proc_net_remove("ip_conntrack"); cleanup_init: @@ -483,5 +523,6 @@ EXPORT_SYMBOL(ip_conntrack_expect_list); EXPORT_SYMBOL(ip_conntrack_lock); EXPORT_SYMBOL(ip_conntrack_hash); +EXPORT_SYMBOL(ip_conntrack_untracked); EXPORT_SYMBOL_GPL(ip_conntrack_find_get); EXPORT_SYMBOL_GPL(ip_conntrack_put); diff -Nru linuxor/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c --- linuxor/net/ipv4/netfilter/ip_nat_core.c 2005-04-20 19:12:36.000000000 +0300 +++ linux/net/ipv4/netfilter/ip_nat_core.c 2005-04-20 19:19:51.000000000 +0300 @@ -1023,6 +1023,10 @@ /* FIXME: Man, this is a hack. <SIGH> */ IP_NF_ASSERT(ip_conntrack_destroyed == NULL); ip_conntrack_destroyed = &ip_nat_cleanup_conntrack; + + /* Initialize fake conntrack so that NAT will skip it */ + ip_conntrack_untracked.nat.info.initialized |= + (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST); return 0; } diff -Nru linuxor/net/ipv4/netfilter/ipt_conntrack.c linux/net/ipv4/netfilter/ipt_conntrack.c --- linuxor/net/ipv4/netfilter/ipt_conntrack.c 2004-02-20 20:52:45.000000000 +0200 +++ linux/net/ipv4/netfilter/ipt_conntrack.c 2005-04-20 19:19:51.000000000 +0300 @@ -27,11 +27,13 @@ #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) - if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); - else - statebit = IPT_CONNTRACK_STATE_INVALID; - + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW]) + statebit = IPT_CONNTRACK_STATE_UNTRACKED; + else if (ct) + statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); + else + statebit = IPT_CONNTRACK_STATE_INVALID; + if(sinfo->flags & IPT_CONNTRACK_STATE) { if (ct) { if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != diff -Nru linuxor/net/ipv4/netfilter/ipt_state.c linux/net/ipv4/netfilter/ipt_state.c --- linuxor/net/ipv4/netfilter/ipt_state.c 2004-02-20 20:52:45.000000000 +0200 +++ linux/net/ipv4/netfilter/ipt_state.c 2005-04-20 19:19:51.000000000 +0300 @@ -21,7 +21,9 @@ enum ip_conntrack_info ctinfo; unsigned int statebit; - if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW]) + statebit = IPT_STATE_UNTRACKED; + else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) statebit = IPT_STATE_INVALID; else statebit = IPT_STATE_BIT(ctinfo);