免费注册 查看新帖 |

Chinaunix

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

[网络管理] 关于Linux下每IP的NAT Session数限制的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-22 17:21 |只看该作者 |倒序浏览
请教坛子里的高人前辈,小弟现有一需求如下:

用linux做网关,iptables 伪装。现在想限制每台计算机的nat session数量,无论是tcp还是udp协议。TCP比较简单,已经有现成的connlimit模块,而对于udp则没有相关的模块。我知道udp没有session,但是在conntrack表中是有nat session存在的,我现在就想限制每个ip 在conntrack表中的session数,无论tcp还是udp,不知各位有没有相关经验可以赐教?小弟在此先谢过了!

论坛徽章:
0
2 [报告]
发表于 2007-10-22 22:56 |只看该作者
我写了一个脚本,定期去统计每个IP net session 的数目,当某个IP超过我预定的数目就将其列入黑名单,禁止30分钟内使用网络。

论坛徽章:
0
3 [报告]
发表于 2007-10-23 10:07 |只看该作者
谢谢这位老兄,你的方法可以实现这个目标,但是比较被动,我希望的结果是和connlimit限制tcp一样的效果来限制udp,我google了一下,2003年有人根据iplimit改写了一个udplimit,但是netfilter团队没有接受他的补丁,因此也就没有了下文,下边是原文,不知哪位高人能改写一下以便能用在2.6内核上?

Hi again,

Jan Du Caju wrote:
> >  Ing. CIP Alejandro Celi Mariategui wrote:
> >
> >  (Sorry, but my english is very bad)
> >  Hi,
> >  I compile with p-o-m the server kernel with IPLIMIT Patch by Gerd
> >  Knorr
> >  [1]<kraxel@xxxxxxxxxxx>
> >  It work fine, i can limit ex: max 10 TCP connections on the server,
> >  but i want to limit the UDP connections to 10 (max).
> >  How I can do it?

>    This week I made a updlimit patch (shameless copy of iplimit ;-)
>    I will post it this afternoon/evening when I have more time (and
>    a cross post to the netfilter-devel list. Maybe they like it)

In attachment you will find:
udplimit.patch
udplimit.patch.config.in
udplimit.patch.configure.help
udplimit.patch.help
udplimit.patch.makefile

put those under <patch-o-matic>/base/ directory

