A userspace application that filters DHCP floods to protect a DHCP server. It uses the Netfilter userspace packet queuing API.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

perftest.pl 4.3KB

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