Sunday, 6 December 2009
Juletip 6: Vi bygger IPv6 pakker med PCS
« Juletip 5: Vi bygger pakker | Main | Juletip 7: Vi sender sender sender pakker pakker pakker »Dagen idag bliver lidt kortere, men forhåbentlig så mere fokuseret :-)
Målet idag er således at vise hvordan man bygger IPv6 pakker med PCS som vi igår brugte til IPv4 pakker.
Til at starte med er det relativt nemt at ændre lidt imports, som man ligeledes skal opdatere hvis det er andre typer pakker man vil sende:
from pcs.packets.ethernet import ethernet from pcs.packets.ipv6 import * from pcs.packets.icmpv6 import * from pcs import *
Tilsvarende ændrer man selvfølgelig til IPv6 på Ethernet niveau og på IPv6 niveau:
ip6 = ipv6() ip6.traffic_class = 0 ip6.flow = 0 ip6.length = 0 ip6.next_header = 0x3a ip6.hop = 255 ip6.src = inet_pton(AF_INET6, "2001:16d8:dd0f:cf0f:223:6cff:fe9a:f52c") ip6.dst = inet_pton(AF_INET6, "2001:16d8:dd0f:cf0f:240:63ff:fec9:f311") print ip6
Men husk der er nogle andre felter i en IPv6 pakke:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Traffic Class | Flow Label | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | Next Header | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Source Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Destination Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Disse felter i pakken er således defineret og der er nogle interessante observationer. Den første er at headeren IKKE behøver noget padding, der er færre felter og adresserne er 4 gange så store. Det med at headeren har et fast format burde gøre det nemmere at afkode i hardware og med færre felter, hvoraf en del er indenfor de første 64-bit burde ligeledes optimere behandlingen af IPv6 og medføre flere pakker per sekund.
Version er 4-bit og burde vel være 6? Men ligesom med IPv4 har man glemt at skrive at der rent faktisk skal checkes for dette.
Traffic class svarer til Type of Service fra IPv4 og giver mulighed for at identificere og skelne mellem forskellige prioriteter for IPv6 pakkerne.
Flow label kan bruges af en afsender til pakker som skal have speciel behandling af IPv6 routere, eksempelvis ikke-standard quality of service eller "real-time" service.
Payload Length er længden af pakken efter headeren - inklusiv eventuelle andre headere.
Next Header er en nyt ting i IPv6, flere headere på IP niveau. Denne feature gør 1) IPv6 headeren har en konstant størrelse og er den som routere typisk vil se på, med afsender og modtager 2) der kan udvides med ny funktionalitet sidenhen. Der er defineret et antal headere - men det vil vi ikke gennemgå idag.
Hop limit er helt tilsvarende Time to Live fra IPv4 og er en tæller som angiver hvor mange hops en pakke må sendes over, før den eventuelt smides væk. Det sikrer at hvis der er routing loops så fjernes pakken når denne tæller rammer 0.
Source og Destination er ligesom på IPv4 naturligvis afsender og modtager - men der er jo ingen garantier for at det er den rigtige afsender, man kan således spoofe afsender adresser, hvorfor man har defineret IPsec OG gode internetudbydere bør implementere både ingress og egress filtering af trafik. IPv6 adresserne er 128-bit og der har været meget snak om det kæmpe adresserum - selvom det ikke er eneste ændring fra IPv4.
ICMPv6 ECHO test program
Godt så lad os se på ICMPv6 test programmet, som er modificeret fra eksemplet igår:
#!/usr/bin/env python
# Copyright (c) 2006, Neville-Neil Consulting
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Neville-Neil Consulting nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# File: $Id: icmpv4test.py,v 1.8 2006/09/05 07:30:56 gnn Exp $
#
# Author: George V. Neville-Neil
#
# Description: This module performs a self test on the IPv4 packet.
# That is to say it first encodes a packet, then decodes it and makes
# sure that the data matches.
import sys
if "-l" in sys.argv:
sys.path.insert(0, "../") # Look locally first
sys.argv.remove("-l") # Needed because unittest has issues
from pcs.packets.ethernet import ethernet
from pcs.packets.ipv6 import *
from pcs.packets.icmpv6 import *
from pcs import *
class hlktest():
def test_icmpv6_ping(self):
import os
uname = os.uname()[0]
if uname == "FreeBSD":
devname = "edsc0"
elif uname == "Linux":
devname = "lo"
elif uname == "Darwin":
print "Found Darwin"
devname = "en1"
else:
print "unknown host os %s" % uname
return
e = ethernet()
e.src = "\x00\x23\x6c\x9a\xf5\x2c"
e.dst = "\x00\x40\x63\xc9\xf3\x11"
e.type = 0x86dd
print e
ip6 = ipv6()
ip6.traffic_class = 0
ip6.flow = 0
ip6.length = 0
ip6.next_header = 0x3a
ip6.hop = 255
ip6.src = inet_pton(AF_INET6, "2001:16d8:dd0f:cf0f:223:6cff:fe9a:f52c")
ip6.dst = inet_pton(AF_INET6, "2001:16d8:dd0f:cf0f:240:63ff:fec9:f311")
print ip6
icmp6 = icmpv6(ICMP6_ECHO_REQUEST)
icmp6.type = 128
icmp6.code = 0
icmp6.cksum = 0
icmp6.id=0xa03b
icmp6.sequence=0x00
# icmp6.checksum = icmp6.cksum(icmp6) & 0xffff
icmp6.checksum = 0x5e8a
print icmp6
ip6.length = len(icmp6.bytes)# note that IPv6 payload length is PAYLOAD only
print ip6.length
packet = Chain([e, ip6, icmp6])
packet.encode()
output = PcapConnector(devname)
n_out = output.write(packet.bytes, len (packet.bytes))
print n_out
hlk = hlktest()
hlk.test_icmpv6_ping()
og ligesom igår kan det betale sig at downloade det :-)
Der er nogle ting der er anderledes, eksempelvis Payload length som nu kun er for indholdet efter IPv6 header, dvs ip6.length er kun icmp6.bytes. Jeg havde ligeledes lidt bøvl med checksummerne, så jeg kørte programmet og Wireshark var så flink at fortælle hvad checksum burde have været :-) Der mangler også at angive nogle bytes til data delen - men det må så være jeres opgave :-) (Jeg opdaterer senere hvis jeg løser det, jeg lærer jo også! )
Run the program
Men programmet køres ligesom igår, inkl debug info og giver resulatet som ses i Wireshark:
hlk@bigfoot:hlk$ sudo python icmpv6test-hlk.py Found Darwin Ethernet dst: 0:40:63:c9:f3:11 src: 0:23:6c:9a:f5:2c type: 0x86dd version 6 traffic_class 0 flow 0 length 0 next_header 58 hop 255 src 2001:16d8:dd0f:cf0f:223:6cff:fe9a:f52c dst 2001:16d8:dd0f:cf0f:240:63ff:fec9:f311 type 128 code 0 checksum 24202 id 41019 sequence 0 8 62 hlk@bigfoot:hlk$
Det var alt for idag :-)
PS undervejs da jeg havde problemer stødte jeg på følgende program ICMPv6 ECHO program skrevet med PCS, som dog ikke virker 100% http://sources.zabbadoz.net/ipv6/CSCsd13298/
Posted by at CET 10:12 06/12/2009 in Toolbox entries
[Trackback URL for this entry]