in the <patch-o-matic> directory you run: ./runme base
(don't forget to select udplimit ;-)

recompile your kernel (with Connections/UDP limit match support
CONFIG_IP_NF_MATCH_UDPLIMIT ;-)

Place the other file attachment (libipt_udplimit.c) in the directory
<iptables>/extensions/

in this directory you will also find the file Makefile where you add
udplimit just after iplimit

recompile iptables

Hope this helps (it works for me :-)

Greetz,
Jan.
--------------------------------------------- KULeuvenNet -----

  1. diff -urN -x *~ -x [Cc]onfig.* -x Makefile
  2. vanilla-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c
  3. linux-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c
  4. --- vanilla-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c       Fri Feb 21
  5. 17:20:55 2003
  6. +++ linux-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c Fri Feb 21 17:17:38 2003
  7. @@ -0,0 +1,215 @@
  8. +/*
  9. + * netfilter module to limit the number of parallel udp
  10. + * connections per IP address.
  11. + * Jan Du Caju <Jan.DuCaju@xxxxxxxxxxxx>
  12. + *
  13. + * based on ...
  14. + * iplimit (in fact a shameless copy ;-)
  15. + *   (c) 2000 Gerd Knorr <kraxel@xxxxxxxxxxx>
  16. + *   Nov 2002: Martin Bene <martin.bene@xxxxxxxxxxxxx>:
  17. + *             only ignore TIME_WAIT or gone connections
  18. + *
  19. + *
  20. + * Kernel module to match connection tracking information.
  21. + * GPL (C) 1999  Rusty Russell (rusty@xxxxxxxxxxxxxxx).
  22. + */
  23. +#include <linux/module.h>
  24. +#include <linux/skbuff.h>
  25. +#include <linux/list.h>
  26. +#include <linux/netfilter_ipv4/ip_conntrack.h>
  27. +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
  28. +#include <linux/netfilter_ipv4/ip_tables.h>
  29. +#include <linux/netfilter_ipv4/ipt_iplimit.h>
  30. +
  31. +#define DEBUG 0
  32. +
  33. +MODULE_LICENSE("GPL");
  34. +
  35. +/* we'll save the tuples of all connections we care about */
  36. +struct ipt_iplimit_conn
  37. +{
  38. +        struct list_head list;
  39. +       struct ip_conntrack_tuple tuple;
  40. +};
  41. +
  42. +struct ipt_iplimit_data {
  43. +       spinlock_t lock;
  44. +       struct list_head iphash[256];
  45. +};
  46. +
  47. +static int ipt_iphash(u_int32_t addr)
  48. +{
  49. +       int hash;
  50. +
  51. +       hash  =  addr        & 0xff;
  52. +       hash ^= (addr >>  8) & 0xff;
  53. +       hash ^= (addr >> 16) & 0xff;
  54. +       hash ^= (addr >> 24) & 0xff;
  55. +       return hash;
  56. +}
  57. +
  58. +static int count_them(struct ipt_iplimit_data *data,
  59. +                     u_int32_t addr, u_int32_t mask,
  60. +                     struct ip_conntrack *ct)
  61. +{
  62. +       int addit = 1, matches = 0;
  63. +       struct ip_conntrack_tuple tuple;
  64. +       struct ip_conntrack_tuple_hash *found;
  65. +       struct ipt_iplimit_conn *conn;
  66. +       struct list_head *hash,*lh;
  67. +
  68. +       spin_lock(&data->lock);
  69. +       tuple = ct->tuplehash[0].tuple;
  70. +       hash = &data->iphash[ipt_iphash(addr & mask)];
  71. +
  72. +       /* check the saved connections */
  73. +       for (lh = hash->next; lh != hash; lh = lh->next) {
  74. +               conn = list_entry(lh,struct ipt_iplimit_conn,list);
  75. +               found = ip_conntrack_find_get(&conn->tuple,ct);
  76. +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
  77. +                   found != NULL) {
  78. +                       addit = 0;
  79. +               }
  80. +#if DEBUG
  81. +               printk("ipt_udplimit [%d]: src=%u.%u.%u.%u:%d
  82. dst=%u.%u.%u.%u:%d\n",
  83. +                      ipt_iphash(addr & mask),
  84. +                      NIPQUAD(conn->tuple.src.ip),
  85. ntohs(conn->tuple.src.u.udp.port),
  86. +                      NIPQUAD(conn->tuple.dst.ip),
  87. ntohs(conn->tuple.dst.u.udp.port));
  88. +#endif
  89. +               if (NULL == found) {
  90. +                       /* this one is gone */
  91. +                       lh = lh->prev;
  92. +                       list_del(lh->next);
  93. +                       kfree(conn);
  94. +                       continue;
  95. +               }
  96. +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
  97. +                       /* same source IP address -> be counted! */
  98. +                       matches++;
  99. +               }
  100. +               nf_conntrack_put(&found->ctrack->infos[0]);
  101. +       }
  102. +       if (addit) {
  103. +               /* save the new connection in our list */
  104. +#if DEBUG
  105. +               printk("ipt_udplimit [%d]: src=%u.%u.%u.%u:%d
  106. dst=%u.%u.%u.%u:%d new\n",
  107. +                      ipt_iphash(addr & mask),
  108. +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
  109. +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
  110. +#endif
  111. +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
  112. +               if (NULL == conn)
  113. +                       return -1;
  114. +               memset(conn,0,sizeof(*conn));
  115. +               INIT_LIST_HEAD(&conn->list);
  116. +               conn->tuple = tuple;
  117. +               list_add(&conn->list,hash);
  118. +               matches++;
  119. +       }
  120. +       spin_unlock(&data->lock);
  121. +       return matches;
  122. +}
  123. +
  124. +static int
  125. +match(const struct sk_buff *skb,
  126. +      const struct net_device *in,
  127. +      const struct net_device *out,
  128. +      const void *matchinfo,
  129. +      int offset,
  130. +      const void *hdr,
  131. +      u_int16_t datalen,
  132. +      int *hotdrop)
  133. +{
  134. +       const struct ipt_iplimit_info *info = matchinfo;
  135. +       int connections, match;
  136. +       struct ip_conntrack *ct;
  137. +       enum ip_conntrack_info ctinfo;
  138. +
  139. +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
  140. +       if (NULL == ct) {
  141. +               printk("ipt_udplimit: Oops: invalid ct state ?\n");
  142. +               *hotdrop = 1;
  143. +               return 0;
  144. +       }
  145. +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
  146. +       if (-1 == connections) {
  147. +               printk("ipt_udplimit: Hmm, kmalloc failed :-(\n");
  148. +               *hotdrop = 1; /* let's free some memory :-) */
  149. +               return 0;
  150. +       }
  151. +        match = (info->inverse) ? (connections <= info->limit) : (connections
  152. > info->limit);
  153. +#if DEBUG
  154. +       printk("ipt_udplimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
  155. +              "connections=%d limit=%d match=%s\n",
  156. +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
  157. +              connections, info->limit, match ? "yes" : "no");
  158. +#endif
  159. +
  160. +       return match;
  161. +}
  162. +
  163. +static int check(const char *tablename,
  164. +                const struct ipt_ip *ip,
  165. +                void *matchinfo,
  166. +                unsigned int matchsize,
  167. +                unsigned int hook_mask)
  168. +{
  169. +       struct ipt_iplimit_info *info = matchinfo;
  170. +       int i;
  171. +
  172. +       /* verify size */
  173. +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_iplimit_info)))
  174. +               return 0;
  175. +
  176. +       /* refuse anything but udp */
  177. +       if (ip->proto != IPPROTO_UDP)
  178. +               return 0;
  179. +
  180. +       /* init private data */
  181. +       info->data = kmalloc(sizeof(struct ipt_iplimit_data),GFP_KERNEL);
  182. +       spin_lock_init(&(info->data->lock));
  183. +       for (i = 0; i < 256; i++)
  184. +               INIT_LIST_HEAD(&(info->data->iphash));
  185. +      
  186. +       return 1;
  187. +}
  188. +
  189. +static void destroy(void *matchinfo, unsigned int matchinfosize)
  190. +{
  191. +       struct ipt_iplimit_info *info = matchinfo;
  192. +       struct ipt_iplimit_conn *conn;
  193. +       struct list_head *hash;
  194. +       int i;
  195. +
  196. +       /* cleanup */
  197. +       for (i = 0; i < 256; i++) {
  198. +               hash = &(info->data->iphash);
  199. +               while (hash != hash->next) {
  200. +                       conn = list_entry(hash->next,struct
  201. ipt_iplimit_conn,list);
  202. +                       list_del(hash->next);
  203. +                       kfree(conn);
  204. +               }
  205. +       }
  206. +       kfree(info->data);
  207. +}
  208. +
  209. +static struct ipt_match udplimit_match
  210. += { { NULL, NULL }, "udplimit", &match, &check, &destroy, THIS_MODULE };
  211. +
  212. +static int __init init(void)
  213. +{
  214. +       /* NULL if ip_conntrack not a module */
  215. +       if (ip_conntrack_module)
  216. +               __MOD_INC_USE_COUNT(ip_conntrack_module);
  217. +       return ipt_register_match(&udplimit_match);
  218. +}
  219. +
  220. +static void __exit fini(void)
  221. +{
  222. +       ipt_unregister_match(&udplimit_match);
  223. +       if (ip_conntrack_module)
  224. +               __MOD_DEC_USE_COUNT(ip_conntrack_module);
  225. +}
  226. +
  227. +module_init(init);
  228. +module_exit(fini);

  229.     dep_tristate '  Connection state match support' CONFIG_IP_NF_MATCH_STATE
  230. $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
  231.     dep_tristate '  Connections/UDP limit match support'
  232. CONFIG_IP_NF_MATCH_UDPLIMIT $CONFIG_IP_NF_IPTABLES

  233. obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
  234. obj-$(CONFIG_IP_NF_MATCH_UDPLIMIT) += ipt_udplimit.o

  235. Author: Gerd Knorr <kraxel@xxxxxxxxxxx>
  236.         Jan Du Caju <Jan.DuCaju@xxxxxxxxxxxx> (I just made a shameless copy
  237.         of iplimit of Gerd Knorr ;-)
  238. Status: ItWorksForMe[tm]

  239. This adds CONFIG_IP_NF_MATCH_UDPLIMIT match allows you to restrict the
  240. number of parallel UDP connections to a server per client IP address
  241. (or address block).

  242. Examples:

  243. # allow 5 udp connections per client host
  244. iptables -p udp -m udplimit --udplimit-above 5 -j REJECT

  245. # you can also match the other way around:
  246. iptables -p udp -m udplimit ! --udplimit-above 5 -j ACCEPT

  247. # limit the nr of parallel http requests to 16 per class C sized
  248. # network (24 bit netmask)
  249. iptables -p udp --dport 161 -m udplimit --udplimit-above 16             \
  250.         --iplimit-mask 24 -j REJECT

  251. CONFIG_IP_NF_MATCH_STATE
  252. Connections/UDP limit match support
  253. CONFIG_IP_NF_MATCH_UDPLIMIT
  254.   This match allows you to restrict the number of parallel UDP
  255.   connections to a server per client IP address (or address block).

  256.   If you want to compile it as a module, say M here and read
  257.   Documentation/modules.txt.  If unsure, say `N'.

  258. /* Shared library add-on to iptables to add state tracking support. */
  259. #include <stdio.h>
  260. #include <netdb.h>
  261. #include <string.h>
  262. #include <stdlib.h>
  263. #include <stddef.h>
  264. #include <getopt.h>
  265. #include <iptables.h>
  266. #include <linux/netfilter_ipv4/ip_conntrack.h>
  267. #include <linux/netfilter_ipv4/ipt_iplimit.h>

  268. /* Function which prints out usage message. */
  269. static void
  270. help(void)
  271. {
  272.         printf(
  273. "udplimit v%s options:\n"
  274. "[!] --udplimit-above n         match if the number of existing udp connections
  275. is (not) above n\n"
  276. " --udplimit-mask n             group hosts using mask\n"
  277. "\n", IPTABLES_VERSION);
  278. }

  279. static struct option opts[] = {
  280.         { "udplimit-above", 1, 0, '1' },
  281.         { "udplimit-mask",  1, 0, '2' },
  282.         {0}
  283. };

  284. /* Initialize the match. */
  285. static void
  286. init(struct ipt_entry_match *m, unsigned int *nfcache)
  287. {
  288.         /* Can't cache this */
  289.         *nfcache |= NFC_UNKNOWN;
  290. }

  291. /* Function which parses command options; returns true if it
  292.    ate an option */
  293. static int
  294. parse(int c, char **argv, int invert, unsigned int *flags,
  295.       const struct ipt_entry *entry,
  296.       unsigned int *nfcache,
  297.       struct ipt_entry_match **match)
  298. {
  299.         struct ipt_iplimit_info *info = (struct
  300. ipt_iplimit_info*)(*match)->data;

  301.         if (0 == (*flags & 2)) {
  302.                 /* set default mask unless we've already seen a mask option */
  303.                 info->mask = htonl(0xFFFFFFFF);
  304.         }

  305.         switch (c) {
  306.         case '1':
  307.                 check_inverse(optarg, &invert, &optind, 0);
  308.                 info->limit = atoi(argv[optind-1]);
  309.                 info->inverse = invert;
  310.                 *flags |= 1;
  311.                 break;

  312.         case '2':
  313.                 info->mask = htonl(0xFFFFFFFF << (32 - atoi(argv[optind-1])));
  314.                 *flags |= 2;
  315.                 break;

  316.         default:
  317.                 return 0;
  318.         }

  319.         return 1;
  320. }

  321. /* Final check */
  322. static void final_check(unsigned int flags)
  323. {
  324.         if (!flags & 1)
  325.                 exit_error(PARAMETER_PROBLEM, "You must specify
  326. `--udplimit-above'");
  327. }

  328. static int
  329. count_bits(u_int32_t mask)
  330. {
  331.         int i, bits;

  332.         for (bits = 0, i = 31; i >= 0; i--) {
  333.                 if (mask & htonl((u_int32_t)1 << i)) {
  334.                         bits++;
  335.                         continue;
  336.                 }
  337.                 break;
  338.         }
  339.         return bits;
  340. }

  341. /* Prints out the matchinfo. */
  342. static void
  343. print(const struct ipt_ip *ip,
  344.       const struct ipt_entry_match *match,
  345.       int numeric)
  346. {
  347.         struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data;

  348.         printf("#conn/%d %s %d ", count_bits(info->mask),
  349.                info->inverse ? "<" : ">", info->limit);
  350. }

  351. /* Saves the matchinfo in parsable form to stdout. */
  352. static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
  353. {
  354.         struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data;

  355.         printf("%s--udplimit-above %d ",info->inverse ? "! " : "",info->limit);
  356.         printf("--udplimit-mask %d ",count_bits(info->mask));
  357. }

  358. static struct iptables_match udplimit = {
  359.         name:           "udplimit",
  360.         version:        IPTABLES_VERSION,
  361.         size:           IPT_ALIGN(sizeof(struct ipt_iplimit_info)),
  362.         userspacesize:  offsetof(struct ipt_iplimit_info,data),
  363.         help:           help,
  364.         init:           init,
  365.         parse:          parse,
  366.         final_check:    final_check,
  367.         print:          print,
  368.         save:           save,
  369.         extra_opts:     opts
  370. };

  371. void _init(void)
  372. {
  373.         register_match(&udplimit);
  374. }
