Thursday 12 December 2013

Maintain that State...



Ankur :  Taking into consideration TCP ,we  have defined how the  mappings are maintained for TCP session ,once the session expires this mapping is removed from cache the entry.

Charitha: So we need to keep track of tcp states and a timer that tracks the remaining lifetime of the TCP session .Once the timer expires the dynamically created mapping is removed from the cache entry.


Ankur : Now to define the states 

 V6 INIT: An IPv6 packet containing a TCP SYN was received,translated, and forwarded by the  NAT64, implying that a TCP connection is being initiated from the IPv6 side. The NAT64 is
 now waiting for a matching IPv4 packet containing the TCP SYN in the opposite direction.
the opposite direction.

ESTABLISHED: Represents an open connection, with data able to flow in both directions.

V4 FIN RCV: An IPv4 packet containing a TCP FIN was received by the NAT64, data can still flow in the connection, and the NAT64 is waiting for a matching TCP FIN in the opposite direction.

V6 FIN RCV: An IPv6 packet containing a TCP FIN was received bythe NAT64, data can still flow in the connection, and the NAT64 is waiting for a matching TCP FIN in the opposite direction.

V6 FIN + V4 FIN RCV: Both an IPv4 packet containing a TCP FIN and an IPv6 packet containing an TCP FIN for this connection were received by the NAT64. The NAT64 keeps the connection state alive and forwards packets in both directions for a short period of time to allow remaining packets (in particular, the ACKs) to be delivered.

TRANS: The lifetime of the state for the connection is set to TCP_TRANS minutes either because a packet containing a TCP RST was received by the NAT64 for this connection or simply because the
lifetime of the connection has decreased and there are only TCP_TRANS minutes left. The NAT64 will keep the state for the connection for TCP_TRANS minutes, and if no other data packets for
that connection are received, the state for this connection is then terminated.

CLOSED: CLOSED is a fictional state because it represents the state when there is no state for this
particular cache entry, and therefore no connection.



Charitha :we need a state machine for TCP processing.It should be noted that there is one state machine per connection, so only packets belonging to a given connection are inputs to the state machine associated to that connection.








Thursday 7 November 2013

Walkthrough. Part 3

Getting to know finer details....end of Week 5


Ankur - RFCs are so difficult to read.

Charitha - The IPv6 - IPv4 packet translation that is implemented by tayga is according to the RFC 6145. It defines how the IP header is translated for ICMP, TCP and UDP packets.

Ankur - Now Time to define and move step by step about what we are going to do in the project

Charitha - Lets keep our goal simple initial work at tranport layer then move up the stack.

Ankur - so We need to map many IPv6 to one IPv4 system (in genral n to m mapping) Some how we need to maintain the mapping .Better way would be extracting the port number in tcp segment + IPv6 address –> mapped to new port number generated by us + IPv4 address

Charitha - Yup got it we maintain a list of values

Our Binding Information Base of IP addresses would look like this.

IPv6
Port
IPv4
New Port
2001:db8:1:ffff::1
12345
192.255.0.1
23456
2001:db8:1:ffff::3
80
192.255.0.1
34568
2001:db8:1:2010::1
80
192.255.0.1
27890


Ankur : exactly,We can have Port numbers included in the cache structure which currently now maintains one to one mapping.  

Walkthrough. Part 2

Getting to know finer details....end of Week 5

Charitha - Long time since we have updated the blog.

Ankur - Yes, analyzing the code, we totally forget about updating the blog.
C code is implemented here with great expertise. Even the simple list implementation uses Macros, which is quite interesting.

Charitha - Yes, saw through it.

#define list_entry(x, TYPE, FIELD) \
({ \
      const typeof( ((type *)0)->field ) *__mptr = (x); \
      (type *)( (char *)__mptr - offsetof(type, field) ); \
})

This gets a pointer to the object containing x of type TYPE. This is something new.

Ankur - Lets get back to where we stopped i.e read_from_tun(). Once the tun driver gets the packet, the stream is filled into "recv_buf" buffer. This stream is defined by structure below for IPv6, IPv4 and ICMP. 

     struct 
     {
            struct tun_pi pi;
            struct ip6 ip6;
            struct ip6_frag ip6_frag;
     } __attribute__ ((__packed__)) header;

   OR

   struct
   {
           struct tun_pi pi;
           struct ip4 ip4;
   } __attribute__ ((__packed__)) header;

  OR

  struct
   {
           struct tun_pi pi;
           struct ip4 ip4; or struct ip6 ip6;
           struct icmp icmp;
   } __attribute__ ((__packed__)) header;
         

Tun driver adds its own header to the packet received. Hence it has to be excluded while taking the packet for conversion. 

     data_len = ret - sizeof(struct tun_pi);
     where 
             struct tun_pi is the header Tun driver adds to the packet it receives. 
             ret = length of recv_buf.

After this, depending on the request, IPv4 or IPv6 handle function is called which gets the packet for manipulation.
      handle_ip6(struct pkt *) or  handle_ip4(struct pkt *) 
This is where all the parsing ,check summing, checking of TTL(time to live) and translation is taken care of by calling appropriate function.

Charitha - Great !! Now concentrating on the function xlate_4to6_data(struct pkt *) or xlate_6to4_data(struct pkt *), which does the main translation.
And what is  __attribute__ ((__packed__)) header? This is something new.

Ankur - Oh ya, as we know structure definition basically has padding embedded into it and hence sizeof will not always be the same sum member size. Well, "__attribute__ ((__packed__)" doesn't allow padding.

Charitha - Now moving on.
Above mentioned function creates a cache entry where the mapping of IPv4 and IPv6 addresses are stored. 

But as we know this project aims to make NAT64 stateful, we need to store some extra information about the mapping, which is the port number of TCP or UDP packet.

Ankur - Exactly, Next we will look at what needs to be done to accommodate port numbers as part of the mapping and how the translation happens.

Monday 14 October 2013

Walkthrough. Part 1


Getting to know finer details....end of Week 3


Ankur - I guess the most difficult thing to do is figuring out the code others have written.


Charitha - Yeah, I had a look at tayga implementation. It polls.


Ankur - Same here! Tayga is written in C. As I was looking through the code, it consists of 5 implementation files and few header files.
The "main" is in tayga.c file, which reads command line arguments and the configuration file parameters.


For eg: tayga --mkTUN to make a TUN driver
tayga --rmTUN to remove the TUN driver


Configuration file parameters
TUN-device nat64   # Name of the TUN driver
ipv4-addr 192.168.255.1 # Tayga’s IPv4 address
prefix 2001:db8:1:ffff::/96 # /96 prefix for IPv6 clients
dynamic-pool 192.168.255.0/24 # pool of assignable IPv4 addresses




Charitha - As I remember from our previous conversation, TUN interfaces are a feature offered by Linux that can do user space networking, allowing user space programs to see raw network traffic at IP level.


Ankur - Absolutely! You mentioned something about polling.


Charitha - Once the TUN driver is created, the program attaches to the TUN interface where it gets a special file descriptor. The program uses poll() to wait for some event on the file descriptor.


                  int poll(struct pollfd *fds, nfds_t nfds, int timeout);


Poll waits for one of a set of file descriptors to become ready to perform I/O. The file descriptor we are talking about here is the TUN fd.
Another set of fd which it keeps track of  is signals. These are user interrupt signals like SIGINT, SIGSTOP and also few other signals like SIGUSR1, SIGUSR2.


From description of TUN interface, we know that it sends both IPv4 and IPv6 packet.


Ankur - Yes So basically, the Program manipulates the IP packets(IPv4 to IPv6 and vice versa) and sends it back to the TUN interface.


Charitha - Exactly. Have a look at this function in tayga.c file.
    static void read_from_tun(void)
It reads the packets from TUN fd and forwards it for translation.


Ankur - Let me go and have a look at how the translation happens!

Saturday 21 September 2013

Intricacies in Simplicity

                                              
How does it work?....Week 1


Charitha - I thought stateful implementation of TAYGA was going to be easy..!


Ankur - I know, when i looked at the number of files in the source code, it seemed so less. But nevertheless, this is an important project considering the fast depletion of IPv4 addresses. Hopefully it will be useful to people.


Charitha - That is true. The current version of TAYGA, which currently supports stateless NAT64 implementation uses TUN driver to exchange packets with the kernel. TAYGA maps IPv6 address to IPv4 address. But this mapping is 1:1. All we need to do it make this mapping N:1.


Ankur - You mean N number of IPv6 addresses have a single IPv4 address associated with it?


Charitha - Yes. By the way how did you install and see its working?


Ankur - Aha..! I downloaded the source from the website and did a normal installation as specified in the ReadMe. Initially I wasn't sure about the mapping is actually made. But it turned out to be quite simple.


TAYGA first creates a NAT64 network interface.
sudo tayga --mktun


It directs set of IPv6 addresses to the network interface(NAT64). Lets say 2001:db8:1:ffff::/96(prefix). Also it has a pool of IPv4 addresses(192.168.255.0/24). So this is how it works.


If I ping to an address assigned to any network interface in the system, say 192.168.0.1, I need to ping from an IPv6 source to address 2001:db8:1:ffff::192.168.0.1 . TAYGA translates this packet to an IPv4 packet. It picks an IPv4 address from its pool(192.168.255.0/24) dynamically, unless specified statically in the config file and records this mapping.


Source IPv6 client  to 2001:db8:1:ffff::192.168.0.1
192.168.255.x to 192.168.0.1
Reverse order is used when sending packet back from IPv4 address to IPv6 address.


Look at this for instance.
The mapping done in TAYGA for the ping request : ping6 2001:db8:1:ffff::192.168.0.1



Charitha - Oh..! Does this mean that first and IPv6 client has to initiate the connection? And how did you see the functioning you just described?


Ankur - Yes, thats true. I used wireshark. The information was pretty detailed.




Ankur - But how do we plan to make it stateful?


Charitha - As you said, currently what TAYGA is doing is when you get a new hit from IPv6 network side it assigns a new IPv4 address from pool of IPv4 address .
The response from IPv4 network side is attached with the NAT64 IPv6 prefix to get a valid IPv6 address and this packet is sent IPv6 destination.
In brief How we could change this is when we get new request from IPv6
generate a port number attach IPv4 to it.The IPv6 packets from same source will go to same mapping.In case a new IPv6 request is encountered  a new port number is generated and same IPv4 is attached to it. We'll maintain this table in TAYGA. It is like multiplexing many IPv6 devices into a single IPv4 address.

Ankur - Time to dive into the code..!

Stateful implementation of NAT64


The Beginning....Week 0

What is NAT64? Why NAT64?

Lets answer why first! As we know IPv4 is 32 bits long address and it has an address range of 232 which is a total of 4,294,967,296 addresses. Due to expansion of network, setting up of huge data centers etc., IPv4 address will soon exhaust. Internet Assigned Numbers Authority (IANA) has given lot of thought on the current scenario and hence concept of migration to IPv6 has come into picture.

Well, where does NAT64 come in all this discussion going on? If you didn't realize most of our network is attached to IPv4 address space. With emerging of new network of IPv6 , intercommunication with older IPv4 systems will be a potential problem. Both IPv6 and IPv4 have entire different architecture  plus the translation isn't symmetric, i.e., IPv6 address space is a lot larger than IPv4 address space [read more]. This is where NAT64 comes to the rescue.

So What exactly is NAT64? NAT64 is address translation mechanism that facilitates IPv6 network to communicate with IPv4 network and vice-versa. TAYGA implements NAT64.
TAYGA! Now what's this?

TAYGA is stateless implementation of NAT64. It is a daemon that performs translation of packets between IPv4 and IPv6. TAYGA is coded in C language .

What is our role in this ?

As we know, TAYGA is a stateless implementation. What we plan to do as a part of our project is to make it stateful.

Ahh! Now what is the difference between TAYGA stateless and TAYGA stateful?

In brief, currently TAYGA is implemented in such a way that it performs transparent mapping ,that is 1 to 1 mapping. For every IPv6 it assigns an IPv4 address. To make it  Stateful, we are going to make N:1 mapping by maintaining the state via port number and IP address combination. Follow our blog to keep yourself posted.

Want to enhance further understanding, to dive in deeeeeeeeep refer to.
Want to try it out  practically ?
Download TAYGA source code from here.