How to block packet in pox controller? - packet

When im trying this code below and check it using "tcpdump -teni h32-eth0" cause i was attack on host32 but packets keep coming with length 0, i want to drop the incoming packet, anybody can help?
def _timer_func ():
global diction
global set_Timer
if set_Timer==True:
for k,v in diction.iteritems():
print "Switch ID : "+str(k)
#print "nilai v : "+str(v)
#print "v iteritems : "+str(v.iteritems)
for i,j in v.iteritems():
print "Port Number : "+str(i)
#print "nilai j : "+str(j)
if j >=5:
print "_____________________________________________________________________________________________"
print "\n DDOS DETECTED \n"
print "\n",str(diction)
print "\n",datetime.datetime.now(),": BLOCKED PORT NUMBER : ", str(i), " OF SWITCH ID: ", str(k)
print "\n___________________________________________________________________________________________"
#os._exit(0)
dpid = k
msg = of.ofp_packet_out(in_port=i) #drop paket
print msg
core.openflow.sendToDPID(dpid,msg)
diction={}

I think you are missing the packet's buffer-id or the packet itself in the message that you send to the switch. Note that, you are dropping one packet. It will not prevent from further packets arriving through that in-port. If you want to block that in-port or better this flow, then you should install a flow matching rule that will drop all matching packets.

Related

perl socket client won't recognize end of message

I am running a simple perl socket client that queries a server, and then tries to close the socket once a keyword or phrase is encountered.
...
local $\ = "\x{0d}";
while($line = <$sock>){
print $line."\n";
last if ($line =~ /C6/);
}
...
close($sock);
I'd be happy to terminate on either the (0x0d) or the "C6" string - they both terminate the message. I'm monitoring it with Wireshark, and both triggers occur at the end of the message, yet I can't break out of the while loop, either with a break or last, nor does $line ever print.
Ideas? TIA
You don't exit when you receive C6 without receiving a Carriage Return (or EOF) because your code always waits for a Carriage Return (or EOF). Fix:
# sysread returns as soon as data is available, so this is a just a maximum.
use constant BLOCK_SIZE => 4*1024*1024;
my $buf = '';
while (1) {
my $rv = sysread($sock, $buf, length($buf), 4*1024*1024);
die($!) if !defined($rv);
last if !$rv;
process_message($1)
while $buf =~ s/^( (?: [^C\x0D] | C (?=[^6]) )*+ (?: C6 | \x0D ) )//xs;
}
die("Premature EOF") if length($buf);
I think the root of your problem here is that you've got $\ set, which is the output record separator, rather than $/ which is the input record separator.
So your while is waiting for a \n to occur before handing $line onto the rest of the loop.
But failing that, there's also a question of buffering and autoflushing on your socket.
And ... when you say you're monitoring with wireshark, how sure are you that those values are part of the packet content payload rather than part of the packet? Do you actually get \n sent from the server as part of the packet at any point?

How to extract all Ping Parameters in Perl

