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.

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("n", 1); # DUID option
  65. $hdr .= pack("n", 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. }