Assignment 3

Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

The assignment is due June 7th at 5pm for groups of two submissions.

1. Introduction 1

2. ICMP echo request/reply 3

3. TCP connections 4

4. Mappings 4
4.1 Cleaning up defunct mappings 5

5. Implementation 5
5.1 Mapping data structure and concurrency 5
5.2 Download skeleton code 6
5.3 Test connectivity of your emulated topology 7
5.3.1 Configure the environment 7
5.3.2 Start Mininet 7
5.3.3 Start POX 8
5.3.4 Start reference solution 9
5.4 Tracking Connections 11
5.5 Adding command-line flags 11
5.6 Reference Implementation 12

6. Testing 12

7. Deliverables 12

8. Submissions 13

Network Address Translator


Please use the discussion board to post questions/suggestions. This assignment is
based on the 2nd assignment. You will understand how NAT works after finishing the
assignment. Of course, the focus is not on performance, but on simplified functionality
and that will make the problem tractable!

1. Introduction
In this assignment you will be writing a simple NAT that can handle ICMP and TCP. It
will implement a subset of the functionality specified by RFC5382 and RFC5508.
Before beginning this lab, it is crucial that you:

● Understand how NATs work;


● Understand TCP handshake and teardown packet sequences. Consider working
through the TCP state diagram;
● Understand NAT Endpoint Independence. NAT builds on the 2nd assignment.
You should start with your static router code and extend it to include NAT
functionality;

As with "Static Router", we will create a NAT that sits in Mininet between the app
servers and the client. The internal interface of the NAT faces the client, while the
external interfaces are connected to app servers. The app servers are "outside" the
NAT, while the client is "inside."

The topology of NAT is as follows, where the NAT's internal interface (eth1) faces the
client and its external interface (eth2) has two application servers connected with a
switch:

A correct implementation should support the following operations from the emulated
client host:

● Pinging the NAT's internal interface from the emulated client host;
● Pinging any of the app servers (e.g. 172.64.3.21, 172.64.3.22 above);
● Downloading files using HTTP from the app servers. All packets to external hosts
(app servers) should appear to come from eth2's address (e.g. 172.64.3.1
above);

There are three major parts to the assignment:


● Translating ICMP echo messages (and their corresponding replies);
● Translating TCP packets;
● Cleaning up defunct mappings between internal addresses and the external
address. Note that your NAT is not required to handle UDP. It is entirely up to
you whether you drop or forward UDP traffic;

Your NAT builds on the "static router". You must add a new command-line flag, -n,
which controls whether the NAT is enabled. If the -n flag is not passed, then the router
should act following the requirements of "static router". For example, it should be
possible to traceroute across the router when the -n flag is not passed. All of the ICMP
errors in "static router" still apply. More precisely:

● Your NAT MUST generate and process ICMP messages as per the "static
router";

2. ICMP echo request/reply


The first four bytes of an ICMP echo request contain a 16-bit query identifier and a 16-
bit sequence number. Because multiple hosts behind the NAT may choose the same
identifier and sequence number, the NAT must make their combination globally unique.
It needs to maintain the mapping between a globally unique identifier and the
corresponding internal address and internal identifier, so that it can rewrite the
corresponding ICMP echo reply messages. The first three requirements for your NAT
are:

● Your NAT MUST translate ICMP echo requests from internal addresses to
external addresses, and MUST correctly translate the corresponding ICMP echo
replies;
● ICMP echo requests MUST be external host independent: two requests from the
same internal host with the same query identifier to different external hosts
MUST have the same external identifier;
● An ICMP query mapping MUST NOT expire less than 60 seconds after its last
use. This value MUST be configurable, as described below;