I am trying to ping around 100 hosts from a column in sql database
I am using the
use Net::Ping;
use Array::Average; modules
Is there an alternative such that i can extract the packet loss,rtt(min,max,avg) parameters directly from a perl script?
Here is my pseudo code
$p = Net::Ping->new('icmp');
$p->hires();
$host = "www.xyz.com";
print "$host \n";
#rtt= 0;
$j=0;
for ($i=0;$i<5;$i++) {
($ret, $duration, $ip) = $p->ping($host, 5);# wait time 5
if($ret){
printf("$host [ip: $ip] $duration ms\n");
$rtt[$i] = $duration;
}
else{
$j++;
#$p->nack( $failed_ack_host );
}}
print " #rtt\n";
$rtt= average(#rtt);
print "The average rtt is $rtt \n";
$Packet_Loss = ((5-$j)/5)*100;
print "$Packet_Loss\%\n";
`Net::Ping' does not seem to return RTT, etc. You might try issuing the system ping command, and processing the results yourself:
$result = `ping -c 10 $host`;
...then parse $result for the fields you need.
Looking at the documentation and source code, the Net::Ping module carries out just one "ping" each time you call the ping() method. It does not keep any internal "state" based on the success or otherwise of previous calls. The advantage of this approach is that it's simple and no-nonsense. However, if you want aggregated results, you're going to have to do them yourself, as you've discovered.
While it's tempting to call an external ping command, you need to be sure that's what you want: you gain not having to do some maths, but you then become more system-specific (not all systems have a ping command), you are dependent on some assumptions about what options to pass to the command and what format the output will be in, you've added the overhead of creating a new process, and you're running the risk that you may never get control back (some ping commands simply run until you interrupt them). Personally, I'd stick with the approach you're taking.
Also, in your particular code above, have a look at how you're storing your results. If the first three and last ping succeed, say, but the last-but-one doesn't, you're passing an array to average() with an undefined value, which is probably not what you want. I'd suggest something like this instead:
my #rtt;
my $attempts = 5;
foreach (1 .. $attempts) {
my ($ret, $duration, $ip) = $p->ping($host, 5); # timeout after 5 seconds
if ($ret) {
print "$host [ip: $ip] $duration ms\n";
push #rtt, $duration;
} else {
$j++;
}
}
⋮
if (#rtt) {
my $rtt= average(#rtt);
print "The average rtt is $rtt \n";
} else {
print "No responses to ping\n";
}
This fixes one or two other corner cases as well.

Perl Pcap Module not capturing over 1500 Bytes

I have a small pcap listener i made in perl. And whenever i get anything over 1500 Bytes, it just prints as 1500.
66.0.X.X 1500
Now i get that reply when i sent a 2000 byte packet, i also tried sending 1600, and 10k.
No matter what i get 1500 for pcap.
How can i fix this i looked at SNAPLEN but when i set it under or over, i get the same results.
I have also tried tcpdump and i get weird results, as you can see the first "length" is 1500, but the second a line under is 5000 which is what i sent.
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
21:59:06.142530 IP (tos 0x0, ttl 58, id 45206, offset 0, flags [+], proto UDP (17), length 1500)
37.X.X.X.48254 > XXX.54: UDP, length 5000
my code:
use Net::Pcap;
use NetPacket::Ethernet;
use NetPacket::Ethernet qw(:strip);
use NetPacket::IP;
use NetPacket::IP;
use NetPacket::TCP;
use strict;
my $err;
# Use network device passed in program arguments or if no
# argument is passed, determine an appropriate network
# device for packet sniffing using the
# Net::Pcap::lookupdev method
my $dev = $ARGV[0];
unless (defined $dev) {
$dev = Net::Pcap::lookupdev(\$err);
if (defined $err) {
die 'Unable to determine network device for monitoring - ', $err;
}
}
# Look up network address information about network
# device using Net::Pcap::lookupnet - This also acts as a
# check on bogus network device arguments that may be
# passed to the program as an argument
my ($address, $netmask);
if (Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err)) {
die 'Unable to look up device information for ', $dev, ' - ', $err;
}
# Create packet capture object on device
my $object;
$object = Net::Pcap::open_live($dev, 65535, 1, 0, \$err);
unless (defined $object) {
die 'Unable to create packet capture on device ', $dev, ' - ', $err;
}
# Compile and set packet filter for packet capture
# object - For the capture of TCP packets with the SYN
# header flag set directed at the external interface of
# the local host, the packet filter of '(dst IP) && (tcp
# [13] & 2 != 0)' is used where IP is the IP address of
# the external interface of the machine. For
# illustrative purposes, the IP address of 127.0.0.1 is
# used in this example.
my $filter;
Net::Pcap::compile(
$object,
\$filter,
'(port 111)',
0,
$netmask
) && die 'Unable to compile packet capture filter';
Net::Pcap::setfilter($object, $filter) &&
die 'Unable to set packet capture filter';
# Set callback function and initiate packet capture loop
Net::Pcap::loop($object, -1, \&process_packet, '') ||
die 'Unable to perform packet capture';
Net::Pcap::close($object);
sub process_packet {
my ($user_data, $hdr, $pkt) = #_;
my $ip_obj = NetPacket::IP->decode(eth_strip($pkt));
#print("$ip_obj->{src_ip} -> $ip_obj->{dest_ip} $ip_obj->{caplen}\n");
warn "packet!\n";
my %header = %$hdr;
#process_packet(\%header, $pkt);
my $len = length $pkt;
my $fag = length $user_data;
my $fag2 = length $hdr;
warn "$header{len} $header{caplen} $len $fag $fag2\n";
}
From "listening on eth1" I infer you're capturing on an Ethernet. The largest packet size on Ethernet is 1518 bytes (except for non-standard "jumbo frames"), which is:
14 bytes of Ethernet header;
1500 bytes of Ethernet payload;
4 bytes of frame check sequence at the end.
This means that (unless the network is using jumbo frames) the largest IP packet you can send on an Ethernet is 1500 bytes.
So, if you try to send 5000 bytes of data over UDP-over-IPv4 on an Ethernet, that will become a 5008-byte UDP packet when the 8-byte UDP header is added, and that will become a 5028-byte or larger IPv4 packet when the IPv4 header is added (the minimum size of an IPv4 header is 20 bytes, and it can be bigger if there are options in the packet). That's too big for Ethernet, so the IP layer in the protocol stack on your machine will "fragment" that packet into multiple smaller IP packets, and, if all of those fragments arrive at the destination machine, its IP layer will reassemble them into a larger IP packet and then hand the IP payload of the reassembled packet to the UDP layer, so the program receiving the UDP packet will see all 5000 bytes.
Your tcpdump output is the output for the first of the fragments; the IP-layer total length of the packet, extracted from the IP header, is 1500 (IP's length field includes the length of the IP headers and the payload), but the UDP-layer length, extracted from the UDP header (which will normally fit in the first fragment), is 5000.
This has nothing to do with the snapshot length; it has to do with the way IP works, and the maximum packet size on Ethernet.
Upon advice from the comments, I decided to try Net::Pcap::Easy instead of Net::Pcap. As stated in the pod for the former module: "Net::Pcap is awesome, but it's difficult to bootstrap".
The following code solves my problem:
use strict;
use warnings;
use Net::Pcap::Easy;
# all arguments to new are optoinal
my $npe = Net::Pcap::Easy->new(
dev => "eth1",
filter => "port 111",
packets_per_loop => 10,
bytes_to_capture => 1024,
timeout_in_ms => 0, # 0ms means forever
promiscuous => 0, # true or false
udp_callback => sub {
my ($npe, $ether, $ip, $udp, $header ) = #_;
print "UDP: $ip->{src_ip}:$udp->{src_port}"
. " -> $ip->{dest_ip}:$udp->{dest_port} $udp->{len}\n";
},
# tcp_callback => sub {
# my ($npe, $ether, $ip, $tcp, $header ) = #_;
# my $xmit = localtime( $header->{tv_sec} );
#
# print "$xmit TCP: $ip->{src_ip}:$tcp->{src_port}"
# . " -> $ip->{dest_ip}:$tcp->{dest_port}\n";
#
# },
#
# icmp_callback => sub {
# my ($npe, $ether, $ip, $icmp, $header ) = #_;
# my $xmit = localtime( $header->{tv_sec} );
#
# print "$xmit ICMP: $ether->{src_mac}:$ip->{src_ip}"
# . " -> $ether->{dest_mac}:$ip->{dest_ip}\n";
# },
);
1 while $npe->loop;

Pattern matching an array with specific start and end words/characters

Have some output in an array which I am trying to pull details from where the output begins with a specific word and ends with a specific word/character. This output is then to be printed to the screen.
The output in the array which I am working with is:
router rip
version 2
redistribute bgp 45134 metric 3
passive-interface Serial1/3:1.333
passive-interface Serial3/1:3.333
passive-interface Serial3/1:5.333
passive-interface Serial3/2:1.333
passive-interface Serial3/4:1.333
passive-interface Serial3/4:17.333
passive-interface Serial6/1:1.333
no auto-summary
!
address-family ipv4 vrf TestVRF-0001
redistribute bgp 45134 metric 3
network 10.0.0.0
no auto-summary
version 2
exit-address-family
!
The perl code I have generated so far is below:
elsif ( $action eq "show_vrf1" ) {
my $cmd = "show run | begin router rip";
my #lines = $s->cmd(String => $cmd,
Prompt => "/$enableprompt/",
Timeout => 10);
foreach my $line (#lines) {
if(/address-family ipv4 vrf TestVRF-0001.*?!/){
$result=$1;
print $result;
}
}
}
Which I am wanting to only pull the below out of the array:
address-family ipv4 vrf TestVRF-0001
redistribute bgp 45134 metric 3
network 10.0.0.0
no auto-summary
version 2
exit-address-family
!
For some reason when I run the script, I just get a blank screen with no data pulled from the array.
if($line =~ /address-family ipv4 vrf TestVRF-0001.*?!/){
instead of
if(/address-family ipv4 vrf TestVRF-0001.*?!/){
?
You match $line against the regular expression. The output you expect is not on one line, so no line can match it.
You can store the whole multiline string in a scalar:
my $output = join q(), $s->cmd(...);
And then, you can retrieve the output, if you use parentheses to really capture a part of the string:
if ($output =~ /(address-family ipv4 vrf TestVRF-0001.*?!)/s) {
my $result = $1;
Note that the /s modifier is needed to make dot match a newline, which it normaly does not.

perl Net::Telnet basics

As mentioned in the cpan documentation of Net::Telnet:
All output is flushed while all input is buffered. Each object contains its own input buffer.
Talking crudely, is it so that the command that I am sending is referred to as the output and the result as input as it is buffered?
I have the following code for sending commands and receiving the results.
sub sendCmd {
my $t = shift #_;
my $query = shift #_;
$t->buffer_empty;
print "Sending command $query to telnet target\n";
#out = $t->cmd(String => $query,Timeout => 70,
Errmode => 'return',Prompt => '/#/');
push(#out, ${$t->buffer});
$t->buffer_empty;
return #out;
}
The problem here is that if I have a loop of the following kind:
while(1)
{
#res1 = sendCmd('cmd1');
print #res1,"\n";
#res2 = sendCmd('cmd2');
print #res2,"\n";
}
This gives the expected alternating output for some time but after that :
problem 1:i observe after a while that - the result of cmd1 appears as the result for cmd2 and vice versa.
problem 2: the command may itself appear appended to the result.
Please help me with both these problems. Meanwhile I was thinking to revert to waitfor - print combination.
Thanks.