Ecdysis: open-source implementation of a NAT64 gateway

Description

Ecdysis is aimed to develop an open-source implementation of a NAT64 gateway to run on open-source operating systems such as Linux and BSD. The gateway is comprised of two distinct modules: the DNS ALG and the IP translator. The DNS ALG is implemented in two DNS open-source server: Unbound and Bind. The IP translator is implemented in Linux as kernel module using Netfilter faclities and in openBSD as a modification of PF.

This project is funded by the NLnet Foundation and Viagénie.

The project name, Ecdysis, (pronunciation) refers to the molting of the cuticula in arthropods, as an analogy of IPv4 molting into IPv6. After molting, the arthropod is fresh and ready to grow! Arthropods is also the expertise of the 5 years old son of one of the project leads...

Why Translate between IPv4 and IPv6?

IPv4 and IPv6 networks are "incompatible". The IETF recommendation has usually been to rely on dual-stack deployment: have both networks coexist until IPv6 takes over IPv4. However, IPv6 growth has been much slower than anticipated. Therefore, new IPv6-only deployments face an interesting challenge, that of communicating with the predominantly IPv4-only rest of the world. A similar problem is encountered when legacy IPv4-only devices need to reach the IPv6 Internet.

The IETF is currently trying to solve these problems. One initial proposal was NAT-PT [RFC2766]. However, it suffered from various issues which eventually caused it to be declared obsolete in [RFC4966]. Recently, there has been a concerted effort coming from the BEHAVE, V6OPS, and SOFTWIRE working groups to engineer a new solution. Discussions at the 71st and 72nd IETF meetings (Philadelphia and Dublin) led to the scheduling of a two-day interim meeting in Montréal in October 2008. IPv4/IPv6 translation continued to be a major focus of interest at the 73rd IETF meeting in Minneapolis, in November 2008.

This translation concerns has resulted in several draft documents. The general framework for IPv4/IPv6 translation is described in [draft-ietf-behave-v6v4-framework]. It also explains the background of the problem, and some expected uses. Another document describes the translation proposal [draft-ietf-behave-v6v4-xlate]. There are two concrete protocol proposals that have much in common: NAT64/DNS64 [draft-ietf-behave-v6v4-xlate-stateful] [draft-ietf-behave-dns64] and IVI [draft-xli-behave-ivi]. A good text comparing the proposals is [draft-wing-nat-pt-replacement-comparison]

Specifications

Ecdysis conforms to the following specifications:

Download

Download the source code of Ecdysis.

DNS64 - DNS ALG

License is BSD-like for patches, GPLv3 for the standalone. It has been only compiled and tested on Linux Fedora 10. See instructions below.

NAT64 - IP Translator

This is our first release of the IP Translator which currently supports TCP, UDP and ICMP traffic. See instructions below.

Instructions

Standalone DNS translator

Instructions for stand-alone implementation:

# This is a very simple implementation of DNS64. It listens for DNS queries on
# on UDP port 53. It relays the query. When the answer section of an AAAA query
# response is empty, it generates an A query and converts the A records into
# AAAA records, prefixing them with the DNS64 prefix (configured below).
#
#
# Bugs:
#
#  - It is slow. We don't care, that's not the point. The point is to be able to
#    experiment in a quick prototyping language (in this case, Perl).
#
#  - Error handling is deficient. We also don't care. What's important is to not
#    clutter the code with error handling statements. Only the bare minimum is
#    included.
#
#  - Only a single request is processed at a time. This is a variant of "slow"
#    above.
#
#
# Notes:
#
#  - Some modules are needed. To install them using CPAN, use the following:
#
#      # perl -MCPAN -e 'install IO::Socket::INET6 Net::DNS NetAddr::IP::Util'
#
#  - Remember that it is necessary to run as root to bind to port 53 on many
#    systems.

All configuration parameters are at the top of the Perl source code.

- Set the $PREF64 variable to your DNS64 prefix. It must be a /96 or shorter.
For example:

    my $PREF64 = "64:FF9B::/96";

- By default, requests are forwarded to the system-configured DNS servers
(usually in /etc/resolv.conf). If you want to change this, edit the
@NAMESERVERS array. For example:

    my @NAMESERVERS = qw(2620:0:230:8000::2 206.123.31.2);

To test that things are working right, perform a query against dns64.pl for a
domain name for which no AAAA record exists. You should see a AAAA record in
the answer section. The corresponding IPv6 address will be inside the DNS64
prefix. For example:

    $ ./dns64.pl &
    $ dig @localhost jazz-v4.viagenie.ca aaaa
    [...]
    ;; ANSWER SECTION:
    jazz-v4.viagenie.ca.        86400   IN      AAAA    64:ff9b::ce7b:1f02


Unbound

To enable DNS64 functionality in Unbound, two directives in unbound.conf must
be edited:

1. The "module-config" directive must start with "dns64". For example:

    module-config: "dns64 validator iterator"

If you're not using DNSSEC then you may remove "validator".

2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:

    dns64-prefix: 64:FF9B::/96

The prefix must be a /96 or shorter.

To test that things are working right, perform a query against Unbound for a
domain name for which no AAAA record exists. You should see a AAAA record in
the answer section. The corresponding IPv6 address will be inside the DNS64
prefix. For example:

    $ unbound -c unbound.conf
    $ dig @localhost jazz-v4.viagenie.ca aaaa
    [...]
    ;; ANSWER SECTION:
    jazz-v4.viagenie.ca.        86400   IN      AAAA    64:ff9b::ce7b:1f02

Bind

In named.conf, specify your DNS64 prefix with the dns64-prefix option. For
example:

options {
    dbs64-prefix 64:FF9B::/96;
}

The prefix must be a /96 or shorter.

To test that things are working right, perform a query against Bind for a
domain name for which no AAAA record exists. You should see a AAAA record in
the answer section. The corresponding IPv6 address will be inside the DNS64
prefix. For example:

    $ named -c named.conf
    $ dig @localhost jazz-v4.viagenie.ca aaaa
    [...]
    ;; ANSWER SECTION:
    jazz-v4.viagenie.ca.        86400   IN      A       206.123.31.2
    jazz-v4.viagenie.ca.        86400   IN      AAAA    64:ff9b::ce7b:1f02

NAT64 in PF

For the binary distribution (pf_nat64-0.1-amd64.tgz), run './install.sh'. This script will replace your current kernel, pfctl, systat, tcpdump. The old ones will have the ".old" extension added.

For the source distribution (pf_nat64-0.1.tgz), apply 'pf_nat64.patch' to the OpenBSD 4.6 tree and go through the usual OpenBSD compilation and installation process. See the README inside the package for more details.

Add the following rule into /etc/pf.conf:
nat64 from any to PREFIX -> a.b.c.d
Set PREFIX to 64:ff9b::/96 to use the well-known nat64 prefix. Set a.b.c.d to the nat64 ipv4 address. There is currently a conflict with any other rule that would try to establish state for the same packets. Please ensure that your "pass" and "block" rules do not also apply to packets handled by the nat64 rule. The nat64 rule has the same syntax as the nat rule.

NAT64 in Linux

Requirement: kernel 2.6.33 Compilation:
make
Installation:
make install
Configuration: edit
./config-example.sh
to fit your environment.

Contact

Please contact us at info@viagenie.ca.