免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: mouzhi
打印 上一主题 下一主题

[网络管理] 【急】服务器受到攻击,如何能验证? [复制链接]

论坛徽章:
0
21 [报告]
发表于 2006-10-13 20:17 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
22 [报告]
发表于 2006-10-14 09:01 |只看该作者
原帖由 initx 于 2006-10-13 20:13 发表


我比较赞同colddawn的做法,另外你这个实验没有说明一点问题
lag由3ms增加200ms以上
你每秒多少数据的包?数据包的大小分片如何分的呢?
CPU,内存,存储配置又是如何呢?如果你拿PIII的同档次的机器
跑1 ...

硬盘是个瓶颈
包速率很低,大概 1Kpps,记录的速率大概也就 100Kpps,Pentium MMX 的机器,5400 转 3.6GB 硬盘
用 -j LOG 有问题,tcpdump 没问题,说明什么?
我重申过很多次了,磁盘 I/O 占用很大,至少我做过实验,你们用 -j LOG 是否也做过实验呢?
也许弄的双 XEON 的 SCSI 硬盘的机器可以 -j LOG 大概上万 pps 的数据,但我没有这个条件去实验,有条件的朋友可否帮我做一下实验,然后贴一下结果?就要 1Wpps 好了,全部 -j LOG,用高端一些的机器,告诉我 CPU 和网络延时的差异变化,谢谢!

论坛徽章:
0
23 [报告]
发表于 2006-10-14 17:43 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
24 [报告]
发表于 2006-10-14 17:50 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
25 [报告]
发表于 2006-10-14 18:09 |只看该作者
同意一下楼上的。

论坛徽章:
0
26 [报告]
发表于 2006-10-14 23:01 |只看该作者
原帖由 initx 于 2006-10-14 17:43 发表


你的MMX机器的测试能说明什么?

那我就不贴了,贴了又能说明什么呢?
我说过很多遍了磁盘 I/O,我的机器慢,硬盘转速低,cache 少,相对 tcpdump 就没事
如果这仍不能说明什么,那讨论下去确实没意义了

论坛徽章:
0
27 [报告]
发表于 2006-10-14 23:12 |只看该作者
原帖由 platinum 于 2006-10-14 23:01 发表

那我就不贴了,贴了又能说明什么呢?
我说过很多遍了磁盘 I/O,我的机器慢,硬盘转速低,cache 少,相对 tcpdump 就没事
如果这仍不能说明什么,那讨论下去确实没意义了


两种机制,级别不同

论坛徽章:
0
28 [报告]
发表于 2006-10-15 01:21 |只看该作者
对于说使用iptables记录log会导致磁盘i/o瓶颈的问题,我从理论上怀疑,同时我自己的经验也证明写日志不会导致很严重的问题,至少在100Mbps环境下,普通PC的硬件都不会有太大问题。

理论推测:
1,硬盘传输速率,以普通UDMA/133来计算,单个IDE磁盘能达到的传输速率极限为133MB/s,但其实无法达到,根据现今很多IDE硬盘评测,基本都能达到60MB/s的最大传输速率,按平均30MB/s来算,也就是说硬盘同步读写能达到30MB/s,换算到bit为240Mb/s,此时CPU占用率最大不超过10%。
然后算网络流量以及产生日志的量。按照1个包产生100字节的日志纪录,如果是每秒1k的包,那流量不过100KB。算bit也不过800Kb,离240Mb差的远哪。
2,iptables与tcpdump效率对比:
   如果不写文件,iptables处理比tcpdump效率高得多,这没人有意见吧。
  如果都写日志,那iptables同样比tcpdump高得多,这也是显而易见的吧。
  又有人说tcpdump不写日志,难道就你tcpdump能不写日志吗?凭什么认为tcpdump可以不写日志就咬定使用iptables不行?我还可以把iptables日志转储到ramfs呢。
  另外加一个个人推测,别以为tcpdump不写日志就一定比iptables+log耗费更多的系统资源,如果算上libpcap著名的低性能和内核磁盘缓冲带来的异步些文件,谁比谁高效还真没人敢下定论,怎么就有人牛到敢直斥别人“疯了”?!