Other "static router" ICMP behavior should continue to work properly (e.g. responding to
an ECHO request from an external host addressed to the NAT's external interface).
3. TCP connections
When an internal host opens a TCP connection to an external host, your NAT must
rewrite the packet so that it appears as if it is coming from the NAT's external address.
This requires allocating a globally unique port, under a set of restrictions as detailed
below. The requirements for your NAT are a subset of those in specified in RFC5382; in
some cases they are more restrictive. Refer to the RFC for details on the terms used.
Your NAT has the following requirements:

● Your NAT MUST have an "Endpoint-Independent Mapping" behavior for TCP.


This means your NAT will assign the same external port mapping value to
packets sent by an internal endpoint, as long as packets have (1) the same
source IP address; (2) the same source port, regardless of their destination IP
address or destination port.
● Your NAT MUST support all valid sequences of TCP packets (defined in
RFC0793) for connections initiated both internally as well as externally when the
connection is permitted by the NAT. OPTIONAL: in addition to handling the TCP
3-way handshake mode of connection initiation, you NAT can support to handle
the TCP simultaneous-open mode of connection initiation.
● Your NAT MUST have an "Endpoint-Independent Filtering" behavior for TCP.
This means your NAT only needs to check the (1) destination IP and (2)
destination port of an inbound packet sent by an external endport to decide
whether to pass the packet or not. In our case, it’s the eth2 and the http port.
● Your NAT MUST NOT respond to an unsolicited inbound SYN packet for at least
6 seconds after the packet is received. If during this interval the NAT receives
and translates an outbound SYN for the connection the NAT MUST silently drop
the original unsolicited inbound SYN packet. Otherwise, the NAT MUST send an
ICMP Port Unreachable error (Type 3, Code 3) for the original SYN. If your NAT
cannot determine whether the endpoints of a TCP connection are active, it MUST
abandon the session if it has been idle for some time. In such cases, the value of
the "established connection idle-timeout" MUST NOT be less than 2 hours 4
minutes. The value of the "transitory connection idle-timeout" MUST NOT be less
than 4 minutes. These two values are configurable, as described below.

4. Mappings
When assigning a port to a mapping, you are free to choose a port any way you choose.
The only requirement is that you do not use the well-known ports (0-1023).
As noted above, mappings should be Endpoint Independent. Once a mapping is made
between an internal host's (ip, port) pair to an external port in the NAT, any traffic from
that host's (ip, port) directed to any external host, and any traffic from any external host
to the mapped external port will be rewritten and forwarded accordingly.

4.1 Cleaning up defunct mappings


Your NAT must clean up defunct mappings. Your NAT must periodically timeout both
defunct ICMP query sessions and idle TCP connections. Once all connections using a
particular mapping are closed or timed out, the mapping should be cleared. Once
cleared, a mapping can be reused in new connections.

The periodic function that handles timeouts should fire in its own separate thread (more
on threading below). The following three timeout intervals for mappings should be
configurable via command-line flags:

● -I INTEGER -- ICMP query timeout interval in seconds (default to 60)


● -E INTEGER -- TCP Established Idle Timeout in seconds (default to 7440)
● -R INTEGER -- TCP Transitory Idle Timeout in seconds (default to 300)

TCP Established Idle Timeout applies to TCP connections in the established (data
transfer) state. TCP Transitory Idle Timeout applies to connections in other states (e.g.
LISTEN). Refer to the TCP state diagram.

5. Implementation

5.1 Mapping data structure and concurrency


Mapping state and delaying incoming SYN connections will require a data structure
similar to the ARP cache from "static router". Unlike "static router", however, in this
assignment it is up to you to implement it.

Be sure to study how the ARP cache works. For handling timeouts, a separate thread is
spawned (at the top of sr_router.c) that periodically runs. NAT timeouts should have
their own thread as well. Because the main forwarding thread and the ARP cache
timeout thread share the data structure, the ARP cache accessors and mutators use
locks. Be sure that your NAT's mapping data structure uses locks as well,
otherwise nasty concurrency bugs will be sure to crop up.
In addition, be careful how your mapping table returns mappings, you do not want to
hand out pointers to structures that may be freed by the periodic timeout. Take a look at
the sr_arpcache_lookup code in the ARP cache.

To get you started on the right track, we provide skeleton code for a possible NAT
mapping data structure. You will use the same environment that we set up in "simple
router" for this assignment. For detailed instructions, please refer to Environment Setup
and Simple Router.

This assignment would require some thread programming.There are also many
resources on the web explaining why and when systems use them. Finally, there are
lots of good pthreads tutorials on the web, for concrete programming guidance. You can
also use the ARP cache code as a guide. Since this isn't a high performance system,
it's better to be conservative with your locks; a race condition is much harder to debug
than a deadlock.

5.2 Download skeleton code


Open up a terminal on your VM, download the skeleton code for "NAT" using git.

> cd ~
> https://[email protected]/cs561-17sp/cs561-as3.git
> cd cs561-as3

The skeleton code resides in router/. The router directory is the same starter code for
the 2nd assignment. You should make a copy of your “Static Router” into the NAT
directory as follows:

> pwd
/home/networks/cs561-as3
> cp -r ~/cs561-as2/router ./

Now untar the file sr_nat_table.tar. Then you will find two files, sr_nat.c and sr_nat.h.
You also need to copy the rtable into the directory.

> tar xf sr_nat_table.tar


> mv sr_nat.c ./router/
> mv sr_nat.h ./router/
> cp ./rtable ./router/
5.3 Test connectivity of your emulated topology
Same as the the 2nd assignment, we also provide a reference implementation (binary)
for you to test the environment.

5.3.1 Configure the environment

First, configure the environment by running the following command.

> sudo ./config.sh

5.3.2 Start Mininet

> ./run_mininet.sh

You should see an output that looks like this (except for the IP addresses).
5.3.3 Start POX

Start the Mininet controller (and wait for it to print some messages)

> ./run_pox.sh

It will print messages that look like this:


5.3.4 Start reference solution

> ./sr_nat -n

Note that “-n” means NAT is enabled. You should see an output like this:
To see whether the NAT is doing the translation, let’s do a tcpdump at server1 and
observe the packet is going to be received at the server 1. To do so, go to the terminal
where you run the Mininet, type the following command in the Mininet command line
interface (CLI) to bring up the terminal of server1.

mininet> xterm server1

Then in the server1 terminal:

> tcpdump -n -i server1-eth0

Now, back to the Mininet CLI to send some ping packets from client to server1:

mininet> client ping -c 3 172.64.3.21

On the Mininet CLI, you should be able to see the following output:

PING 172.64.3.21 (172.64.3.21) 56(84) bytes of data.


64 bytes from 172.64.3.21: icmp_req=1 ttl=63 time=283 ms
64 bytes from 172.64.3.21: icmp_req=2 ttl=63 time=52.1 ms
64 bytes from 172.64.3.21: icmp_req=3 ttl=63 time=78.9 ms

On the server1 terminal, you should be able to see the following output:

Note the packets received at server1 is from 172.64.3.1, which is the IP of NAT's
external interface, instead of 10.0.1.100, the IP of the client host.

Now, let’s disable NAT and compare. Back to the terminal where you run “./sr_nat -n”,
use control-c to stop the current “./sr_nat -n” process, and run the following command
> ./sr_nat

Also using tcpdump on server1's terminal to see the packets reaches server1:

> server1 tcpdump -n -i server1-eth0

You should be able to see the following output:

This time, since the NAT is disabled, the source IP shows the client's IP (10.0.1.100)
instead.

5.4 Tracking Connections


You do not need to keep lots of state per connection. For example, there is no need to
track seqnos or window values or ensure TCP packets are in proper order to the end
hosts. Keep only the information that is useful to the NAT for establishing or clearing
mappings.

When rewriting TCP packets, remember to update the checksum (over the pseudo-
header, tcp header, and payload). The TCP checksum is calculated like the IP
checksum, so you can reuse the cksum function. Note that if the checksum is incorrect
when the packet comes in, you can drop it; you should not "correct the checksum" as
that would hide potential attackers or errors.

5.5 Adding command-line flags


You must add the following command-line flags to sr_main.c:

● -n -- Enable NAT functionality


● -I INTEGER -- ICMP query timeout interval in seconds (default to 60)
● -E INTEGER -- TCP Established Idle Timeout in seconds (default to 7440)
● -R INTEGER -- TCP Transitory Idle Timeout in seconds (default to 300)
Make sure to adjust the parameter to getopt, and add the proper cases. getopt() is a
useful C library call to parse a list of arguments passed to your program. Here is a good
tutorial on using getopt: Command line processing using getopt().

For example, starting your NAT with:

> ./sr -s localhost -p 8888 -n -I 70 -R 40

It would enable NAT functionality, timeout ICMP mappings after 70 seconds, TCP
mappings with at least one established connection after 7440 seconds, and TCP
mappings with only transitory connections after 40 seconds.

5.6 Reference Implementation


A reference implementation (binary), sr_nat, is available along with the start code.
Please use it to check expected output.

6. Testing
We’re testing your code in the following three scenarios. Please refer to our binary
solution for expected behavior. You should do tcpdump at the server side to make
sure where the packet is from. And you should test the following cases in the
mininet client.

● Ping the internal NAT interface from the VM (ping 10.0.1.1);


● Ping any of the HTTP servers from the VM (ping 172.64.3.21/172.64.3.22);
● Download a file using HTTP from one of the HTTP servers (wget
172.64.3.21/172.64.3.22);
● We’ll check your code on the mapping cleaning;

You’re recommended to think more about testing cases and describe in the document.

7. Deliverables
● Final source code: Remember one of the goals of this assignment is for you to
build a basic NAT. Therefore, your final code MUST be runnable as a single shell
command (“./router/sr -n”). We will test your code in the same setup.
● README: This file should be 1-3 page document describing your high-level
design, implementation, and special testing cases.

8. Submissions
The assignment is due June 7th at 5pm for group submissions.

Make sure your names are on the README. Create a tarball of the cs561-as3 folder with your
updates to the started code. Submit your tar-ball to the course dropbox. NOTE: we
recommend you to use the referenced solution (./sr_nat -n) to test your code before
submission.

You might also like