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 4.0KB

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