复制代码

[ 本帖最后由 flycolt 于 2007-10-23 10:09 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2007-11-15 11:50 |只看该作者
原帖由 flycolt 于 2007-10-23 10:07 发表
谢谢这位老兄,你的方法可以实现这个目标,但是比较被动,我希望的结果是和connlimit限制tcp一样的效果来限制udp,我google了一下,2003年有人根据iplimit改写了一个udplimit,但是netfilter团队没有接受他的补丁 ...



不知上面这位兄弟可否也实现了上面的功能?实现后能够帖出来大家一起讨论下呢?

论坛徽章:
0
5 [报告]
发表于 2007-11-15 12:11 |只看该作者
CU 上有位高人,ID 是 liuzhuan23,他实现了对 udp 的控制,但我没有看到过他的代码,更没有测试过
本想自己也写一个,但由于水平不够,也没有时间研究,所以一直搁浅了,一直想向 liuzhuan23 请教但也很少碰面
这段时间比较闲,找个时间我把他找出来,一起研究一下,不知道他是否会和我一样比较闲

论坛徽章:
0
6 [报告]
发表于 2007-11-15 12:54 |只看该作者
参照connlimit写一个UDP的不就可以了么?

论坛徽章:
0
7 [报告]
发表于 2007-11-17 10:42 |只看该作者
都是强人,留名观望啊。

论坛徽章:
0
8 [报告]
发表于 2007-11-21 16:35 |只看该作者
大概看了一下connlimit的代码,它是读取conntrack的信息,来对tcp的连接数目进行限制的。
如果改写为udp没什么困难。

但是conntrack本身性能比较差,我想做一个不基于conntrack的iplimit,同时对tcp和udp有效。

论坛徽章:
0
9 [报告]
发表于 2007-11-30 10:07 |只看该作者
请问斑竹使用connlimit模块限制UDP连接的这个想法是否也实现了呢?

可否帖出来给大家学习一下呢?

论坛徽章:
0
10 [报告]
发表于 2007-11-30 12:01 |只看该作者
upd目前没有更好的办法来对付吧。除了封端口,大家还有什么别的办法呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP