master-thesis/doc/Background.tex
2019-08-19 17:50:00 +02:00

491 lines
26 KiB
TeX

\chapter{\label{background}Background}
In this chapter we describe the key technologies involved and their
relation to our work.
% ----------------------------------------------------------------------
\section{\label{background:p4}P4}
P4 is a programming language designed to program inside network
equipment. It's main features are protocol and target independence.
The \textit{protocol independence} refers to the separation of concerns in
terms of language and protocols: P4, generally speaking, operates on
bits that are parsed and then accessible in the self defined
structures called headers. The general flow can be seen in
figure \ref{fig:p4fromnsg}: a parser parses the incoming packet and
prepares it for processing in the switching logic. Afterwards the
packets are output and deparsing of the parsed data might follow.
In the context of NAT64 this is a very important feature: while the
parser will read and parse in the ingress pipeline one protocol
(f.i. IPv6), the deparser will output a different protocol (f.i. IPv4).
\begin{figure}[h]
\includegraphics[scale=0.9]{p4-from-nsg}
\centering
\caption{P4 protocol independence~\cite{vanbever:_progr_networ_data_planes}}
\label{fig:p4fromnsg}
\end{figure}
The \textit{target independence} is the second very powerful feature
of P4: it allows code to be compiled to different targets. While in
theory the P4 code should be completely target independent, in reality
there are some modifications needed on a per-target basis and each
target faces different restrictions. The challenges arising from this
are discussed in section \ref{results:p4}.
As opposed to general purpose programming languages, P4 lacks some
features. Most notably loops, floating point operations and
modulo operations.
However within its constraints, P4 can guarantee
operation at line speed, which general purpose programming languages
cannot guarantee and also fail to achieve in reality
(see section \ref{results:softwarenat64} for details).
% ok
% ----------------------------------------------------------------------
\section{\label{background:ip}IPv6, IPv4 and Ethernet}
The first IPv6 RFC was published in 1998~\cite{rfc2460}. Both IPv4 and
IPv4 operate on layer 3 of the OSI model. In this thesis we only
consider transmission via Ethernet, which operates at
layer 2. Inside the Ethernet frame a field named ``type'' specifies
the higher level protocol identifier.\footnote{
0x0800 for IPv4~\cite{rfc894} and 0x86DD for IPv6~\cite{rfc2464}.}
This is important, because
Ethernet can only reference one protocol, which makes IPv4 and IPv6
mutually exclusive.
The figures \ref{fig:ipv4header} and \ref{fig:ipv6header} show the
packet headers of IPv4 and IPv6. The most notable differences between
the two protocols for this thesis are:
\begin{itemize}
\item Different address lengths
\begin{itemize}
\item IPv4: 32 bit
\item IPv6: 128 bit
\end{itemize}
\item Lack of a checksum in IPv6
\item Format of Pseudo headers (see section \ref{background:checksums})
\end{itemize}
% ----------------------------------------------------------------------
\section{\label{background:arpndp}ARP and NDP, ICMP and ICMP6}
While IPv6 and IPv4 are primarily used as a ``shell'' to support
addressing for protocols that have no or limited addressing support
(like TCP or UDP), protocols like ARP~\cite{rfc826} and
NDP~\cite{rfc4861} provide support for resolving IPv6 and IPv4
addresses to hardware (MAC) addresses. While both ARP and NDP are only
used prior to establishing a connection on and their results are
cached, their availability is crucial for operating a switch.
Figure \ref{fig:arpndp} illustrates a typical address resolution process.
\begin{figure}[h]
\includegraphics[scale=0.3]{arp-ndp}
\centering
\caption{ARP and NDP}
\label{fig:arpndp}
\end{figure}
The major difference between ARP and NDP in relation to P4 are
\begin{itemize}
\item ARP is a separate protocol on the same layer as IPv6 and IPv4,
\item NDP operates below ICMP6 which operates below IPv6,
\item NDP contains checksums over payload,
\item and NDP in ICMP6 contains optional, non referenced option fields
(specifically: ICMP6 link layer address option).
\end{itemize}
ARP is required to be a separate protocol, because IPv4 hosts don't
know how to communicate with each other yet, because they don't have a
way to communicate to the target IPv4 address (``The chicken and the
egg problem'').
NDP on the other hand already works within IPv6, as every IPv6 host is
required to have a self-assigned link local IPv6 address from the
range \texttt{fe80::/10} (compare RFC4291~\cite{rfc4291}). NDP also
does not require broadcast communication, because hosts automatically
join multicast groups that embed parts of their
IPv6 addresses~\cite{rfc2710},~\cite{wikipedia:_solic}. This way the
collision domain is significantly reduced in IPv6, compared to IPv4.
As seen later in this document (compare
section \ref{results:netpfga:features}), the requirement to generate checksums
over payload poses difficult problems for some hardware targets. Even
more difficult is the use of options within ICMP6. Figure shows a
typical layout of a neighbor advertisement messages.
\begin{figure}[h]
\includegraphics[scale=0.3]{icmp6ndp}
\centering
\caption{ICMP6 option fields}
\label{fig:icmp6ndp}
\end{figure}
The problem arises from the layout of the options, as seen in the
following quote and in figure \ref{icmp6ndp}:
\begin{quote}
``Neighbor Discovery messages include zero or more options, some of
which may appear multiple times in the same message. Options should
be padded when necessary to ensure that they end on their natural
64-bit boundaries''.\footnote{Quote from \cite{rfc4861}.}
\end{quote}
ICMP6 and ICMP are primarily used to signal errors in
communication. Specifically signalling that a packet is too big to
pass a certain link and needs fragmentation is a common functionality
of both protocols. For a host (or switch) to be able to emit ICMP6 and
ICMP messages, the host requires a valid IPv6 / IPv4 address.
Without ICMP6 / ICMP support path MTU
discovery~\cite{rfc1191},~\cite{rfc8201}
does not work and the sender needs to determine
different ways of finding out the maximum MTU on the path.
% ok -- need to separate backgroun and results
% ----------------------------------------------------------------------
\section{\label{background:transition}IPv6 Translation Mechanisms}
While in this thesis the focus was in NAT64 as a translation mechanism,
there are a variety of different approaches, some of which we would
like to portray here.
% ----------------------------------------------------------------------
\subsection{\label{background:transition:stateless}Stateless NAT64}
Stateless NAT64 describes static mappings between IPv6 and IPv4
addresses. This can be based on longest prefix matchings (LPM),
ranges, bitmasks or individual entries.
NAT64 translations as described in this thesis modify multiple layers
in the translation process:
\begin{itemize}
\item Ethernet (changing the type field)
\item IPv4 / IPv6 (changing the protocol, changing the fields)
\item TCP/UDP/ICMP/ICMP6 checksums
\end{itemize}
Figures \ref{fig:ipv6header} and \ref{fig:ipv4header} show the headers
of IPv4 and IPv6. As can be seen in the diagrams not only are the
addresses of different size, but fields have also been changed or
removed when the version changed. Depending on the NAT64
translation direction, a translator will need to re-arrange fields to
a different position, remove fields and add fields.
\begin{figure}[h]
\begin{verbatim}
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Source Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Destination Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\end{verbatim}
\centering
\caption{IPv6 Header~\cite{rfc2460}}
\label{fig:ipv6header}
\end{figure}
% ----------------------------------------------------------------------
\subsection{\label{background:transition:statefulnat64}Stateful NAT64}
Stateful NAT64 as defined in RFC6146~\cite{rfc6146} defines how to
cretate 1:n mappings between IPv6 and IPv4 hosts. The motivation for
stateful NAT64 is similar to stateful NAT44~\cite{rfc3022}: it allows
translating many IPv6 addresses to one IPv4 address. While the
opposite translation is also technically possible, the differences in
address space don't justify its use in general.
\begin{figure}[h]
\begin{verbatim}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\end{verbatim}
\caption{IPv4 Header~\cite{rfc791}}
\label{fig:ipv4header}
\end{figure}
Stateful NAT64 in particular uses information in higher level
protocols to multiplex connections: Given one IPv4 address and the tcp
protocol, outgoing connections from IPv6 hosts can dynamically mapped
to the range of possible tcp ports. After a session is closed, the
port can be reused again.
\begin{figure}[h]
\includegraphics[scale=0.5]{statefulnat64}
\centering
\caption{Stateful NAT64}
\label{fig:statefulnat64}
\end{figure}
The selection of mapped ports is usually based on the availability on
the IPv4 side and not related to the original port. To support
stateful NAT64, the translator needs to store the mapping in a table and
purge entries regularly.
Stateful NAT64 usually uses information found in protocols at layer 4
like TCP~\cite{rfc793} or UDP~\cite{rfc768}. However it can also
support ICMP~\cite{rfc792} and ICMP6~\cite{rfc4443}.
% ----------------------------------------------------------------------
\subsection{\label{background:transition:Protocol dependent}Higher
Layer Protocol Dependent Translation}
Further translation can be achieved by using information in higher
level protocols like HTTP~\cite{rfc2616} or TLS~\cite{rfc4366}.
Application proxies like
nginx~\cite{nginx:_nginx_high_perfor_load_balan}
use layer 7 protocol
information to proxy towards backends. Within this proxying method,
the underlying IP protocol can be changed from IPv6 to IPv4 and vice
versa. However the requested hostname that is usually used for
selecting the backend is encrypted in TLS 1.3~\cite{rfc8446}, which
poses a challenge for implementations.
While protocol dependent translation has the highest amount of
information to choose from for translation, complex parsers or even
cryptographic methods are required for it. That reduces the
opportunities of protocol dependent translation
% ----------------------------------------------------------------------
\subsection{\label{background:transition:prefixnat}Mapping IPv4
Addresses in IPv6}
As described in section \ref{background:ip}, one of the major
differences between IPv6 and IPv4 is the address length. As the whole
IPv4 Internet can be represented in only 32 bits, it is a common
practice to assign an IPv6 prefix for IPv6 hosts that represents a
mapping to the IPv4 Internet. In RFC6052~\cite{rfc6502} the well
known prefix \textit{64:ff9b::/96} is defined. One possibility to map
an IPv4 address into the prefix is by adding its integer value to the
prefix, treating it like an offset. In figure \ref{fig:ipv4embed}
we show an example python code of how this can be done.
\begin{figure}[h]
\begin{verbatim}
>>> import ipaddress
>>> prefix=ipaddress.IPv6Network("64:ff9b::/96")
>>> ipv4address=ipaddress.IPv4Address("192.0.2.0")
>>> int(ipv4address)
3221225984
>>> hex(3221225984)
'0xc0000200'
>>> prefix[int(ipv4address)]
IPv6Address('64:ff9b::c000:200')
\end{verbatim}
\centering
\caption{Representing an IPv4 address in an IPv6 prefix}
\label{fig:ipv4embed}
\end{figure}
Network administrators can choose to use either the well known prefix
or to use a network block of their own to map the
Internet.\footnote{For instance
2a0a:e5c0:0:1::/96~\cite{ungleich:networkinfrastructure}.}
While a /96 prefix seems a natural selection (it provides exactly 32 bit),
other prefix lengths are defined in RFC6052 (see figure
\ref{fig:prefixlen}) that allow flexible embedding of the IPv4 address.
\begin{figure}[h]
\begin{verbatim}
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|32| prefix |v4(32) | u | suffix |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|40| prefix |v4(24) | u |(8)| suffix |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|48| prefix |v4(16) | u | (16) | suffix |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|56| prefix |(8)| u | v4(24) | suffix |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|64| prefix | u | v4(32) | suffix |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|96| prefix | v4(32) |
+--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
\end{verbatim}
\centering
\caption{IPv4 embedding depending on the prefix length}
\label{fig:prefixlen}
\end{figure}
RFC6146, which describes stateful NAT64, states that
``IPv4 addresses of IPv4 hosts are algorithmically
translated to and from IPv6 addresses by using the algorithm defined
in [RFC6052]''~\cite{rfc6146} While this sentencen does not use the
typical RFC keywords like SHALL, REQUIRED, etc.~\cite{rfc2119}, we
interpret this sentence in the meaning of ``a stateful NAT64
translator SHALL implement IPv4 address embedding as described in the
algorithm of RFC6052''.
% ----------------------------------------------------------------------
\subsection{\label{background:transition:dns64}DNS64}
Tightly related to NAT64 is a technology known as
DNS64~\cite{rfc6174}. DNS64 tries to solve the problem of addressing
IPv4 only hosts from IPv6 only hosts
by adding a ``fake'' IPv6 (AAAA) DNS resource record, as shown in
figure \ref{fig:dns64}.
\begin{figure}[h]
\includegraphics[scale=0.4]{dns64}
\centering
\caption{Illustration of DNS64}
\label{fig:dns64}
\end{figure}
The DNS64 DNS server will query the authorative DNS server for an AAAA
record. However as the host \textit{ipv4onlyhost.example.com} is only
reachable by IPv4, it also only has an A entry. After receiving the
answer that there is no AAAA record, the DNS64 server will ask for an
A record and gets an answer that the name
\textit{ipv4onlyhost.example.com} resolves to the IPv4 address
\textit{192.0.2.0}. The DNS64 server then embeds the IPv4 address in
the configured IPv6 prefix (\textit{64:ff9b::/96} in this case) and
returns a fake AAAA record to the IPv6 only host. The IPv6 only host
then will use address to connect to. The NAT64 translator recognises
either that the address is part of a configured prefix or that it has
a dedicated table entry for mapping this IPv6 address to an IPv4
address and translates it accordingly.
% ----------------------------------------------------------------------
\section{\label{background:checksums}Protocol Checksums}
One challenge for translating IPv6-IPv4 are checksums of higher level
protocols like TCP and UDP that incorporate information from the lower
level protocols. The pseudo header for upper layer protocols for
IPv6 is defined in RFC2460~\cite{rfc2460} and shown in figure
\ref{fig:ipv6pseudoheader}, the IPv4 pseudo header for TCP and UDP are
defined in RFC768 and RFC793 and are shown in \ref{fig:ipv4pseudoheader}.
\begin{figure}[h]
\begin{verbatim}
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Source Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Destination Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Upper-Layer Packet Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| zero | Next Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\end{verbatim}
\centering
\caption{IPv6 Pseudo Header}
\label{fig:ipv6pseudoheader}
\end{figure}
When translating, the checksum fields in the higher protocols need to be
adjusted. The checksums for TCP and UDP is calculated not only over the pseudo
headers, but also contain the payload of the packet. This is
important, because some targets (like the NetPFGA) do not allow to
access the payload (see section \ref{design:netpfga}).
\begin{figure}[h]
\begin{verbatim}
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source address |
+--------+--------+--------+--------+
| destination address |
+--------+--------+--------+--------+
| zero |protocol| TCP/UDP length |
+--------+--------+--------+--------+
\end{verbatim}
\centering
\caption{IPv4 Pseudo Header}
\label{fig:ipv4pseudoheader}
\end{figure}
The checksums for IPv4, TCP, UDP and ICMP6 are all based on the
``Internet Checksum''~\cite{rfc791},~\cite{rfc1071}.
Its calculation can be summarised as follows:
\begin{quote}
The checksum field is the 16-bit one's complement of the one's
complement sum of all 16-bit words in the header. For purposes of
computing the checksum, the value of the checksum field
is zero.\footnote{Quote from Wikipedia~\cite{wikipedia:_ipv4}.}.
\end{quote}
% ----------------------------------------------------------------------
\section{\label{background:networkdesign}Network Designs}
%% \begin{figure}[h]
%% \includegraphics[scale=0.5]{v4only}
%% \centering
%% \caption{IPv4 only network}
%% \label{fig:v4onlynet}
%% \end{figure}
In relation to IPv6 and IPv4, there are in general three different
network designs possible:
The oldest form are IPv4 only networks.
These networks consist of
hosts that are either not configured for IPv6 or are even technically
incapable of enabling the IPv6 protocol. These nodes are connected to
an IPv4 router that is connected to the Internet. That router might be
capable of translating IPv4 to IPv6 and vice versa.
%% \begin{figure}[h]
%% \includegraphics[scale=0.5]{dualstack}
%% \centering
%% \caption{Dualstack network}
%% \label{fig:dualstacknet}
%% \end{figure}
With the introduction of IPv6, hosts can have a separate IP stack
active and in that configuration hosts are called ``dualstack hosts''.
Dualstack hosts are capabale of reaching both IPv6 and IPv4 hosts
directly without the need of any translation mechanism.
The last possible network design is based on IPv6 only hosts.
While it is technically easy to disable IPv4, it
seems that completely removing the IPv4 stack in current operating
systems is not an easy task~\cite{ungleich:_ipv4}.
%% \begin{figure}[h]
%% \includegraphics[scale=0.5]{v6only}
%% \centering
%% \caption{IPv6 only network}
%% \label{fig:v6onlynet}
%% \end{figure}
While the three network designs look similar, there are significant
differences in operating them and limitations that are not easy to
circumvent. In the following sections we describe the limitations and
reason how a translation mechanism like our NAT64 implementation
should be deployed.
% ----------------------------------------------------------------------
\subsection{\label{background:networkdesign:ipv4}IPv4 only network limitations}
As shown in figures \ref{fig:ipv4header} and \ref{fig:ipv6header}
the IPv4 address size is 32 bit, while the IPv6 address size is 128
bit.
Without an extension to the address space, there is no protocol independent
mapping of IPv4 address to IPv6\footnote{See section
\ref{background:ip}.} that can cover the whole IPv6 address space.
Thus IPv4 only hosts can
never address every host in the IPv6 Internet. While protocol
dependent translations can try to minimise the impact, accessing all
IPv6 addresses independent of the protcol is not possible.
% ok
% ----------------------------------------------------------------------
\subsection{\label{background:networkdesign:dualstack}Dualstack network
maintenance}
While dualstack hosts can address any host in either IPv6 or IPv4
networks, the deployment of dualstack hosts comes with a major
disadvantage: all network configuration double. The required routing
tables double, the firewall rules roughly double\footnote{The rulesets
even for identical policies in IPv6 and IPv4 networks are not
identical, but similar. For this reason we state that roughly double
the amount of firewall rules are required for the same policy to be
applied.} and the number of network supporting systems (like DHCPv4,
DHCPv6, router advertisement daemons, etc.) also roughly double.
Additionally services that run on either IPv6 or IPv4 might need to be
configured to run in dualstack mode as well and not every software
might be capable of that.
So while there is the instant benefit of not requiring any transition mechanism
or translation method, we argue that the added complexity (and thus
operational cost) of running dual stack networks can be significant.
% ----------------------------------------------------------------------
\subsection{\label{background:networkdesign:v6only}IPv6 only networks}
IPv6 only networks are in our opinion the best choice for long term
deployments. The reasons for this are as follows: First of all hosts
eventually will need to support IPv6 and secondly
IPv6 hosts can address the whole 32 bit IPv4 Internet mapped in
a single /96 IPv6 network. IPv6 only networks also allow the operators
to focus on one IP stack.