个人经验:
  双Xeon机器,SCSI硬盘,iptables记录,几分钟内就能搞出G为单位的日志,系统负载1左右,日志记录没有明显拖慢网络,至于数据就不搞了,几年前的机器了,早就干掉了。

另外拿个不是很恰当的例子类比下:比如兵法连接很大的web服务器,httpd server一般是要记录访问日志的,一般来说是访问1个文件记录一条,按照普通网页文件算100k大小一个,如果iptables这种内核级别的磁盘读写在1kpps的时候都会把系统拖垮的话,那记录同样数量级别的httpd server,假定访问都是这种小文件访问的情况下,因为i/o瓶颈,没可能跑上1M的流量了?实际情况是很烂的一个PC都能胜任此类工作,

论坛徽章:
0
29 [报告]
发表于 2006-10-15 02:47 |只看该作者
请你不要偷换概念,我针对的是楼主分析可能被 DDoS 的情况
请认真阅读 16 楼的贴子
我针对说他“疯了”不仅是说他用 iptables 的 -j LOG 替代 tcpdump,还包括了 16 楼最后红色的那几个字
1、全部 NEW
2、十几分钟

按照1个包产生100字节的日志纪录,如果是每秒1k的包,那流量不过100KB。

对不起,不能同意你的假设
我数了一下,一条 -j LOG 的记录占用了 196 字节(平均)

  1. Oct 15 02:15:49 PT_LINUX kernel: IN=ppp0 OUT=ath0 SRC=60.166.224.239 DST=192.168.39.200 LEN=40 TOS=0x00 PREC=0x00 TTL=112 ID=53284 DF PROTO=TCP SPT=14114 DPT=26881 WINDOW=0 RES=0x00 ACK RST URGP=0
复制代码

而 tcpdump -i ppp0 -c 10 -w test 之后的 test 文件只有 838 字节,平均每个包是 83.8 字节,相差了 2 倍多
我想,如果 LOG 的时候使用了 --log-prefix 参数,恐怕还不止这个数字吧?

如果不写文件,iptables处理比tcpdump效率高得多,这没人有意见吧。
如果都写日志,那iptables同样比tcpdump高得多,这也是显而易见的吧。

“的吧”、“的吧”,你的猜测和假设也太多了点
我仍然很抱歉,这两句话还不足以说服我,我有意见,而且你的论点相反让我感觉非常站不住脚,下面来具体说一下为什么

