免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3527 | 回复: 4
打印 上一主题 下一主题

improve netfilter against DOS [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-10 20:36 |只看该作者 |倒序浏览
though only for the case of syn flood,
maybe the first time of cookie implementation in netfilter,
since iam lazy and netfilter is nice.

  1. diff -upr linux-2.6.17.8/include/linux/netfilter/nf_conntrack_tcp.h msyn-linux-2.6.17.8/include/linux/netfilter/nf_conntrack_tcp.h
  2. --- linux-2.6.17.8/include/linux/netfilter/nf_conntrack_tcp.h        2006-08-07 12:18:54.000000000 +0800
  3. +++ msyn-linux-2.6.17.8/include/linux/netfilter/nf_conntrack_tcp.h        2007-04-09 15:06:47.000000000 +0800
  4. @@ -36,6 +36,7 @@ struct ip_ct_tcp_state {
  5.         u_int8_t        td_scale;        /* window scale factor */
  6.         u_int8_t        loose;                /* used when connection picked up from the middle */
  7.         u_int8_t        flags;                /* per direction options */
  8. +        u_int8_t        dummy;
  9. };

  10. struct ip_ct_tcp
  11. @@ -49,6 +50,8 @@ struct ip_ct_tcp
  12.         u_int32_t        last_seq;        /* Last sequence number seen in dir */
  13.         u_int32_t        last_ack;        /* Last sequence number seen in opposite dir */
  14.         u_int32_t        last_end;        /* Last seq + len */
  15. +        u_int32_t        aseq;
  16. +        u_int32_t        pseq;
  17. };

  18. #endif /* __KERNEL__ */
  19. diff -upr linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack.h msyn-linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack.h
  20. --- linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack.h        2006-08-07 12:18:54.000000000 +0800
  21. +++ msyn-linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack.h        2007-04-29 15:23:07.000000000 +0800
  22. @@ -81,6 +81,10 @@ struct ip_conntrack

  23.         /* Have we seen traffic both ways yet? (bitset) */
  24.         unsigned long status;
  25. +       
  26. +        unsigned long cookie;
  27. +#define IPCT_COOKIE        0x00001000        /* cookie ct */
  28. +#define IPCT_HOCONT        0x00000010        /* half-open-cnt ct */

  29.         /* Timer function; drops refcnt when it goes off. */
  30.         struct timer_list timeout;
  31. @@ -287,6 +291,10 @@ static inline int is_confirmed(struct ip
  32.         return test_bit(IPS_CONFIRMED_BIT, &ct->status);
  33. }

  34. +extern int nr_ho;
  35. +//extern int cfg_nic_ok(struct sk_buff *);
  36. +extern int sysctl_nt_syn_cookie[4];
  37. +
  38. static inline int is_dying(struct ip_conntrack *ct)
  39. {
  40.         return test_bit(IPS_DYING_BIT, &ct->status);
  41. diff -upr linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack_tuple.h msyn-linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
  42. --- linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack_tuple.h        2006-08-07 12:18:54.000000000 +0800
  43. +++ msyn-linux-2.6.17.8/include/linux/netfilter_ipv4/ip_conntrack_tuple.h        2007-04-09 15:09:11.000000000 +0800
  44. @@ -47,7 +47,7 @@ struct ip_conntrack_manip
  45. struct ip_conntrack_tuple
  46. {
  47.         struct ip_conntrack_manip src;
  48. -
  49. +       
  50.         /* These are the parts of the tuple which are fixed. */
  51.         struct {
  52.                 u_int32_t ip;
  53. diff -upr linux-2.6.17.8/include/linux/skbuff.h msyn-linux-2.6.17.8/include/linux/skbuff.h
  54. --- linux-2.6.17.8/include/linux/skbuff.h        2006-08-07 12:18:54.000000000 +0800
  55. +++ msyn-linux-2.6.17.8/include/linux/skbuff.h        2007-04-03 11:51:08.000000000 +0800
  56. @@ -89,6 +89,7 @@ struct net_device;
  57. struct nf_conntrack {
  58.         atomic_t use;
  59.         void (*destroy)(struct nf_conntrack *);
  60. +        unsigned long dummy, cook2;
  61. };

  62. #ifdef CONFIG_BRIDGE_NETFILTER
  63. diff -upr linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_core.c msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_core.c
  64. --- linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_core.c        2006-08-07 12:18:54.000000000 +0800
  65. +++ msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_core.c        2007-04-29 15:23:38.000000000 +0800
  66. @@ -21,6 +21,7 @@
  67. #include <linux/types.h>
  68. #include <linux/icmp.h>
  69. #include <linux/ip.h>
  70. +#include <linux/tcp.h>
  71. #include <linux/netfilter.h>
  72. #include <linux/netfilter_ipv4.h>
  73. #include <linux/module.h>
  74. @@ -69,6 +70,8 @@ struct ip_conntrack_protocol *ip_ct_prot
  75. static LIST_HEAD(helpers);
  76. unsigned int ip_conntrack_htable_size = 0;
  77. int ip_conntrack_max;
  78. +int sysctl_nt_syn_cookie[4] = { 8192, 128, 0, 0 };
  79. +int nr_ho = 0;
  80. struct list_head *ip_conntrack_hash;
  81. static kmem_cache_t *ip_conntrack_cachep __read_mostly;
  82. static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly;
  83. @@ -352,6 +355,13 @@ destroy_conntrack(struct nf_conntrack *n
  84.                 ip_conntrack_put(ct->master);

  85.         DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
  86. +        if (nfct->cook2) {
  87. +                struct sk_buff * tmp =
  88. +                (struct sk_buff *) nfct->cook2;
  89. +                nfct->cook2 = 0;
  90. +                atomic_dec(&(tmp->users));
  91. +                kfree_skb(tmp);
  92. +        }
  93.         ip_conntrack_free(ct);
  94. }

  95. @@ -363,7 +373,13 @@ static void death_by_timeout(unsigned lo
  96.         /* Inside lock so preempt is disabled on module removal path.
  97.          * Otherwise we can get spurious warnings. */
  98.         CONNTRACK_STAT_INC(delete_list);
  99. -        clean_from_lists(ct);
  100. +        clean_from_lists(ct);
  101. +        if ((ct->cookie & IPCT_HOCONT)
  102. +            && (ct->proto.tcp.state == TCP_CONNTRACK_SYN_SENT
  103. +                || ct->proto.tcp.state == TCP_CONNTRACK_SYN_RECV))
  104. +                --nr_ho;
  105. +        if (nr_ho <0)
  106. +                nr_ho = 0;
  107.         write_unlock_bh(&ip_conntrack_lock);
  108.         ip_conntrack_put(ct);
  109. }
  110. @@ -492,6 +508,9 @@ __ip_conntrack_confirm(struct sk_buff **
  111.                 set_bit(IPS_CONFIRMED_BIT, &ct->status);
  112.                 CONNTRACK_STAT_INC(insert);
  113.                 write_unlock_bh(&ip_conntrack_lock);
  114. +                if ((ct->cookie & IPCT_HOCONT)
  115. +                    && ct->proto.tcp.state == TCP_CONNTRACK_SYN_SENT)
  116. +                        ++nr_ho;
  117.                 if (ct->helper)
  118.                         ip_conntrack_event_cache(IPCT_HELPER, *pskb);
  119. #ifdef CONFIG_IP_NF_NAT_NEEDED
  120. @@ -503,8 +522,7 @@ __ip_conntrack_confirm(struct sk_buff **
  121.                                          IPCT_RELATED : IPCT_NEW, *pskb);

  122.                 return NF_ACCEPT;
  123. -        }
  124. -
  125. +        }
  126.         CONNTRACK_STAT_INC(insert_failed);
  127.         write_unlock_bh(&ip_conntrack_lock);

  128. @@ -745,7 +763,192 @@ init_conntrack(struct ip_conntrack_tuple

  129.         return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
  130. }
  131. +static struct sk_buff * make_new_syn(struct sk_buff *);
  132. +static void give_cookie_toc(struct sk_buff *);
  133. +static int skb_is_cookie_ok(struct sk_buff *);
  134. +static u32 make_cookie(struct sk_buff * , int);
  135. +static int skb_is_syn_ack(struct sk_buff * , int);
  136. +
  137. +static struct sk_buff * make_new_syn (struct sk_buff * skbo)
  138. +{
  139. +        struct sk_buff * skb ;
  140. +        struct tcphdr *th, *oth;
  141. +        struct iphdr *iph, *oiph;
  142. +        struct ethhdr *eth, *oeth;
  143. +        unsigned int size = 20 + 28;
  144. +       
  145. +        size += (((skbo->nh.raw - skbo->mac.raw) +15) & ~15);
  146. +        if ((skb = alloc_skb(size, GFP_ATOMIC)) == NULL)
  147. +                return NULL;
  148. +        skb_reserve(skb, size);
  149. +
  150. +        oeth = (struct ethhdr *)skbo->mac.raw;
  151. +        oiph = skbo->nh.iph;
  152. +        oth  = (void *)oiph + (oiph->ihl<<2) ;
  153. +
  154. +        th = (struct tcphdr *) skb_push(skb, 28);
  155. +        memset(th, 0, 28);
  156. +
  157. +        th->source = oth->source;
  158. +        th->dest   = oth->dest;
  159. +
  160. +        th->seq = htonl(ntohl(oth->seq) -1);
  161. +
  162. +        th->syn = 1;
  163. +        th->doff = 28 >> 2;
  164. +        th->window = oth->window ;
  165. +        *(__be32 *)(th + 1) = htonl((2 << 24) | (4 << 16) | 1460);
  166. +        th->check  = csum_tcpudp_magic(oiph->saddr, oiph->daddr,
  167. +                                        skb->len, IPPROTO_TCP,
  168. +                        csum_partial((char *)th, skb->len, 0));       
  169. +
  170. +        skb->nh.iph = iph = (struct iphdr *)skb_push(skb, 20);
  171. +        memset(iph, 0, 20);
  172. +
  173. +        iph->version  = 4;
  174. +        iph->ihl      = 5;
  175. +        iph->ttl      = oiph->ttl;
  176. +        iph->tos      = oiph->tos;
  177. +        iph->protocol = oiph->protocol;
  178. +        iph->id       = oiph->id ;
  179. +
  180. +        iph->daddr    = oiph->daddr;
  181. +        iph->saddr    = oiph->saddr;
  182. +
  183. +        iph->tot_len  = htons(skb->len);
  184. +        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
  185. +
  186. +        size = skbo->nh.raw - skbo->mac.raw;
  187. +        eth = (struct ethhdr *)skb_push(skb, size);
  188. +        skb_pull(skb, size);
  189. +        skb->mac.raw = (void *)eth;
  190. +        memcpy(skb->mac.raw, skbo->mac.raw, size);
  191. +        skb->protocol = skbo->protocol;
  192. +        skb->pkt_type = skbo->pkt_type;
  193. +        skb->dev = skbo->dev;
  194. +        return skb;
  195. +}
  196. +static void give_cookie_toc (struct sk_buff * skbo)
  197. +{
  198. +        struct sk_buff * skb ;
  199. +        struct tcphdr *th, *oth;
  200. +        struct iphdr *iph, *oiph;
  201. +        struct ethhdr *eth, *oeth;
  202. +        unsigned int size = 20 + 28;
  203. +       
  204. +        size += (((skbo->nh.raw - skbo->mac.raw) +15) & ~15);
  205. +        if ((skb = alloc_skb(size, GFP_ATOMIC)) == NULL)
  206. +                return;
  207. +        skb_reserve(skb, size);
  208. +
  209. +        oeth = (struct ethhdr *) skbo->mac.raw;
  210. +        oiph = skbo->nh.iph;
  211. +        oth  = (struct tcphdr *)((char *)oiph + (oiph->ihl<<2));
  212. +
  213. +        skb->h.th = th = (struct tcphdr *) skb_push(skb, 28);
  214. +        memset(th, 0, 28);
  215. +
  216. +        th->source = oth->dest;
  217. +        th->dest   = oth->source;
  218. +       
  219. +        th->ack_seq = htonl(ntohl(oth->seq) + 1);
  220. +        th->seq     = htonl(make_cookie(skbo, 1));
  221. +
  222. +        th->syn = th->ack = 1;
  223. +        th->doff = 28 >> 2;
  224. +
  225. +        th->window = htons(5840);
  226. +        *(__be32 *)(th + 1) = htonl((2 << 24) | (4 << 16) | 1460);
  227. +
  228. +        th->check = csum_tcpudp_magic(oiph->daddr, oiph->saddr,
  229. +                                        skb->len, IPPROTO_TCP,
  230. +                        csum_partial((char *)th, skb->len, 0));       
  231. +
  232. +        skb->nh.iph = iph = (struct iphdr *)skb_push(skb, 20);
  233. +        memset(iph, 0, 20);
  234. +
  235. +        iph->daddr    = oiph->saddr;
  236. +        iph->saddr    = oiph->daddr;
  237. +
  238. +        iph->version  = 4;
  239. +        iph->ihl      = 5;
  240. +        iph->ttl      = 64;
  241. +        iph->tos      = oiph->tos;
  242. +        iph->protocol = oiph->protocol;
  243. +        iph->id       = oiph->id ;
  244. +
  245. +        iph->tot_len  = htons(skb->len);
  246. +        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
  247. +
  248. +        size = skbo->nh.raw - skbo->mac.raw;
  249. +        eth = (struct ethhdr *)skb_push(skb, size);
  250. +        skb->mac.raw = (void *)eth;
  251. +        memcpy(skb->mac.raw, skbo->mac.raw, size);
  252. +        memcpy(eth->h_dest, oeth->h_source, ETH_ALEN);
  253. +        memcpy(eth->h_source, oeth->h_dest, ETH_ALEN);
  254. +
  255. +        skb->protocol = skbo->protocol;
  256. +        skb->dev = (skbo->dev->priv_flags & IFF_EBRIDGE) ?
  257. +                    skbo->nf_bridge->physindev :
  258. +                    skbo->input_dev;
  259. +        dev_queue_xmit(skb);
  260. +}
  261. +static int skb_is_syn_ack (struct sk_buff * skb, int syn)
  262. +{
  263. +        struct iphdr * i = skb->nh.iph;
  264. +        struct tcphdr * t =
  265. +        (struct tcphdr *)((char *)i +(i->ihl<<2));
  266. +
  267. +        if ((syn ? (t->syn == 1 && t->ack == 0) :
  268. +                   (t->syn == 0 && t->ack == 1))
  269. +            && t->fin == 0 && t->rst == 0
  270. +            && skb->len == 4*(i->ihl + t->doff))
  271. +                return 1;
  272. +        return 0;
  273. +}
  274. +static u32 make_cookie (struct sk_buff * skb, int is_syn)
  275. +{
  276. +        /*
  277. +        * code granted by other guys,
  278. +        * though simple and effective,
  279. +        * no need to appreciate.
  280. +        *
  281. +        * and linux has other nicee codes,
  282. +        * isnt it?
  283. +        *
  284. +        *
  285. +        *
  286. +        *
  287. +        *
  288. +        */
  289. +}
  290. +static int skb_is_cookie_ok (struct sk_buff * skb)
  291. +{
  292. +        struct iphdr * i = skb->nh.iph;
  293. +        struct tcphdr * t =
  294. +        (struct tcphdr *)((char *)i +(i->ihl<<2));

  295. +        if (skb/*xxuglyx*/)
  296. +                return 1;
  297. +        return 0;
  298. +}
  299. +static int cfg_nic_ok(struct sk_buff * skb)
  300. +{
  301. +        int j, k;
  302. +       
  303. +        k = sizeof(sysctl_nt_syn_cookie) / sizeof(int);
  304. +        for (j = 2; j < k; j++) {
  305. +                if (sysctl_nt_syn_cookie[j] > 0 &&
  306. +                    sysctl_nt_syn_cookie[j] == (
  307. +#ifdef CONFIG_BRIDGE_NETFILTER
  308. +                    skb->nf_bridge ?
  309. +                    skb->nf_bridge->physindev->ifindex :
  310. +#endif
  311. +                    skb->input_dev->ifindex))
  312. +                        return 1;
  313. +        }
  314. +        return 0;
  315. +}
  316. /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
  317. static inline struct ip_conntrack *
  318. resolve_normal_ct(struct sk_buff *skb,
  319. @@ -758,6 +961,9 @@ resolve_normal_ct(struct sk_buff *skb,
  320.         struct ip_conntrack_tuple_hash *h;
  321.         struct ip_conntrack *ct;

  322. +        static unsigned long cnt_ho, tstamp = 0;
  323. +        unsigned long now;
  324. +
  325.         IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);

  326.         if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
  327. @@ -767,6 +973,48 @@ resolve_normal_ct(struct sk_buff *skb,
  328.         /* look for tuple match */
  329.         h = ip_conntrack_find_get(&tuple, NULL);
  330.         if (!h) {
  331. +#define cfg_anr  sysctl_nt_syn_cookie[0]
  332. +#define cfg_snr  sysctl_nt_syn_cookie[1]
  333. +
  334. +                if (proto->proto == IPPROTO_TCP &&
  335. +                    hooknum == NF_IP_PRE_ROUTING &&
  336. +                    cfg_nic_ok(skb))
  337. +                {
  338. +                        if (cfg_anr < 0 || cfg_snr < 0) {
  339. +        mixi:
  340. +                                h = ERR_PTR(-601);
  341. +                                return (void *)h;
  342. +                        }
  343. +                        tuple.dst.dir = 0;
  344. +                        if (skb_is_syn_ack(skb, 1)) {
  345. +                                int buk = 0;
  346. +                               
  347. +                                now = jiffies ;
  348. +                                cnt_ho += (now - tstamp);
  349. +                                tstamp = now;
  350. +                                if (cnt_ho > HZ * cfg_snr)
  351. +                                        cnt_ho = HZ * cfg_snr;
  352. +                                if (cnt_ho >= HZ) {
  353. +                                        cnt_ho -= HZ ;
  354. +                                        buk = 1;
  355. +                                }
  356. +                                if (nr_ho < cfg_anr && buk) {
  357. +                                        tuple.dst.dir = 4;
  358. +                                        goto nook;
  359. +                                }
  360. +                                h = ERR_PTR(-600);
  361. +                                return (void *)h;
  362. +                        } else if (skb_is_syn_ack(skb, 0) &&
  363. +                                   skb_is_cookie_ok(skb)) {
  364. +                                tuple.dst.dir = 12;
  365. +                                goto nook;
  366. +                        } else
  367. +                                goto mixi;
  368. +                }
  369. +#undef cfg_anr
  370. +#undef cfg_snr
  371. +
  372. +        nook:
  373.                 h = init_conntrack(&tuple, proto, skb);
  374.                 if (!h)
  375.                         return NULL;
  376. @@ -801,7 +1049,24 @@ resolve_normal_ct(struct sk_buff *skb,
  377.         skb->nfctinfo = *ctinfo;
  378.         return ct;
  379. }
  380. -
  381. +static void rechk_skb(struct tcphdr * th,
  382. +                        enum ip_conntrack_dir dir,
  383. +                        u_int32_t aseq, u_int32_t pseq)
  384. +{
  385. +        u32 diffs[2];
  386. +       
  387. +        if (!dir) {
  388. +                diffs[0] = ~(th->ack_seq);
  389. +                th->ack_seq = diffs[1] =
  390. +                        htonl(ntohl(th->ack_seq) - pseq+aseq) ;
  391. +        } else {
  392. +                diffs[0] = ~(th->seq);
  393. +                th->seq = diffs[1] =
  394. +                        htonl(ntohl(th->seq) - aseq+pseq) ;
  395. +        }
  396. +        th->check = csum_fold(csum_partial((char *)diffs,
  397. +                        sizeof(diffs), th->check^0xFFFF));
  398. +}
  399. /* Netfilter hook itself. */
  400. unsigned int ip_conntrack_in(unsigned int hooknum,
  401.                              struct sk_buff **pskb,
  402. @@ -815,6 +1080,16 @@ unsigned int ip_conntrack_in(unsigned in
  403.         int set_reply = 0;
  404.         int ret;

  405. +        u_int8_t old_state = 0;
  406. +        enum ip_conntrack_dir dir;
  407. +        struct iphdr *iph;
  408. +        struct tcphdr *th;
  409. +        unsigned int index;
  410. +
  411. +        int ala = 0;
  412. +        int cry, br;
  413. +        struct sk_buff *new_skb;
  414. +
  415.         /* Previously seen (loopback or untracked)?  Ignore. */
  416.         if ((*pskb)->nfct) {
  417.                 CONNTRACK_STAT_INC(ignore);
  418. @@ -856,21 +1131,103 @@ unsigned int ip_conntrack_in(unsigned in
  419.                 CONNTRACK_STAT_INC(invalid);
  420.                 return -ret;
  421.         }
  422. -
  423. -        if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
  424. +        if (!(ct = resolve_normal_ct(*pskb, proto,
  425. +                        &set_reply, hooknum, &ctinfo))) {
  426.                 /* Not valid part of a connection */
  427.                 CONNTRACK_STAT_INC(invalid);
  428.                 return NF_ACCEPT;
  429.         }
  430. -
  431.         if (IS_ERR(ct)) {
  432.                 /* Too stressed to deal. */
  433.                 CONNTRACK_STAT_INC(drop);
  434. +                if (PTR_ERR(ct) == -600) {
  435. +                        give_cookie_toc(*pskb);
  436. +                }
  437.                 return NF_DROP;
  438.         }
  439. -
  440.         IP_NF_ASSERT((*pskb)->nfct);

  441. +#define        COOK_TCP_SYN_SET        0
  442. +#define        COOK_TCP_SYNACK_SET        1
  443. +#define        COOK_TCP_FIN_SET        2
  444. +#define        COOK_TCP_ACK_SET        3
  445. +#define        COOK_TCP_RST_SET        4
  446. +#define        COOK_TCP_NONE_SET        5
  447. +#define        COOK_TCP_CONNTRACK_NONE                0
  448. +#define        COOK_TCP_CONNTRACK_SYN_SENT        1
  449. +
  450. +        dir = CTINFO2DIR(ctinfo);
  451. +        cry = (proto->proto == IPPROTO_TCP
  452. +                && (ct->cookie & IPCT_COOKIE)) ? 111 : 0;
  453. +        br = (in && (in->priv_flags & IFF_EBRIDGE)) ? 11 : 0;
  454. +        old_state = ct->proto.tcp.state;
  455. +       
  456. +        if (cry) {
  457. +                iph = (*pskb)->nh.iph;
  458. +                th = (struct tcphdr *)(iph->ihl*4 + (char *)iph);
  459. +                if (th->rst) {
  460. +                        index = COOK_TCP_RST_SET;
  461. +                        /* why not smilee? */
  462. +                } else if (th->syn)
  463. +                        index = th->ack ?
  464. +                                COOK_TCP_SYNACK_SET :
  465. +                                COOK_TCP_SYN_SET;
  466. +                else if (th->fin)
  467. +                        index = COOK_TCP_FIN_SET;
  468. +                else if (th->ack)
  469. +                        index = COOK_TCP_ACK_SET;
  470. +                else
  471. +                        index = COOK_TCP_NONE_SET;
  472. +                //old_state = ct->proto.tcp.state;
  473. +                ala = 4+3;
  474. +
  475. +                if (hooknum == NF_IP_LOCAL_OUT &&
  476. +                    dir && !in && out) {
  477. +                        if (index == COOK_TCP_SYNACK_SET &&
  478. +                            old_state == COOK_TCP_CONNTRACK_SYN_SENT)
  479. +                                ala = 3;
  480. +                }
  481. +                if (hooknum == NF_IP_PRE_ROUTING &&
  482. +                    dir && !out && in &&
  483. +                    !cfg_nic_ok(*pskb)) {
  484. +                        if (index == COOK_TCP_SYNACK_SET &&
  485. +                            old_state == COOK_TCP_CONNTRACK_SYN_SENT)
  486. +                                ala = 2;
  487. +                }
  488. +                if (hooknum == NF_IP_PRE_ROUTING &&
  489. +                    !dir && !out && in &&
  490. +                    cfg_nic_ok(*pskb)) {
  491. +                        if (index == COOK_TCP_ACK_SET &&
  492. +                            old_state == COOK_TCP_CONNTRACK_NONE)
  493. +                                ala = 1;
  494. +                }
  495. +        }
  496. +        if (cry && ala == 1) {
  497. +                new_skb = make_new_syn(*pskb);
  498. +                if (!new_skb)
  499. +                        return NF_DROP;
  500. +
  501. +                ct->ct_general.cook2 = (unsigned long) *pskb;
  502. +                atomic_inc(&((*pskb)->users));
  503. +
  504. +                new_skb->nfct = (*pskb)->nfct;
  505. +                (*pskb)->nfct = NULL;
  506. +                new_skb->nfctinfo = (*pskb)->nfctinfo;
  507. +                (*pskb)->nfctinfo = 0;
  508. +                if (br && (*pskb)->nf_bridge) {
  509. +                        new_skb->nf_bridge = (*pskb)->nf_bridge;
  510. +                        nf_bridge_get((*pskb)->nf_bridge);
  511. +                }
  512. +                *pskb = new_skb;
  513. +        } else if (cry && ala > 3 && !dir) {
  514. +                if (!skb_make_writable(pskb, 20+(*pskb)->nh.iph->ihl*4))
  515. +                        return NF_DROP;
  516. +                iph = (*pskb)->nh.iph;
  517. +                th = (struct tcphdr *)((char *)iph + iph->ihl*4);
  518. +                rechk_skb(th, dir,
  519. +                        ct->proto.tcp.aseq, ct->proto.tcp.pseq);
  520. +        }
  521. +       
  522.         ret = proto->packet(ct, *pskb, ctinfo);
  523.         if (ret < 0) {
  524.                 /* Invalid: inverse of the return code tells
  525. @@ -880,11 +1237,69 @@ unsigned int ip_conntrack_in(unsigned in
  526.                 CONNTRACK_STAT_INC(invalid);
  527.                 return -ret;
  528.         }
  529. -
  530.         if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
  531.                 ip_conntrack_event_cache(IPCT_STATUS, *pskb);

  532. +        if (ret == NF_ACCEPT && cry && dir
  533. +                && (ala == 3 || ala == 2)) {
  534. +                if (ala == 3 && ct->ct_general.cook2) {
  535. +                        new_skb = (struct sk_buff *)ct->ct_general.cook2;
  536. +
  537. +                        ct->ct_general.cook2 = 0;
  538. +                        atomic_dec(&(new_skb->users));
  539. +                        kfree_skb(new_skb);
  540. +                        return NF_DROP;
  541. +                } else if (ala == 2 && ct->ct_general.cook2) {
  542. +                        int r;
  543. +                       
  544. +                        new_skb = (struct sk_buff *)ct->ct_general.cook2;
  545. +                        ct->ct_general.cook2 = 0;
  546. +                        atomic_dec(&(new_skb->users));
  547. +                        if (!skb_make_writable(&new_skb,
  548. +                                20+new_skb->nh.iph->ihl*4)) {
  549. +                                kfree(new_skb);
  550. +                                return NF_DROP;
  551. +                        }
  552. +                        new_skb->nfct = (*pskb)->nfct;
  553. +                        (*pskb)->nfct = NULL;
  554. +                        new_skb->nfctinfo = (*pskb)->nfctinfo - IP_CT_DIR_REPLY;
  555. +                        (*pskb)->nfctinfo = 0;
  556. +
  557. +                        kfree_skb(*pskb);
  558. +                        *pskb = new_skb;
  559. +                        iph = (*pskb)->nh.iph;
  560. +                        th = (struct tcphdr *)((char *)iph + iph->ihl*4);
  561. +
  562. +                        rechk_skb(th, dir,
  563. +                                ct->proto.tcp.aseq, ct->proto.tcp.pseq);
  564. +
  565. +                        r = proto->packet(ct, *pskb, (*pskb)->nfctinfo);
  566. +                        if (r < 0) {
  567. +                                nf_conntrack_put((*pskb)->nfct);
  568. +                                (*pskb)->nfct = NULL;
  569. +                                CONNTRACK_STAT_INC(invalid);
  570. +                                return -r ;
  571. +                        }
  572. +                        return r;
  573. +                }
  574. +        }
  575. +        if (ret == NF_ACCEPT && cry && ala > 3 && dir) {
  576. +                if (!skb_make_writable(pskb, 20+(*pskb)->nh.iph->ihl*4))
  577. +                        return NF_DROP;
  578. +                iph = (*pskb)->nh.iph;
  579. +                th = (void *)iph + iph->ihl*4;
  580. +                rechk_skb(th, dir,
  581. +                        ct->proto.tcp.aseq, ct->proto.tcp.pseq);
  582. +        }
  583.         return ret;
  584. +#undef COOK_TCP_SYN_SET
  585. +#undef COOK_TCP_SYNACK_SET
  586. +#undef COOK_TCP_FIN_SET
  587. +#undef COOK_TCP_ACK_SET
  588. +#undef COOK_TCP_RST_SET
  589. +#undef COOK_TCP_NONE_SET
  590. +#undef COOK_TCP_CONNTRACK_NONE
  591. +#undef COOK_TCP_CONNTRACK_SYN_SENT
  592. }

  593. int invert_tuplepr(struct ip_conntrack_tuple *inverse,
复制代码

[ 本帖最后由 sisi8408 于 2008-2-24 18:00 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-08-10 20:39 |只看该作者
sorry, too long to put into one slot

  1. diff -upr linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
  2. --- linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c        2006-08-07 12:18:54.000000000 +0800
  3. +++ msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c        2007-04-29 11:29:47.000000000 +0800
  4. @@ -613,6 +613,8 @@ static int tcp_in_window(struct ip_ct_tc
  5.                         sender->td_maxend = end;
  6.                         sender->td_maxwin = (win == 0 ? 1 : win);

  7. +                        if (state->pseq)
  8. +                                state->aseq = seq;
  9.                         tcp_options(skb, iph, tcph, sender);
  10.                         /*
  11.                          * RFC 1323:
  12. @@ -947,12 +949,12 @@ static int tcp_packet(struct ip_conntrac
  13.                 conntrack->proto.tcp.last_seq = ntohl(th->seq);
  14.                 conntrack->proto.tcp.last_end =
  15.                     segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
  16. -               
  17.                 write_unlock_bh(&tcp_lock);
  18.                 if (LOG_INVALID(IPPROTO_TCP))
  19.                         nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
  20.                                   "ip_ct_tcp: invalid packet ignored ");
  21.                 return NF_ACCEPT;
  22. +       
  23.         case TCP_CONNTRACK_MAX:
  24.                 /* Invalid packet */
  25.                 DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
  26. @@ -963,6 +965,7 @@ static int tcp_packet(struct ip_conntrac
  27.                         nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
  28.                                   "ip_ct_tcp: invalid state ");
  29.                 return -NF_ACCEPT;
  30. +       
  31.         case TCP_CONNTRACK_SYN_SENT:
  32.                 if (old_state < TCP_CONNTRACK_TIME_WAIT)
  33.                         break;
  34. @@ -984,6 +987,7 @@ static int tcp_packet(struct ip_conntrac
  35.                                               NULL, "ip_ct_tcp: invalid SYN");
  36.                         return -NF_ACCEPT;
  37.                 }
  38. +       
  39.         case TCP_CONNTRACK_CLOSE:
  40.                 if (index == TCP_RST_SET
  41.                     && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
  42. @@ -1024,12 +1028,13 @@ static int tcp_packet(struct ip_conntrac
  43.                 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
  44.                 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
  45.                 old_state, new_state);
  46. -
  47.         conntrack->proto.tcp.state = new_state;
  48. +
  49.         if (old_state != new_state
  50.             && (new_state == TCP_CONNTRACK_FIN_WAIT
  51.                     || new_state == TCP_CONNTRACK_CLOSE))
  52. -                conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
  53. +                conntrack->proto.tcp.seen[dir].flags |=
  54. +                        IP_CT_TCP_FLAG_CLOSE_INIT;
  55.         timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
  56.                   && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
  57.                   ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
  58. @@ -1045,9 +1050,13 @@ static int tcp_packet(struct ip_conntrac
  59.                    problem case, so we can delete the conntrack
  60.                    immediately.  --RR */
  61.                 if (th->rst) {
  62. -                        if (del_timer(&conntrack->timeout))
  63. +                        if (del_timer(&conntrack->timeout)) {
  64.                                 conntrack->timeout.function((unsigned long)
  65.                                                             conntrack);
  66. +                        }
  67. +                        if (conntrack->cookie & IPCT_HOCONT)
  68. +                           //(old_state == 1 || old_state ==2)
  69. +                                --nr_ho;
  70.                         return NF_ACCEPT;
  71.                 }
  72.         } else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
  73. @@ -1057,11 +1066,18 @@ static int tcp_packet(struct ip_conntrac
  74.                 /* Set ASSURED if we see see valid ack in ESTABLISHED
  75.                    after SYN_RECV or a valid answer for a picked up
  76.                    connection. */
  77. +                if ((conntrack->cookie & IPCT_HOCONT)
  78. +                        && old_state != new_state)
  79. +                        --nr_ho;
  80.                 set_bit(IPS_ASSURED_BIT, &conntrack->status);
  81.                 ip_conntrack_event_cache(IPCT_STATUS, skb);
  82.         }
  83.         ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout);
  84. -
  85. +        if ((conntrack->cookie & IPCT_HOCONT) &&
  86. +            index == TCP_RST_SET &&
  87. +            new_state == TCP_CONNTRACK_CLOSE &&
  88. +            (old_state == 1 || old_state ==2))
  89. +                --nr_ho;
  90.         return NF_ACCEPT;
  91. }
  92.   
  93. @@ -1072,6 +1088,8 @@ static int tcp_new(struct ip_conntrack *
  94.         enum tcp_conntrack new_state;
  95.         struct iphdr *iph = skb->nh.iph;
  96.         struct tcphdr *th, _tcph;
  97. +        unsigned int index;
  98. +        int ala = 0;
  99. #ifdef DEBUGP_VARS
  100.         struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
  101.         struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
  102. @@ -1082,9 +1100,20 @@ static int tcp_new(struct ip_conntrack *
  103.         BUG_ON(th == NULL);
  104.        
  105.         /* Don't need lock here: this conntrack not in circulation yet */
  106. -        new_state
  107. -                = tcp_conntracks[0][get_conntrack_index(th)]
  108. -                [TCP_CONNTRACK_NONE];
  109. +        index = get_conntrack_index(th);
  110. +        if (conntrack->tuplehash[0].tuple.dst.dir == 4)
  111. +                conntrack->cookie |= IPCT_HOCONT;
  112. +        if (conntrack->tuplehash[0].tuple.dst.dir == 12
  113. +            && index == TCP_ACK_SET) {
  114. +                conntrack->proto.tcp.aseq =
  115. +                conntrack->proto.tcp.pseq = 0;
  116. +                ala = 11;
  117. +                conntrack->cookie |= IPCT_COOKIE | IPCT_HOCONT ;
  118. +                index = TCP_SYN_SET;
  119. +        }
  120. +        conntrack->tuplehash[0].tuple.dst.dir = 0;
  121. +        conntrack->tuplehash[1].tuple.dst.dir = 1;
  122. +        new_state = tcp_conntracks[0][index][TCP_CONNTRACK_NONE];

  123.         /* Invalid: delete conntrack */
  124.         if (new_state >= TCP_CONNTRACK_MAX) {
  125. @@ -1107,6 +1136,8 @@ static int tcp_new(struct ip_conntrack *
  126.                 conntrack->proto.tcp.seen[1].flags = 0;
  127.                 conntrack->proto.tcp.seen[0].loose =
  128.                 conntrack->proto.tcp.seen[1].loose = 0;
  129. +                if (ala)
  130. +                conntrack->proto.tcp.pseq = ntohl(th->ack_seq)-1;
  131.         } else if (ip_ct_tcp_loose == 0) {
  132.                 /* Don't try to pick up connections. */
  133.                 return 0;
  134. diff -upr linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_standalone.c msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_standalone.c
  135. --- linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_standalone.c        2006-08-07 12:18:54.000000000 +0800
  136. +++ msyn-linux-2.6.17.8/net/ipv4/netfilter/ip_conntrack_standalone.c        2007-04-11 11:33:39.000000000 +0800
  137. @@ -151,9 +151,10 @@ static int ct_seq_show(struct seq_file *
  138.         proto = __ip_conntrack_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
  139.         IP_NF_ASSERT(proto);

  140. -        if (seq_printf(s, "%-8s %u %ld ",
  141. +        if (seq_printf(s, "%-8s 0x%08x %ld ",
  142.                       proto->name,
  143. -                      conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
  144. +                      //conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
  145. +                      conntrack->cookie,
  146.                       timer_pending(&conntrack->timeout)
  147.                       ? (long)(conntrack->timeout.expires - jiffies)/HZ
  148.                       : 0) != 0)
  149. @@ -584,6 +585,22 @@ static ctl_table ip_ct_sysctl_table[] =
  150.                 .proc_handler        = &proc_dointvec,
  151.         },
  152.         {
  153. +                .ctl_name        = 30,
  154. +                .procname        = "cfg_cookie",
  155. +                .data                = &sysctl_nt_syn_cookie,
  156. +                .maxlen                = sizeof(sysctl_nt_syn_cookie),
  157. +                .mode                = 0644,
  158. +                .proc_handler        = &proc_dointvec,
  159. +        },
  160. +        {
  161. +                .ctl_name        = 31,
  162. +                .procname        = "nr_ho",
  163. +                .data                = &nr_ho,
  164. +                .maxlen                = sizeof(int),
  165. +                .mode                = 0444,
  166. +                .proc_handler        = &proc_dointvec,
  167. +        },
  168. +        {
  169.                 .ctl_name        = NET_IPV4_NF_CONNTRACK_BUCKETS,
  170.                 .procname        = "ip_conntrack_buckets",
  171.                 .data                = &ip_conntrack_htable_size,
复制代码

论坛徽章:
0
3 [报告]
发表于 2007-08-10 21:03 |只看该作者
期望在大于200Kpps flood中仅有一个有效连接,
能够保证连接时间小于3s

论坛徽章:
0
4 [报告]
发表于 2007-08-12 15:42 |只看该作者
Encountering udp/icmp/legal frags,
there is no outstanding and concrete evidence to say,
cookie is effective, at least in the case of netfilter.

But EWMA and/or FLC seem to be new horizon.

论坛徽章:
0
5 [报告]
发表于 2008-02-24 17:54 |只看该作者
it may play game again in the case of FLC
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP