| #!/usr/bin/perl | #!/usr/bin/perl | ||||
| use strict; | use strict; | ||||
| use IO::Socket::INET; | |||||
| use Time::HiRes qw(sleep); | |||||
| use warnings; | use warnings; | ||||
| $| = 1; | |||||
| my($maccnt, $pps, $src, $dest) = @ARGV; | |||||
| usage() if !defined $dest; | |||||
| if ( $maccnt !~ /^\d+$/ || $maccnt < 1 ) { | |||||
| print STDERR "MAC count must be a positive integer\n"; | |||||
| my($clients, $leasetime, $floodclients, $floodpps, $dest, $destport) = @ARGV; | |||||
| usage() if !defined $destport; | |||||
| if ( $clients !~ /^\d+$/ || $clients < 1 ) { | |||||
| print STDERR "clients count must be a positive integer\n"; | |||||
| exit 1; | |||||
| } | |||||
| if ( $leasetime !~ /^\d+$/ || $leasetime < 3 ) { | |||||
| print STDERR "leasetime must be at least 3\n"; | |||||
| exit 1; | exit 1; | ||||
| } | } | ||||
| if ( $pps !~ /^\d+$/ || $pps < 1 ) { | |||||
| print STDERR "packets/sec must be a positive integer\n"; | |||||
| if ( $floodclients !~ /^\d+$/ || $floodclients < 0 ) { | |||||
| print STDERR "floodclients must be a 0 or more\n"; | |||||
| exit 1; | exit 1; | ||||
| } | } | ||||
| if ( $src !~ /^(\d+\.\d+\.\d+\.\d+)$/ ) { | |||||
| print STDERR "source IP must be a valid IPv4 address\n"; | |||||
| if ( $floodpps !~ /^\d+$/ || $floodpps < 0 ) { | |||||
| print STDERR "floodpps must be 0 or more\n"; | |||||
| exit 1; | exit 1; | ||||
| } | } | ||||
| exit 1; | exit 1; | ||||
| } | } | ||||
| main($maccnt, $pps, $src, $dest); | |||||
| if ( $destport !~ /^\d+$/ || $destport < 1 || $destport > 65535 ) { | |||||
| print STDERR "destport must be between 1 and 65535\n"; | |||||
| exit 1; | |||||
| } | |||||
| main($clients, $leasetime, $floodclients, $floodpps, $dest, $destport); | |||||
| sub usage { | sub usage { | ||||
| print STDERR "DHCP Flood using option 82\n"; | |||||
| print STDERR "This is only to test dhcp_protect, the DHCP packets aren't really valid\n"; | |||||
| print STDERR "DO NOT SEND THIS TO YOUR DHCP SERVER !!!!\n"; | |||||
| print STDERR "\n"; | |||||
| print STDERR "Usage: $0 <MAC count> <packets/sec> <source IPv4> <destination IPv4>\n"; | |||||
| print STDERR "Dependency: nemesis must be installed\n"; | |||||
| print STDERR "https://ftp.troglobit.com/nemesis/\n"; | |||||
| print STDERR "\n"; | |||||
| print STDERR <<EOF; | |||||
| ============================================== | |||||
| = DHCP Protect testing client = | |||||
| = This is only to test dhcp_protect = | |||||
| = DO NOT SEND THIS TO YOUR DHCP SERVER !!!! = | |||||
| ============================================== | |||||
| Usage: $0 <clients> <leasetime> <floodclients> <floodpps> <destination> <port> | |||||
| clients : number of 'normal' dhcp clients to simulator. | |||||
| leasetime : the desired leasetime. | |||||
| floodclients : number of client flood the server. | |||||
| floodpps : packet rate at which the floodclients flood the server (per client). | |||||
| destination : target IP address. | |||||
| port : targer UDP port. | |||||
| EOF | |||||
| exit 1; | exit 1; | ||||
| } | } | ||||
| sub main { | sub main { | ||||
| my($maccnt, $pps, $src, $dest)=@_; | |||||
| my($clients, $leasetime, $floodclients, $floodpps, $dest, $destport)=@_; | |||||
| # pseudo packet, the only really relevant thing | |||||
| # is that option 82 is present and at the right place | |||||
| my $hdr = ""; | my $hdr = ""; | ||||
| $hdr .= "010106010c02385600010000000000000000000000000000c16e5f43409c28db"; | |||||
| $hdr .= "d56c000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "0000000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "0000000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "0000000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "0000000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "0000000000000000000000000000000000000000000000000000000000000000"; | |||||
| $hdr .= "000000000000000000000000638253633501013707017903060f77fc390205dc"; | |||||
| $hdr .= "3d0701409c28dbd56c33040076a7000c097370616c6569666f6e000000000000"; | |||||
| $hdr .= "0000000000000000000000520e0104000000000206XXXXXXXXXXXXff00000000"; | |||||
| $hdr .= pack("H2","01"); # Opcode, bootrequest | |||||
| $hdr .= pack("H2","01"); # Hardware type, ethernet | |||||
| $hdr .= pack("H2","06"); # HW addr len, MAC = 6 | |||||
| $hdr .= pack("H2","01"); # hops, 1 relay | |||||
| $hdr .= pack("H8","00000000"); # transaction ID | |||||
| $hdr .= pack("H4","0000"); # secs | |||||
| $hdr .= pack("H4","0000"); # flags | |||||
| $hdr .= pack("H8","00000000"); # ciaddr | |||||
| $hdr .= pack("H8","00000000"); # yiaddr | |||||
| $hdr .= pack("H8","00000000"); # siaddr | |||||
| $hdr .= pack("H8","00000000"); # giaddr | |||||
| $hdr .= pack("H32","0"x32); # cihwaddr | |||||
| $hdr .= pack("H128","0"x128); # hostname | |||||
| $hdr .= pack("H256","0"x256); # boot filename | |||||
| $hdr .= pack("H8","63825363"); # magic cookie | |||||
| $hdr .= pack("C", 82); # opt 82 | |||||
| $hdr .= pack("C", 21); # opt 82 len | |||||
| $hdr .= pack("C", 1); # subopt 1 (circuitid) | |||||
| $hdr .= pack("C", 11); # subopt 1 len | |||||
| $hdr .= "Hello World"; | |||||
| $hdr .= pack("C", 2); # subopt 2 (remoteid) | |||||
| $hdr .= pack("C", 6); # subopt 2 len (mac) | |||||
| if ( $floodclients > 0 ) { | |||||
| my $pid = fork(); | |||||
| # flood client | |||||
| if ( !$pid ) { | |||||
| my $int = 1/$floodpps/$floodclients; | |||||
| my $sock = IO::Socket::INET->new( | |||||
| Proto => 'udp', | |||||
| PeerAddr => "$dest:$destport", | |||||
| ); | |||||
| while(1) { | |||||
| for(my $i=0; $i<$floodclients; $i++) { | |||||
| my $pkt = $hdr; | |||||
| $pkt .= pack("H12", sprintf("66666666%04x", $i)); | |||||
| $sock->send($pkt); | |||||
| sleep($int); | |||||
| } | |||||
| } | |||||
| exit; | |||||
| } | |||||
| } | |||||
| my $int = 1/$pps; | |||||
| my $int = $leasetime/3/$clients; | |||||
| my $sock = IO::Socket::INET->new( | |||||
| Proto => 'udp', | |||||
| PeerAddr => "$dest:$destport", | |||||
| ); | |||||
| while(1) { | while(1) { | ||||
| for(my $i=0; $i<$maccnt; $i++) { | |||||
| my $mac = sprintf("000000%06x", $i); | |||||
| for(my $i=0; $i<$clients; $i++) { | |||||
| my $pkt = $hdr; | my $pkt = $hdr; | ||||
| $pkt =~ s/XXXXXXXXXXXX/$mac/; | |||||
| open(N,"| nemesis udp -S $src -D $dest -x 67 -y 666 -i $int -P -") || die "install nemesis!"; | |||||
| print N pack("H*",$pkt); | |||||
| print N ""; | |||||
| close(N); | |||||
| $pkt .= pack("H12", sprintf("00112233%04x",$i)); | |||||
| $sock->send($pkt); | |||||
| sleep($int); | |||||
| } | } | ||||
| } | } | ||||
| } | } |