Wednesday, July 11, 2018

[Network] Converting IPv4 multicast into IPv6 multicast using Scapy

Introduction

This application is used for translating IPv4 multicast traffic into IPv6 multicast traffic. The application also translates IGMPv3 messages into IPv6 MLD equivalent messages.

To quickly test the application using a sample PCAP file as an input source, type in the following command (the igmpv3.pcap is included in the repo).
python ip_universe_converter.py -i igmpv3.pcap -s 10.11.12.0/24 -d fe80:0:0:0:0:0:0:0/64 --on eth0

The code can be found on Github: https://github.com/kiki-7/Ipv6MulticastConverter

Dependencies

The application is based on Python3. Therefore, one should ensure that Python3 is installed on the target environment before the application is used.
The application uses the following external libraries that need to be installed:
  • Scapy v2.4.0
The library can be installed using the following command:

pip install scapy

Input and output explanation

The application can both read and write network data from PCAP files. It can also sniff network packets on a specific interface and send the converted packets to a specific interface.

Since the input and output source ranges are different, the application enables the user to define the mapping of the IPv4 to IPv6 addresses via the -s and -d options. The -s option is the source IPv4 range, and the -d option represents the target IPv6 range. The application will create a mapping based on this input. For performance reasons, the mapping is done before the input source is read. Each IPv4 address is mapped into a free (previously un-mapped) IPv6 address in the specified range.
If a new IPv4 address is located that is not part of the predefined range, then it will me mapped according to the next free IPv6 address in the supplied range.

For example, the command below will read the network packets stored in PCAP, convert them and send them to the output interface (--on) eth0. The source IPv4 range is 10.11.12.0/24, while the target IPv6 range is fc00:baba::/64. 
ip_universe_converter.py -i vlc_multicast_igmp.pcapng -s 10.11.12.0/24 -d fc00:baba::/64 --on eth0

The following command reads the network data from an interface (eth0) and send it to another interface (eth1).
ip_universe_converter.py –-in eth0 -s 10.11.12.0/24 -d fc00:baba::/64 --on eth1

Classes used in the application

The application is built using several classes defined in Python3. The table below enumerated the classes used and summarizes their purpose.

Class
Script
Summary

ip_universe_converter.py
Contains the main method. Used to parse the command line arguments and initiate the packet translation process by invoking the appropriate classed.
InputHandler
inputHandler.py
This is an abstract class used to define an interface for various input related methods used in the application.
PcapInput
inputHandler.py
This is a concrete class which implements the InputHandler interface. The class is used to read PCAP files.
SniffInput
inputHandler.py
This is a concrete class which implements the InputHandler interface. The class is used to sniff packets on a specific interface.
SnifferThread
inputHandler.py
Used as a wrapper class for starting the Scapy network sniffer on a specific interface.
OutputHandler
outputHandler.py
This is an abstract class used to define an interface for various output related methods used in the application
PcapOutput
outputHandler.py
This is a concrete class which implements the OutputHandler interface. The class is used to write network packets into a PCAP file.
NetworkOutput
outputHandler.py
This is a concrete class which implements the OutputHandler interface. The class is used to send network packets on a specific interface.
IpAddressTranslation
ipTranslation.py
Implements the IPv4 to IPv6 mapping logic.
PacketTranslation
packetTranslation.py
Contains the main traffic translation logic. Iterated over an input source and translates IPv4 packets into IPv6 packets.

IP address mapping explanation
The IPv4 to IPv6 mapping is implemented in the PacketTranslation class located in the packetTranslation.py script. The handleTraffic method iterates over the input source one packet at a time. Only packets containing IGMPv3 messages and IPv4 multicast are processed, the rest are ignored. Scapy is used to detect the messages and its content.

IP address translation
Each IPv4 address is mapped to one IPv6 address. This mapping is stored in a dictionary defined within the IpAddressTranslation class located in the ipTranslation.py script. Before capturing the input sources, the application creates a mapping for every IPv4 defined through the -s command line option. If a new IPv4 address is found in the input packets, then the next unused IPV6 in the range (defined by -d option) is used.

IPv4 multicast to IPv6 translation
IPv4 multicast is detected using the IG bit in the Ethernet header. A multicast MAC address is distinguished by a binary '1' in the least significant bit of the first byte. All packets that have this bit set to '1' are treated as IPv4 multicast and are translated to IPv6, including their payload.

The translation is done using Scapy. The IPv4 layer of every packet is replaced with an equivalent IPv6 layer. The source and destination IP addresses are transformed as explained in the previous sections. The rest of the IPv6 header options are mapped as follows:

  • The hlim field is mapped to TTL
  • The nh field is mapped with the payload protocol number 
  • The tc field is mapped with to TOS field
IGMPv3 to MLD translation

IGMP to MLD translation is done for the IGMPv3 Membership Query and IGMPv3 Membership Report packets. 

For every IGMPv3 Membership Query packets a new packet is created using Scapy. The IPv4 to IPv6 translation is done the same way as for multicast packets (explained in the previous section). MLD is embedded within ICMPv6 packets, therefore the ICMPv6MLQuery2 Scapy class is used to create the MLD query. MLD packets have their maximum response time expressed in milliseconds, while IGMP packets has it displayed in seconds. The rest of the fields are similar, and therefore translated directly. 

IGMPv3 Membership Report packets contain a set of records (one or more) that indicate which hosts are trying to join or leave a multicast group. Every packet is transformed into a ICMPv6 equivalent packet. 

A more detailed explanation of the mapping required for IGMPv3 to MLD can be found in [1].

Useful references

[1] https://tools.ietf.org/html/draft-perreault-pim-igmp-mld-translation-00