A userspace application that filters DHCP floods to protect a DHCP server. It uses the Netfilter userspace packet queuing API.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

perftest.pl 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #!/usr/bin/perl
  2. use strict;
  3. use IO::Socket::INET;
  4. use IO::Socket::INET6;
  5. use Time::HiRes qw(sleep);
  6. use warnings;
  7. $| = 1;
  8. my($clients, $leasetime, $floodclients, $floodpps, $dest, $destport) = @ARGV;
  9. usage() if !defined $destport;
  10. if ( $clients !~ /^\d+$/ || $clients < 1 ) {
  11. print STDERR "clients count must be a positive integer\n";
  12. exit 1;
  13. }
  14. if ( $leasetime !~ /^\d+$/ || $leasetime < 3 ) {
  15. print STDERR "leasetime must be at least 3\n";
  16. exit 1;
  17. }
  18. if ( $floodclients !~ /^\d+$/ || $floodclients < 0 ) {
  19. print STDERR "floodclients must be a 0 or more\n";
  20. exit 1;
  21. }
  22. if ( $floodpps !~ /^\d+$/ || $floodpps < 0 ) {
  23. print STDERR "floodpps must be 0 or more\n";
  24. exit 1;
  25. }
  26. if ( $dest !~ /^(\d+\.\d+\.\d+\.\d+)$/ && $dest !~ /^[0-9a-fA-F:]+$/ ) {
  27. print STDERR "destination IP must be a valid IPv4/IPv6 address\n";
  28. exit 1;
  29. }
  30. if ( $destport !~ /^\d+$/ || $destport < 1 || $destport > 65535 ) {
  31. print STDERR "destport must be between 1 and 65535\n";
  32. exit 1;
  33. }
  34. main($clients, $leasetime, $floodclients, $floodpps, $dest, $destport);
  35. sub usage {
  36. print STDERR <<EOF;
  37. ==============================================
  38. = DHCP Protect testing client =
  39. = This is only to test dhcp_protect =
  40. = DO NOT SEND THIS TO YOUR DHCP SERVER !!!! =
  41. ==============================================
  42. Usage: $0 <clients> <leasetime> <floodclients> <floodpps> <destination> <port>
  43. clients : number of 'normal' dhcp clients to simulator.
  44. leasetime : the desired leasetime.
  45. floodclients : number of client flood the server.
  46. floodpps : packet rate at which the floodclients flood the server (per client).
  47. destination : target IP address.
  48. port : targer UDP port.
  49. EOF
  50. exit 1;
  51. }
  52. sub main {
  53. my($clients, $leasetime, $floodclients, $floodpps, $dest, $destport)=@_;
  54. my $hdr = "";
  55. my $sock;
  56. if ( $dest =~ /:/ ) { # IPv6
  57. $sock = IO::Socket::INET6->new(
  58. Proto => 'udp',
  59. PeerAddr => $dest,
  60. PeerPort => $destport,
  61. );
  62. $hdr .= pack("H2", "01"); # msg-type
  63. $hdr .= pack("H6", "000000"); # transaction-id
  64. $hdr .= pack("C", 1); # DUID option
  65. $hdr .= pack("C", 6); # DUID length
  66. }
  67. else { # IPv4
  68. $sock = IO::Socket::INET->new(
  69. Proto => 'udp',
  70. PeerAddr => "$dest:$destport",
  71. );
  72. # pseudo packet, the only really relevant thing
  73. # is that option 82 is present and at the right place
  74. $hdr .= pack("H2","01"); # Opcode, bootrequest
  75. $hdr .= pack("H2","01"); # Hardware type, ethernet
  76. $hdr .= pack("H2","06"); # HW addr len, MAC = 6
  77. $hdr .= pack("H2","01"); # hops, 1 relay
  78. $hdr .= pack("H8","00000000"); # transaction ID
  79. $hdr .= pack("H4","0000"); # secs
  80. $hdr .= pack("H4","0000"); # flags
  81. $hdr .= pack("H8","00000000"); # ciaddr
  82. $hdr .= pack("H8","00000000"); # yiaddr
  83. $hdr .= pack("H8","00000000"); # siaddr
  84. $hdr .= pack("H8","00000000"); # giaddr
  85. $hdr .= pack("H32","0"x32); # cihwaddr
  86. $hdr .= pack("H128","0"x128); # hostname
  87. $hdr .= pack("H256","0"x256); # boot filename
  88. $hdr .= pack("H8","63825363"); # magic cookie
  89. $hdr .= pack("C", 82); # opt 82
  90. $hdr .= pack("C", 21); # opt 82 len
  91. $hdr .= pack("C", 1); # subopt 1 (circuitid)
  92. $hdr .= pack("C", 11); # subopt 1 len
  93. $hdr .= "Hello World";
  94. $hdr .= pack("C", 2); # subopt 2 (remoteid)
  95. $hdr .= pack("C", 6); # subopt 2 len (mac)
  96. }
  97. if ( $floodclients > 0 ) {
  98. my $pid = fork();
  99. # flood client
  100. if ( !$pid ) {
  101. my $int = 1/$floodpps/$floodclients;
  102. while(1) {
  103. for(my $i=0; $i<$floodclients; $i++) {
  104. my $pkt = $hdr;
  105. $pkt .= pack("H12", sprintf("66666666%04x", $i));
  106. $sock->send($pkt);
  107. sleep($int);
  108. }
  109. }
  110. exit;
  111. }
  112. }
  113. my $int = $leasetime/3/$clients;
  114. while(1) {
  115. for(my $i=0; $i<$clients; $i++) {
  116. my $pkt = $hdr;
  117. $pkt .= pack("H12", sprintf("00112233%04x",$i));
  118. $sock->send($pkt);
  119. sleep($int);
  120. }
  121. }
  122. }