ipt_LOG.c 是通过 printk 大量的信息来实现的,那么 printk 什么东西呢?
因为前面说了做所有 NEW 状态包的 LOG,那么应该写成 iptables -I INPUT -m state --state NEW -j LOG 吧?(因为那位朋友说的可是记录所有进入的 NEW 包哦)
懂 netfilter 的朋友都就应该知道,由于 conntrack 的机制,NEW 状态可以是任何包,包括 tcp、icmp、udp,以及其它
针对那位朋友说的所有 NEW 状态包,我们看一下 ipt_LOG.c 都要做什么,看它是如何处理数据并 printk 的

  1. /* One level of recursion won't kill us */
  2. static void dump_packet(const struct ipt_log_info *info,
  3.                         struct iphdr *iph, unsigned int len, int recurse)
  4. {
  5.         void *protoh = (u_int32_t *)iph + iph->ihl;
  6.         unsigned int datalen = len - iph->ihl * 4;

  7.         /* Important fields:
  8.          * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
  9.         /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
  10.         printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
  11.                NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));

  12.         /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
  13.         printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
  14.                ntohs(iph->tot_len), iph->tos & IPTOS_TOS_MASK,
  15.                iph->tos & IPTOS_PREC_MASK, iph->ttl, ntohs(iph->id));

  16.         /* Max length: 6 "CE DF MF " */
  17.         if (ntohs(iph->frag_off) & IP_CE)
  18.                 printk("CE ");
  19.         if (ntohs(iph->frag_off) & IP_DF)
  20.                 printk("DF ");
  21.         if (ntohs(iph->frag_off) & IP_MF)
  22.                 printk("MF ");

  23.         /* Max length: 11 "FRAG:65535 " */
  24.         if (ntohs(iph->frag_off) & IP_OFFSET)
  25.                 printk("FRAG:%u ", ntohs(iph->frag_off) & IP_OFFSET);

  26.         if ((info->logflags & IPT_LOG_IPOPT)
  27.             && iph->ihl * 4 > sizeof(struct iphdr)
  28.             && iph->ihl * 4 <= len) {
  29.                 unsigned int i;

  30.                 /* Max length: 127 "OPT (" 15*4*2chars ") " */
  31.                 printk("OPT (");
  32.                 for (i = sizeof(struct iphdr); i < iph->ihl * 4; i++)
  33.                         printk("%02X", ((u_int8_t *)iph)[i]);
  34.                 printk(") ");
  35.         }

  36.         switch (iph->protocol) {
  37.         case IPPROTO_TCP: {
  38.                 struct tcphdr *tcph = protoh;

  39.                 /* Max length: 10 "PROTO=TCP " */
  40.                 printk("PROTO=TCP ");

  41.                 if (ntohs(iph->frag_off) & IP_OFFSET)
  42.                         break;

  43.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  44.                 if (datalen < sizeof (*tcph)) {
  45.                         printk("INCOMPLETE [%u bytes] ", datalen);
  46.                         break;
  47.                 }

  48.                 /* Max length: 20 "SPT=65535 DPT=65535 " */
  49.                 printk("SPT=%u DPT=%u ",
  50.                        ntohs(tcph->source), ntohs(tcph->dest));
  51.                 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
  52.                 if (info->logflags & IPT_LOG_TCPSEQ)
  53.                         printk("SEQ=%u ACK=%u ",
  54.                                ntohl(tcph->seq), ntohl(tcph->ack_seq));
  55.                 /* Max length: 13 "WINDOW=65535 " */
  56.                 printk("WINDOW=%u ", ntohs(tcph->window));
  57.                 /* Max length: 9 "RES=0x3F " */
  58.                 printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
  59.                 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
  60.                 if (tcph->cwr)
  61.                         printk("CWR ");
  62.                 if (tcph->ece)
  63.                         printk("ECE ");
  64.                 if (tcph->urg)
  65.                         printk("URG ");
  66.                 if (tcph->ack)
  67.                         printk("ACK ");
  68.                 if (tcph->psh)
  69.                         printk("PSH ");
  70.                 if (tcph->rst)
  71.                         printk("RST ");
  72.                 if (tcph->syn)
  73.                         printk("SYN ");
  74.                 if (tcph->fin)
  75.                         printk("FIN ");
  76.                 /* Max length: 11 "URGP=65535 " */
  77.                 printk("URGP=%u ", ntohs(tcph->urg_ptr));

  78.                 if ((info->logflags & IPT_LOG_TCPOPT)
  79.                     && tcph->doff * 4 > sizeof(struct tcphdr)
  80.                     && tcph->doff * 4 <= datalen) {
  81.                         unsigned int i;

  82.                         /* Max length: 127 "OPT (" 15*4*2chars ") " */
  83.                         printk("OPT (");
  84.                         for (i =sizeof(struct tcphdr); i < tcph->doff * 4; i++)
  85.                                 printk("%02X", ((u_int8_t *)tcph)[i]);
  86.                         printk(") ");
  87.                 }
  88.                 break;
  89.         }
  90.         case IPPROTO_UDP: {
  91.                 struct udphdr *udph = protoh;

  92.                 /* Max length: 10 "PROTO=UDP " */
  93.                 printk("PROTO=UDP ");

  94.                 if (ntohs(iph->frag_off) & IP_OFFSET)
  95.                         break;

  96.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  97.                 if (datalen < sizeof (*udph)) {
  98.                         printk("INCOMPLETE [%u bytes] ", datalen);
  99.                         break;
  100.                 }

  101.                 /* Max length: 20 "SPT=65535 DPT=65535 " */
  102.                 printk("SPT=%u DPT=%u LEN=%u ",
  103.                        ntohs(udph->source), ntohs(udph->dest),
  104.                        ntohs(udph->len));
  105.                 break;
  106.         }
  107.         case IPPROTO_ICMP: {
  108.                 struct icmphdr *icmph = protoh;
  109.                 static size_t required_len[NR_ICMP_TYPES+1]
  110.                         = { [ICMP_ECHOREPLY] = 4,
  111.                             [ICMP_DEST_UNREACH]
  112.                             = 8 + sizeof(struct iphdr) + 8,
  113.                             [ICMP_SOURCE_QUENCH]
  114.                             = 8 + sizeof(struct iphdr) + 8,
  115.                             [ICMP_REDIRECT]
  116.                             = 8 + sizeof(struct iphdr) + 8,
  117.                             [ICMP_ECHO] = 4,
  118.                             [ICMP_TIME_EXCEEDED]
  119.                             = 8 + sizeof(struct iphdr) + 8,
  120.                             [ICMP_PARAMETERPROB]
  121.                             = 8 + sizeof(struct iphdr) + 8,
  122.                             [ICMP_TIMESTAMP] = 20,
  123.                             [ICMP_TIMESTAMPREPLY] = 20,
  124.                             [ICMP_ADDRESS] = 12,
  125.                             [ICMP_ADDRESSREPLY] = 12 };

  126.                 /* Max length: 11 "PROTO=ICMP " */
  127.                 printk("PROTO=ICMP ");

  128.                 if (ntohs(iph->frag_off) & IP_OFFSET)
  129.                         break;

  130.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  131.                 if (datalen < 4) {
  132.                         printk("INCOMPLETE [%u bytes] ", datalen);
  133.                         break;
  134.                 }

  135.                 /* Max length: 18 "TYPE=255 CODE=255 " */
  136.                 printk("TYPE=%u CODE=%u ", icmph->type, icmph->code);

  137.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  138.                 if (icmph->type <= NR_ICMP_TYPES
  139.                     && required_len[icmph->type]
  140.                     && datalen < required_len[icmph->type]) {
  141.                         printk("INCOMPLETE [%u bytes] ", datalen);
  142.                         break;
  143.                 }

  144.                 switch (icmph->type) {
  145.                 case ICMP_ECHOREPLY:
  146.                 case ICMP_ECHO:
  147.                         /* Max length: 19 "ID=65535 SEQ=65535 " */
  148.                         printk("ID=%u SEQ=%u ",
  149.                                ntohs(icmph->un.echo.id),
  150.                                ntohs(icmph->un.echo.sequence));
  151.                         break;

  152.                 case ICMP_PARAMETERPROB:
  153.                         /* Max length: 14 "PARAMETER=255 " */
  154.                         printk("PARAMETER=%u ",
  155.                                ntohl(icmph->un.gateway) >> 24);
  156.                         break;
  157.                 case ICMP_REDIRECT:
  158.                         /* Max length: 24 "GATEWAY=255.255.255.255 " */
  159.                         printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway));
  160.                         /* Fall through */
  161.                 case ICMP_DEST_UNREACH:
  162.                 case ICMP_SOURCE_QUENCH:
  163.                 case ICMP_TIME_EXCEEDED:
  164.                         /* Max length: 3+maxlen */
  165.                         if (recurse) {
  166.                                 printk("[");
  167.                                 dump_packet(info,
  168.                                             (struct iphdr *)(icmph + 1),
  169.                                             datalen-sizeof(struct icmphdr),
  170.                                             0);
  171.                                 printk("] ");
  172.                         }

  173.                         /* Max length: 10 "MTU=65535 " */
  174.                         if (icmph->type == ICMP_DEST_UNREACH
  175.                             && icmph->code == ICMP_FRAG_NEEDED)
  176.                                 printk("MTU=%u ", ntohs(icmph->un.frag.mtu));
  177.                 }
  178.                 break;
  179.         }
  180.         /* Max Length */
  181.         case IPPROTO_AH: {
  182.                 struct ahhdr *ah = protoh;

  183.                 /* Max length: 9 "PROTO=AH " */
  184.                 printk("PROTO=AH ");

  185.                 if (ntohs(iph->frag_off) & IP_OFFSET)
  186.                         break;

  187.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  188.                 if (datalen < sizeof (*ah)) {
  189.                         printk("INCOMPLETE [%u bytes] ", datalen);
  190.                         break;
  191.                 }

  192.                 /* Length: 15 "SPI=0xF1234567 " */
  193.                 printk("SPI=0x%x ", ntohl(ah->spi) );
  194.                 break;
  195.         }
  196.         case IPPROTO_ESP: {
  197.                 struct esphdr *esph = protoh;

  198.                 /* Max length: 10 "PROTO=ESP " */
  199.                 printk("PROTO=ESP ");

  200.                 if (ntohs(iph->frag_off) & IP_OFFSET)
  201.                         break;

  202.                 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  203.                 if (datalen < sizeof (*esph)) {
  204.                         printk("INCOMPLETE [%u bytes] ", datalen);
  205.                         break;
  206.                 }

  207.                 /* Length: 15 "SPI=0xF1234567 " */
  208.                 printk("SPI=0x%x ", ntohl(esph->spi) );
  209.                 break;
  210.         }
  211.         /* Max length: 10 "PROTO 255 " */
  212.         default:
  213.                 printk("PROTO=%u ", iph->protocol);
  214.         }

  215.         /* Proto    Max log string length */
  216.         /* IP:      40+46+6+11+127 = 230 */
  217.         /* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
  218.         /* UDP:     10+max(25,20) = 35 */
  219.         /* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
  220.         /* ESP:     10+max(25)+15 = 50 */
  221.         /* AH:      9+max(25)+15 = 49 */
  222.         /* unknown: 10 */

  223.         /* (ICMP allows recursion one level deep) */
  224.         /* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
  225.         /* maxlen = 230+   91  + 230 + 252 = 803 */
  226. }
