[libvirt] [RFC] libvirt-TCK scripts to verify spoofing prevention

Gerhard Stenzel gstenzel at linux.vnet.ibm.com
Thu Apr 15 12:35:41 UTC 2010


The following patch mainly adds a set of test case to verify that
several spoofing attacks are prevented by the nwfilter subsystem.

In order to have a well defined test machine, the patch also includes
test scripts to network install a virtual disk from scratch, to boot the
virtual test machine prior to running the actual test scripts and to
shut it down afterwards.

While I have tried to remove as much dependency on my local setup as
possible there is still some left, so I am currently more interested in
feedback about the general approach, not necessarily actual inclusion
into the libvirt-TCK git.

For example, I am currently trying to find a suitable location for the
kickstart file, and also a suitable place for the common_functions.pl.

Comments are appreciated ... thanks,

Gerhard


Index: libvirt-tck/scripts/network/README
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/README
@@ -0,0 +1,14 @@
+
+Test cases:
+
+000-install-image.t		creates and install a 2GB fedora virtual disk via
kickstart file from the network
+001-boot-image.t		defines and boots a VM which uses the fedora virtual
disk
+100-ping-still-working.t	verifies the VM is pingable
+210-no-mac-spoofing.t		verifies mac spoofing is prevented
+220-no-ip-spoofing.t		verifies ip spoofing is prevented
+230-no-mac-broadcast.t		verifies mac broadcasting is prevented
+240-no-arp-spoofing.t		verifies arp spoofing is prevented
+999-shutdown-image.t		shuts the VM down
+
+
+
Index: libvirt-tck/scripts/network/000-install-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/000-install-image.t
@@ -0,0 +1,181 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/000-install-image.t - install network test image
+
+=head1 DESCRIPTION
+
+The test case creates and install a 2GB fedora virtual 
+disk via kickstart file from the network.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;
+
+use Sys::Virt::TCK;
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+# variables which may need to be adapted
+my $domain_name ="f12nwtest";
+my $disk_name = "/var/lib/libvirt/images/${domain_name}.img";
+my $disk_size = "2147483648";
+
+my $kickstart_file ="http://192.168.122.1/ks.cfg";
+my $cmdline = "ip=dhcp  gateway=192.168.122.1 ks=${kickstart_file}";
+
+# see if the domain already exits
+my $already_defined = 0;
+diag "searching if ${domain_name} is already defined";
+my $nnames = $conn->num_of_defined_domains();
+my @names = $conn->list_defined_domain_names($nnames);
+foreach (@names){
+    if (/${domain_name}/) {
+	print "$_ already exists, no need to redefine\n";
+	$already_defined = 1;
+    }
+}
+diag $already_defined;
+
+# check for installation disk and build it if not exists
+my $already_installed = 0;
+my $pool = $conn->get_storage_pool_by_name("default");
+my $nnames = $pool->num_of_storage_volumes();
+my @volNames = $pool->list_storage_vol_names($nnames);
+foreach (@volNames){
+    if (/${domain_name}/) {
+	print "$_ already exists, no need to install\n";
+	$already_installed = 1;
+    }
+}
+
+my $volumexml = "<volume>".
+"  <name>${domain_name}.img</name>".
+"  <key>${disk_name}</key>".
+"  <source>".
+"  </source>".
+"  <capacity>${disk_size}</capacity>".
+"  <allocation>4096</allocation>".
+"  <target>".
+"    <path>${disk_name}</path>".
+"    <format type='raw'/>".
+"    <permissions>".
+"      <mode>0644</mode>".
+"      <owner>0</owner>".
+"      <group>0</group>".
+"    </permissions>".
+"  </target>".
+"</volume>";
+
+
+# prepare image
+if ($already_installed == 0) {
+    diag "Creating ${disk_name}";
+    diag $volumexml;
+    my $vol = $pool->create_volume($volumexml)
+#    system("qemu-img create ${disk_name} ${disk_size}");
+}
+
+my $topxml = "  <name>${domain_name}</name>".
+"  <memory>524288</memory>".
+"  <currentMemory>524288</currentMemory>".
+"  <vcpu>1</vcpu>";
+
+my $osxml = "  <os>".
+"    <type arch='x86_64' machine='fedora-13'>hvm</type>".
+"    <kernel>/var/cache/libvirt-tck/os-i686-hvm/vmlinuz</kernel>".
+"    <initrd>/var/cache/libvirt-tck/os-i686-hvm/initrd</initrd>".
+"    <cmdline>${cmdline}</cmdline>".
+"    <boot dev='hd'/>".
+"  </os>";
+
+my $bottomxml = "  <features>".
+"    <acpi/>".
+"    <apic/>".
+"  </features>".
+"  <clock offset='utc'/>".
+"  <on_poweroff>destroy</on_poweroff>".
+"  <on_reboot>restart</on_reboot>".
+"  <on_crash>restart</on_crash>".
+"  <devices>".
+"    <emulator>/usr/bin/qemu-kvm</emulator>".
+"    <disk type='file' device='disk'>".
+"      <driver name='qemu' type='raw'/>".
+"      <source file='${disk_name}'/>".
+"      <target dev='hda' bus='ide'/>".
+"    </disk>".
+"    <controller type='ide' index='0'>".
+"    </controller>".
+"    <interface type='network'>".
+"      <source network='default'/>".
+"      <target dev='vnet0'/>".
+"      <model type='virtio'/>".
+"    </interface>".
+"    <serial type='pty'>".
+"      <target port='0'/>".
+"    </serial>".
+"    <console type='pty'>".
+"      <target port='0'/>".
+"    </console>".
+"    <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'
keymap='de'/>".
+"    <video>".
+"      <model type='cirrus' vram='9216' heads='1'/>".
+"    </video>".
+"  </devices>";
+
+my $xml = "<domain type='kvm'>" .
+$topxml.
+$osxml.
+$bottomxml.
+"</domain>";
+
+diag $xml;
+diag "Defining an inactive domain config";
+my $dom;
+
+# no need to start if already installed
+if (($already_installed == 0) && ($already_defined == 0)) {
+    ok_domain(sub { $dom = $conn->define_domain($xml) }, "defined
persistent domain config");
+    $xml = $dom->get_xml_description;
+    diag $xml;
+    diag "Starting inactive domain config";
+    $dom->create;
+
+    # wait for completion of installation
+    diag "wait for installation to finish .. ";
+    while($dom->is_active()) {
+	sleep(10);
+	diag ".. to view progress connect to virtual machine ${domain_name} ..
";
+    }
+    sleep(10);
+    diag " .. done";
+    # cleanup
+    $dom->undefine;
+} else {
+    ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
existing domain object";
+}
+
+
+
+
+
Index: libvirt-tck/scripts/network/001-boot-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/001-boot-image.t
@@ -0,0 +1,133 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/001-boot-image.t - boot installed test image
+
+=head1 DESCRIPTION
+
+The test case defines and boots a VM which uses the 
+fedora virtual disk create ny 000-install-image
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Sys::Virt::TCK;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+my $already_defined = 0;
+my $domain_name ="f12nwtest";
+
+# see if the domain already exits
+diag "searching if ${domain_name} is already defined";
+my $nnames = $conn->num_of_defined_domains();
+my @names = $conn->list_defined_domain_names($nnames);
+foreach (@names){
+    if (/${domain_name}/) {
+	print "$_ already exists, no need to redefine\n";
+	$already_defined = 1;
+    }
+}
+diag $already_defined;
+
+my $dom;
+my $xml;
+
+if ($already_defined == 1) {
+    ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
existing domain object";
+} else {
+    my $topxml = "  <name>${domain_name}</name>".
+	"  <memory>524288</memory>".
+	"  <currentMemory>524288</currentMemory>".
+	"  <vcpu>1</vcpu>";
+    
+    my $osxml = "  <os>".
+	"    <type arch='x86_64' machine='fedora-13'>hvm</type>".
+	"    <boot dev='hd'/>".
+	"  </os>";
+    
+    my $bottomxml = "  <features>".
+	"    <acpi/>".
+	"    <apic/>".
+	"  </features>".
+	"  <clock offset='utc'/>".
+	"  <on_poweroff>destroy</on_poweroff>".
+	"  <on_reboot>restart</on_reboot>".
+	"  <on_crash>restart</on_crash>".
+	"  <devices>".
+	"    <emulator>/usr/bin/qemu-kvm</emulator>".
+	"    <disk type='file' device='disk'>".
+	"      <driver name='qemu' type='raw'/>".
+	"      <source file='/var/lib/libvirt/images/${domain_name}.img'/>".
+	"      <target dev='hda' bus='ide'/>".
+	"    </disk>".
+	"    <controller type='ide' index='0'>".
+	"    </controller>".
+	"    <interface type='network'>".
+	"      <source network='default'/>".
+	"      <filterref filter='no-spoofing'/>".
+	"      <target dev='vnet0'/>".
+	"      <model type='virtio'/>".
+	"    </interface>".
+	"    <serial type='pty'>".
+	"      <target port='0'/>".
+	"    </serial>".
+	"    <console type='pty'>".
+	"      <target port='0'/>".
+	"    </console>".
+	"    <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'
keymap='de'/>".
+	"    <video>".
+	"      <model type='cirrus' vram='9216' heads='1'/>".
+	"    </video>".
+	"  </devices>";
+    
+    $xml = "<domain type='kvm'>" .
+	$topxml.
+	$osxml.
+	$bottomxml.
+	"</domain>";
+
+    diag $xml;
+    diag "Defining an inactive domain config";
+    ok_domain(sub { $dom = $conn->define_domain($xml) }, "defined
persistent domain config");
+}
+
+# already existing or newly defined, start it up 
+$dom->create;
+my $uuid = $dom->get_uuid_string();
+diag $uuid;
+$xml = $dom->get_xml_description();
+diag $xml;
+ok($dom->get_id() > 0, "running domain has an ID > 0");
+
+my $mac = get_macaddress($xml);
+diag $mac;
+# wait for guest to boot and request dhcp
+sleep(20);
+my $ip = get_ip_from_leases($mac);
+diag "ip is $ip";
+
Index: libvirt-tck/scripts/network/100-ping-still-working.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/100-ping-still-working.t
@@ -0,0 +1,71 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/100-ping-still-working.t - verify machines can be pinged from
host
+
+=head1 DESCRIPTION
+
+The test case validates that it is possible to ping a guest machine
from
+the host.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+my $xml = $dom1->get_xml_description;
+diag $xml;
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $mac1 = get_macaddress($xml);
+diag $mac1;
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# ping guest1
+my $ping1 = `ping -c 10 $guestip1`;
+diag $ping1;
+ok($ping1 =~ "10 received", "ping $guestip1 test");
+
+exit 0;
Index: libvirt-tck/scripts/network/210-no-mac-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/210-no-mac-spoofing.t
@@ -0,0 +1,113 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/210-no-mac-spoofing.t - verify MAC spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that MAC spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 5;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $domain_name ="f12nwtest";
+my $dom1;
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# wait for guest to boot
+diag "waiting for guests to boot";
+#system("sleep 20");
+diag "done";
+
+# ping guest1 first nic
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+my $gateway = "192.168.122.1";
+my $macfalse = "52:54:00:f9:21:22";
+my $ping1 = `ping -c 10 $guestip1`;
+diag $ping1;
+ok($ping1 =~ "10 received", "ping $guestip1 test");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now bring eth0 down, change MAC and bring it up again
+diag "fiddling with mac";
+my $cmdfile = "echo '" . 
+    "/sbin/ifconfig eth0\n".
+    "/sbin/ifconfig eth0 down\n".
+    "/sbin/ifconfig eth0 hw ether ${macfalse}\n".
+    "/sbin/ifconfig eth0 up\n".
+    "/sbin/ifconfig eth0\n".
+    "ping -c 10 ${gateway}\n".
+    "/sbin/ifconfig eth0 down\n".
+    "/sbin/ifconfig eth0 hw ether ${mac1}\n".
+    "/sbin/ifconfig eth0 up\n".
+    "/sbin/ifconfig eth0\n".
+    "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit)  = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("cat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+ok($stdout =~ "100% packet loss", "packet loss expected");
+
+exit 0;
Index: libvirt-tck/scripts/network/230-no-mac-broadcast.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/230-no-mac-broadcast.t
@@ -0,0 +1,102 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/230-no-mac-broadcast.t - verify MAC broadcasts are prevented
+
+=head1 DESCRIPTION
+
+The test case validates that MAC broadcasts are prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $dom1;
+ok_domain { $dom1 = $conn->get_domain_by_name("f12nwtest") } "the
running domain object";
+
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# prepare tcpdump
+diag "prepare tcpdump";
+system("/usr/sbin/tcpdump -v -i virbr0 -n host 255.255.255.255
2> /tmp/tcpdump.log &");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now generate a mac broadcast paket 
+diag "generate mac broadcast";
+my $cmdfile = "echo '" . 
+    "/bin/ping -c 1 192.168.122.255 -b\n".
+    "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit)  = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("cat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+
+# now stop tcpdump and verify result
+diag "stopping tcpdump";
+system("kill -15 `/sbin/pidof tcpdump`");
+my $tcpdumplog = `cat /tmp/tcpdump.log`;
+diag($tcpdumplog);
+ok($tcpdumplog =~ "0 packets captured", "tcpdump expected to capture no
packets");
+
+exit 0;
Index: libvirt-tck/scripts/network/240-no-arp-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/240-no-arp-spoofing.t
@@ -0,0 +1,111 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/240-no-arp-spoofing.t - verify ARP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that ARP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $spoofid = "192.168.122.183";
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# looking up domain
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# check if mac address is listed
+ok($ebtable1 =~ "$guestip1", "check ebtables entry");
+
+# prepare tcpdump
+diag "prepare tcpdump";
+system("/usr/sbin/tcpdump -v -i virbr0 not ip  > /tmp/tcpdump.log &");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now generate a arp spoofing packets 
+diag "generate arpspoof";
+my $cmdfile = "echo '" . 
+    "/usr/bin/yum -y install dsniff\n".
+    "/usr/sbin/arpspoof ${spoofid} &\n".
+    "/bin/sleep 10\n".
+    "kill -15 `/sbin/pidof arpspoof`\n".
+    "' > /test.sh";
+diag "content of cmdfile:";
+diag $cmdfile;
+diag "creating cmdfile";
+my ($stdout, $stderr, $exit)  = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "excuting cmdfile";
+($stdout, $stderr, $exit)  = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("echo test.log\ncat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+
+# now stop tcpdump and verify result
+diag "stopping tcpdump";
+system("kill -15 `/sbin/pidof tcpdump`");
+diag "tcpdump.log:";
+my $tcpdumplog = `cat /tmp/tcpdump.log`;
+diag($tcpdumplog);
+ok($tcpdumplog !~ "${spoofid} is-at", "tcpdump expected to capture no
arp reply packets");
+
+exit 0;
Index: libvirt-tck/scripts/network/220-no-ip-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/220-no-ip-spoofing.t
@@ -0,0 +1,101 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/220-no-ip-spoofing.t - verify IP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that IP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# looking up domain
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# check if IP address is listed
+ok($ebtable1 =~ "$guestip1", "check ebtables entry");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now bring eth0 down, change IP and bring it up again
+diag "preparing ip spoof";
+my $cmdfile = "echo '" . 
+    "/bin/sleep 1\n".
+    "/sbin/ifconfig eth0\n".
+    "/sbin/ifconfig eth0 down\n".
+    "/sbin/ifconfig eth0 192.168.122.183 netmask 255.255.255.0 up\n".
+    "/sbin/ifconfig eth0\n".
+    "/bin/sleep 1\n".
+    "/bin/ping -c 1 192.168.122.1\n".
+    "/sbin/ifconfig eth0 down\n".
+    "/sbin/ifconfig eth0 ${guestip1} netmask 255.255.255.0 up\n".
+    "/sbin/ifconfig eth0 \n".
+    "/bin/sleep 1\n".
+    "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit)  = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit)  = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "running ip spoof";
+($stdout, $stderr, $exit)  = $ssh->cmd("/test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "checking result";
+ok($stdout =~ "100% packet loss", "packet loss expected");
+
+exit 0;
Index: libvirt-tck/scripts/network/999-shutdown-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/999-shutdown-image.t
@@ -0,0 +1,59 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/240-no-arp-spoofing.t - verify ARP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that ARP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+    $tck->cleanup if $tck;
+}
+
+# find domain
+my $domain_name = "f12nwtest";
+diag "Trying domain lookup by name";
+my $dom;
+ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom->get_id() > 0, "running domain has an ID > 0");
+
+# cleanup guest
+diag "cleaning up";
+$dom->shutdown();
+    while($dom->is_active()) {
+	sleep(1);
+	diag ".. waiting for virtual machine ${domain_name} to shutdown.. ";
+    }
+#$dom->undefine();
+
+exit 0;
Index: libvirt-tck/scripts/network/common_functions.pl
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/common_functions.pl
@@ -0,0 +1,35 @@
+use utf8;
+#no utf8;
+
+sub get_macaddress {
+    my $xmldesc = shift;
+
+    my $mac;
+    my $parser = XML::LibXML->new();
+
+    my $doc = $parser->parse_string($xmldesc);
+
+    my $rootel = $doc -> getDocumentElement();
+
+    my @devices = $rootel->getChildrenByTagName("devices");
+    foreach my $device(@devices) {
+	my @interfaces = $device->getChildrenByTagName("interface");
+	foreach my $interface(@interfaces) {
+	    my @targets = $interface->getChildrenByTagName("mac");
+	    foreach my $target(@targets) {
+		$mac = $target->getAttribute("address");
+	    }
+	}
+    }
+    utf8::decode($mac);
+    return $mac;
+}
+
+sub get_ip_from_leases{
+    my $mac = shift;
+    my $tmp = `grep $mac /var/lib/dnsmasq/dnsmasq.leases`;
+    my @fields = split(/ /, $tmp);
+    my $ip = $fields[2];
+    return $ip;
+}
+1;

-- 
Best regards, 

Gerhard Stenzel, 
-----------------------------------------------------------------------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294




More information about the libvir-list mailing list