复制代码

这个处理是不是有点复杂?要判断那么多东西,如果包速率很快的话。。。。
相比之下,tcpudmp 又是如何处理的呢?
tcpdump 只是简单的利用 libpcap 库抓取信息,存入文件而已,没上面那么复杂的处理过程


下面来说最主要的部分,也就是我为什么说他 “疯了” 的地方——文件写入机制
又有人说tcpdump不写日志,难道就你tcpdump能不写日志吗?凭什么认为tcpdump可以不写日志就咬定使用iptables不行?我还可以把iptables日志转储到ramfs呢。
对于说使用iptables记录log会导致磁盘i/o瓶颈的问题,我从理论上怀疑
另外加一个个人推测,别以为tcpdump不写日志就一定比iptables+log耗费更多的系统资源,如果算上libpcap著名的低性能和内核磁盘缓冲带来的异步些文件,谁比谁高效还真没人敢下定论,怎么就有人牛到敢直斥别人“疯了”?!

若你非要把 iptables 的日志放到 ramfs 上,tcpdump 又为何就不可呢?
既然是比较,大家都放在同一起跑线比较好,我们自然都是要比有文件存储记录的情况
请不要凭空猜测或怀疑什么,我们来用事实说话吧

tcpdump 虽然利用了 libpcap,效率确实比 netfilter 要低,因为要把网卡设置为混杂模式,但写文件过程却一直是连续的
如果你写过用户态的程序你会知道如何打开、写入、关闭文件,而 ipt_LOG.c 是如何实现的呢?
ipt_LOG.c 通过 printk 来打印一些重要信息,利用 syslogd 将信息存入 /etc/syslog.conf 指定的文件中
而 syslog 是如何工作的呢?他是通过不断检查 /proc/kmsg 有无新信息,有就马上写入文件来实现的
下面看一下 syslogd.c 的工作方式,看一下它是如何打开、关闭文件的

  1. /* Path for the file where all log messages are written */
  2. #define __LOG_FILE "/var/log/messages"

  3. static char *logFilePath = __LOG_FILE;

  4. /* Note: There is also a function called "message()" in init.c */
  5. /* Print a message to the log file. */
  6. static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
  7. static void message (char *fmt, ...)
  8. {
  9.         int fd;
  10.         struct flock fl;
  11.         va_list arguments;

  12.         fl.l_whence = SEEK_SET;
  13.         fl.l_start  = 0;
  14.         fl.l_len    = 1;

  15.         if ((fd = device_open (logFilePath,
  16.                                                    O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
  17.                                                    O_NONBLOCK)) >= 0) {
  18.                 fl.l_type = F_WRLCK;
  19.                 fcntl (fd, F_SETLKW, &fl);
  20.                 va_start (arguments, fmt);
  21.                 vdprintf (fd, fmt, arguments);
  22.                 va_end (arguments);
  23.                 fl.l_type = F_UNLCK;
  24.                 fcntl (fd, F_SETLKW, &fl);
  25.                 close (fd);
  26.         } else {
  27.                 /* Always send console messages to /dev/console so people will see them. */
  28.                 if ((fd = device_open (_PATH_CONSOLE,
  29.                                                            O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
  30.                         va_start (arguments, fmt);
  31.                         vdprintf (fd, fmt, arguments);
  32.                         va_end (arguments);
  33.                         close (fd);
  34.                 } else {
  35.                         fprintf (stderr, "Bummer, can't print: ");
  36.                         va_start (arguments, fmt);
  37.                         vfprintf (stderr, fmt, arguments);
  38.                         fflush (stderr);
  39.                         va_end (arguments);
  40.                 }
  41.         }
  42. }
复制代码

是否注意到了,在 message 函数里,有一个完整的打开、关闭文件的过程
下面再看一下它是如何记录一条信息的

  1. static void logMessage (int pri, char *msg)
  2. {
  3.         time_t now;
  4.         char *timestamp;
  5.         static char res[20] = "";
  6.         CODE *c_pri, *c_fac;

  7.         if (pri != 0) {
  8.                 for (c_fac = facilitynames;
  9.                          c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
  10.                 for (c_pri = prioritynames;
  11.                          c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
  12.                 if (*c_fac->c_name == '\0' || *c_pri->c_name == '\0')
  13.                         snprintf(res, sizeof(res), "<%d>", pri);
  14.                 else
  15.                         snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
  16.         }

  17.         if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
  18.                 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
  19.                 time(&now);
  20.                 timestamp = ctime(&now) + 4;
  21.                 timestamp[15] = '\0';
  22.         } else {
  23.                 timestamp = msg;
  24.                 timestamp[15] = '\0';
  25.                 msg += 16;
  26.         }

  27.         /* todo: supress duplicates */

  28.         /* now spew out the message to wherever it is supposed to go */
  29.         message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
  30. }
复制代码

最后一个调用 message 函数的语句是否看到了?不知道现在是否能看明白差别了呢?
每条信息的写入,都要单独打开、关闭文件,我说了很多次是磁盘 I/O 的瓶颈,如果遇到了 DDoS 呢?

我的机器很慢,磁盘转速很低,噪音很大,所以 -j LOG 每个数据包的时候都能听到很明显的 “嘎拉” 一下的声音,数据包多的话,这个 “嘎拉” 的声音就非常频繁,但由于转速低,这个声音也有个频繁的范围,如果包速非常快的时候就会造成 “超载”,而反之用 tcpdump 就一点问题没有


另外,上面两位朋友有几个误区,我这里说一下
同时我自己的经验也证明写日志不会导致很严重的问题,至少在100Mbps环境下,普通PC的硬件都不会有太大问题

同样是 100Mbps 的情况下,正常传输(最大吞吐量)与线速传输是截然不同的两个概念,二者对系统的负载差非常大

个人经验:
  双Xeon机器,SCSI硬盘,iptables记录,几分钟内就能搞出G为单位的日志,系统负载1左右,日志记录没有明显拖慢网络

与存放多大数据无关,且与负载无关,网络方面的东西不要看 load,要看 CPU,为什么呢?请去 google 一下 load 是什么。至于双 Xeon 配 SCSI 硬盘的机器我没有发言权,即便真的可以承受 syslog 的实时文件写入的高负载,我也没有钱去买那么好的机器去做实验,太烧包了。。。


另外针对上面的数据,我还有一些分析也可以证明用 -j LOG 不可行
client
P-M 1.7G MEM 512M

60秒测试时间 2.5M测试数据
iptable -L系统负载
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
0  0  10428  31536   8164  65880    0    0     0    24 1067    51  0  0 100  0
0  0  10428  31176   8428  65956    0    0    80   644 1246   478  2  4 83 11
0  0  10428  30600   8980  65972    0    0     0  1180 1442   920  0  5 89  6
0  0  10428  30096   9480  65984    0    0     4  1052 1380   842  2  4 86  8
0  0  10428  29592   9976  65996    0    0     0  1052 1407   839  3  4 88  5
0  0  10428  29064  10472  66012    0    0     0  1068 1401   838  0  2 92  6
0  0  10428  28560  10976  66024    0    0     0  1068 1399   851  0  1 93  6
0  0  10428  28008  11512  66036    0    0     0  1132 1414   900  1  1 92  6
1  1  10428  27504  12012  66052    0    0     4  1080 1386   847  0  2 90  8
0  1  10428  26976  12532  66064    0    0     0  1100 1393   877  0  0 93  7
0  0  10428  26448  13052  66076    0    0     0  1088 1401   866  0  5 90  5
0  0  10428  25872  13604  66092    0    0     0  1180 1441   929  2  4 87  7
0  0  10428  25344  14124  66104    0    0     0  1100 1390   873  4  3 87  6
0  0  10428  24840  14628  66120    0    0     0  1088 1381   851  0  3 91  6
0  0  10428  24312  15140  66132    0    0     0  1084 1377   861  0  2 92  6
0  1  10428  23788  15636  66144    0    0     0  1104 1389   853  1  1 92  6
0  0  10428  23284  16140  66160    0    0     0  1080 1364   844  0  1 93  6
0  0  10428  22828  16576  66172    0    0     0  1084 1385   861  0  2 92  6
0  0  10428  22444  16952  66184    0    0     0  1100 1411   871  0  3 91  6
0  0  10428  21988  17384  66200    0    0     0  1100 1412   863  1  4 89  6
0  0  10428  21652  17720  66212    0    0     0  1004 1415   799  3  3 88  6

如果是普通传输数据的话,应该都是大包,既最大吞吐量的情况
60 秒 2.5MB 数据
2.5 * 1024 / 60 = 43.7kB/s
按照大包 1500bytes 算,43.7 * 1024 / 1500 = 30pps
根据上面的数据,通过 id 来看,CPU 已经被占用了 10%,但是 30pps 与 1kpps 又差了多少呢?30 多倍!10% 与 100% 又差多少呢?即便按照 800bytes 算每个包,1kpps 又会如何呢?届时 CPU 的 idle 不知又剩多少呢?
如果是 syn-flood 攻击的话,64bytes 小包,1kpps 的话,才有 64kB/s 的流量,但被攻击的时候,包速率又何止 1kpps 呢?
另外再补充一点,人家明明已经说了原来是2M的带宽,增加到4M
4M的数据,你们能知道这个数据的含义么?
如果连4M的数据都搞不定的话-_-b 别玩了。你们还是比较适合玩windows

100Mbps 线速是 14.88Wpps,4Mbps 的线速可以达到 5952pps,也就是大概 6kpps 的速度
不是说风凉话,也不是说话尖酸刻薄,但我真的感觉我更比你了解 4Mbps 的数据是什么概念 ^_^

通过 syslogd.c 也看到了,包速率越快,-j LOG 记录的内容就越多,磁盘 I/O 就越大
以一个 6kpps 的 syn-flood 攻击来举例,系统的 application 就要每秒至少产生 6000 次的 “开、关” 文件操作,而且内容还是经过存放的内容还是经过处理过的,如果处理不完就要等待,等待就会造成延时,这个效率。。。

至少对于楼主的问题---分析是否被攻击,我相信这绝对是可行的方法
让我感到不爽的是至少有2个人质疑提出这个建议的人是否“疯了”,另外更有人竟然从分析简易/困难程度,甚至扯到i/o瓶颈去

你自己有没有感觉你在这个讨论里的猜测和假设太多了点?
I/O 问题是我提出来的,不用“竟然有人”,下次直接点我名就好
I/O 的问题我不能不说,还是我前面反反复复说的那句话,磁盘是个瓶颈,而且我记得不止说了一次
算了,我不想一遍又一遍说重复的话了,信不信由你们,何去何从与我无关,这个讨论我就参与到这里了

[ 本帖最后由 platinum 于 2006-10-15 07:13 编辑 ]

论坛徽章:
0
30 [报告]
发表于 2006-10-15 03:07 |只看该作者
看完了楼上的分析。

觉得必须强化的观念就是,在 DDoS 下用日志记录的防火墙,死得更快。

对于日志记录的情况,我的推测:为了尽量把每一条日志都记录进磁盘,syslogd 在写完日志后进行了关闭文件的操作,这样同步缓冲区。所以总会发生硬盘的实际读写。我这里在有人用 ssh 进行端口扫描的时候,硬盘灯就亮个不停,/var/log/secure 的增长速度虽不快,可是在这样高的读写消耗条件下,tcpdump 绝对已经占有了性能优势。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP