Implementing a Simple VNS Firewall

Assignment Overview

In this assignment, you will implement a fully-functional firewall that is capable of routing and filtering real Internet traffic. Your firewall will run as a local user process on your development machine, but will route real packets to and from application servers located on the Stanford network using the Stanford Virtual Network System.


Overview of the Virtual Network System (VNS):

VNS gives you hands-on experience working on projects requiring low level network access, such as routers. The VNS is comprised of two components: (1) The VN Server which runs in a lab at Stanford, and (2) A number of VN Clients which connect to the server. Your router is an example of a VN Client. The server intercepts packets on the network, forwards the packets to the clients, receives packets from the client and injects them back into the network. The physical setup of the VNS is shown in the figure.


The VNS Server:

The server is a user level process running at Stanford. The machine hosting the server is connected to a hub which is connected to two Linux servers running a few internet services (http, ftp, and a streaming music server on port 8888), referred to as application servers. The VN Server simulates a network topology which consists of multiple links and VN Clients. The application servers sit on the other side of the network topology. For example, the simplest topology is one with a single VN Client and one application server, as shown below in the figure.


A client wanting access to traffic in the network connects to the server via a normal tcp socket and requests the traffic seen on links in the topology, in this case, topology 0. Assuming the traffic is not already being sent to some other user, the server accepts the request and sends the traffic on the link to the client over the tcp socket. The client would then inspect the packet, determine where the next hop in the network (which would be fairly easy in the case of topology 0) and send the packet back to the server to be injected back into the network.

The VNS Server can handle multiple (2^16) topologies simultaneously. This means that each student can have his or her own topology to connect to and route over. The VN Server ensures that clients are only sent traffic belonging to their topology.

The VNS Client:

A VNS client is any program that speaks the VNS protocol and connects to the VNS server. In the case of this assignment we provide you with the code for a basic VNS client (called sr or Simple Router) that can connect to the VNS server. The clients are run locally by the students as regular user processes and connect to the server via normal tcp sockets. Clients, once connected to the server, are forwarded all packets that they are supposed to see in the topology. The clients can manipulate the packets in any way they wish, generate responses based on the packets, or make routing decisions for those packets and send the replies back to the server to place back onto the network. For example, on the above topology (topology 0), the VN Server might receive a TCP SYN packet destined for The VN Server sends the packet to the VN Client which would receive the packet on interface zero, decrement the TTL, recalculate the header checksum, consult the routing table and send the packet back to the server with directions to inject it back onto the network out of interface one. What will the destination hardware address be for the packet sent back by the client? What if the client doesn't know the hardware address for www-server-1?

In this assignment you will implement a fully functional router by extending the sr code given to you.

Packet Flow Through the System:

The following scenario is a step by step explanation of how a client routes traffic on a simple topology.

Nick has just finished developing a completed sr router with no firewalling capabilities. He was assigned topology 42 for testing which is shown in the figure below.

To test, Nick runs his router from and connects to the VNS server at, topology 42. The VNS server sends Nick's router the list of interfaces and their IP addresses.

To generate traffic for routing, Nick fires up a standard web browser from his local computer pointed at the IP of the application server on topology 42. Nick's router will now get the opportunity to route all packets between his web browser and the web server.

We'll now walk through the first few significant steps that take place when packets flow between Nick's web browser and the web server.

Test Driving the sr Stub Code:

Before beginning development you should first get familiar with the sr stub code and some of the functionality it provides. Download the Stub Code Tarball and save it locally. As described before, it handles all of the dirty-work required for connecting and communicating with the server. To run the code, untar the package (tar -zxvf sr_stub.tar.gz) and compile it via make. Once compiled, you can connect to the VNS server as follows:

 ./sr -s -t

for example, connecting to the server on topology 0 would look like:

./sr -s -t 0 

(you can use ./sr -h to print a list of the accepted command line options)

After you connect successfully, the server will send you a description of the host including all the interfaces and their IP addresses. The stub code uses this to build the interface list in the router (the head of the list is member if_list for struct sr_instance). The routing table is constructed from the file rtable and by default consists of only the default route which is the firewall. The routing table format is as follows:

ip gateway mask interface
a valid rtable file may look as follows: eth1 eth2 eth0

The VNS Server, on connection should return the IP addresses associated with each one of the interfaces. The output for each interface should look something like:


Speed: 10
Hardware Address: 70:00:00:00:00:01
Ethernet IP:

To test if the router is actually receiving packets try pinging or running traceroute to the IP address of eth0 (which is connected to the firewall in the assignment topology). The sr should print out that it received a packet. What type of packet do you think this is?

What should your router do on receipt of an ARP request packet?

Inspecting Packets with tcpdump

As you work with the sr router, you will want to take a look at the packets that the router is sending and receiving. The easiest way to do this is by logging packets to a file and then displaying them using a program called tcpdump.

First, tell your router to log packets to a file in a format that tcpdump can read by passing it the -l option and a filename:

./sr -t <topo-id> -s -l <logfile>

As the router runs, it will log the packets that it receives and sends (including headers) to the indicated file. After the router has run for a bit, use tcpdump to display the packets in a readable form:

tcpdump -r <logfile> -e -vvv -x

The -r switch tells tcpdump where to look for the logfile. -e tells tcpdump to print the headers of the packets, not just their payload. -vvv makes the output very verbose, and -x puts the packets in a hex format that is usually easier to read than ASCII. You may want to specify the -xx option instead of -x to print the link-level (Ethernet) header in hex as well.

Developing Your Very Own Router Using the SR Stub Code:

Data Structures You Should Know About:

The First Methods to Get Acquainted With:

The two most important methods for developers to get familiar with are as follows:

Dealing with Protocol Headers:

Within the sr framework you will be dealing directly with raw Ethernet packets. There are a number of resources which describe the protocol headers in detail, including Stevens UNP, and the Internet RFC's for ARP (RFC826), IP (RFC791), and ICMP (RFC792). The stub code itself provides some data structures in sr_protocols.h which you may use to manipulate headers. There is no requirement that you use the provided data structures, you may prefer to write your own or use standard system includes.

To Help You Get Started:

We have connected a functioning router to topology 2 to demonstrate how your router should behave once completed. Topology 2 consists of a router with 3 interfaces connected to 2 application servers as shown below:

The router's interface addresses are as follows: additionally, topology 2 has two application servers with the following addresses: You should be able to traceroute to the router or through it to the application servers. Additionally, you should be able to connect to the application servers via an Internet browser and be able to download the posted files. Tracerouting to the application servers should look something like the following.
[casado@yuba ~]$ /usr/sbin/traceroute
traceroute to (, 30 hops max, 38 byte packets
 1  Gates-rtr (  0.546 ms  0.329 ms  0.287 ms
 2  vns-firewall (  0.393 ms  0.302 ms  0.285 ms
 3 (  2.332 ms  1.165 ms  1.435 ms
 4 (  3.243 ms  2.098 ms  2.094 ms
[casado@yuba ~]$

Creating a VNS Firewall

In addition to routing packets between the local networks and the Internet, a virtual router can act as a simple firewall, controlling which packets can reach the application servers connected to the router.

Specifically, a VNS firewall should support the following functionality.

  1. The ability to declare an interface as internal or external. For simplicity only a single external interface is supported. Internal interfaces are connected to local (protected) networks while the external interface is connected to the Internet.
  2. By default packets arriving to the external interface and destined to an internal interface are silently dropped. That is, no response (e.g. ICMP) packet is generated as a result of dropping the original packet. A log entry may be generated depending on the firewall's configuration. See 'Adding Inbound Exceptions' and 'Generating Outbound Traffic' below for important details about this feature.
  3. By default, packets arriving from an internal interface that need to be forwarded through the external interface are allowed to pass through the firewall. Doing so, allows end-hosts within the protected networks to access services on the public Internet.

Supporting Outbound Two-way Traffic

Note that simply allowing packets from the internal hosts go through the firewall is not enough to establish a working connection to an external service, since most (if not all) TCP/IP services entail two-way communications. Therefore, packets that belong to a flow initiated by an internal end-host that arrive to the external interface must be allowed through the firewall. To support this feature the firewall maintains a "flow table" that contains all the active (and allowed) flows that traverse the firewall. In this context, a flow is defined as a 5-tuple .

When the first "internal" packet arrives at the firewall, two entries are added to the flow table, one for each direction of communication. The entry for the external-to-internal flow can be generated by inverting the order of source and destination IP addresses and ports. When a packet arrives to the external interface, the firewall checks if it matches one of the entries in the flow table.If it does then the packet is not dropped and it is forwarded to the internal interface.

Entries remain on the flow table as long as packets that match these entries go through the firewall. To support this feature each entry has a time-to-live (TTL). Each time a packet matching the flow entry is received, the entry's TTL is incremented by X seconds. The firewall periodically scans the flow table and removes all entries whose TTL has expired. (Note: Should we update the entries associated with both directions of a flow when a packet is received or not?)

The flow table can hold up to Y entries at each time. The parameter Y is configurable. If a new entry needs to be added when the flow table is full, first a scan is initiated to determine if one or more stale entries exist in the flow table. If all entries are valid, then an ICMP response is returned (connection refused) to the originator and a log entry is generated. (Note: Can we send ICMP responses to UDP packets?)

Adding Inbound Exceptions

The firewall supports adding explicit rules to allow inbound flows (i.e. coming from the external interface) to traverse the firewall. For example, the firewall's administrator might decide to allow TCP packets with destination port 80 and destination address X.Y.Z.W to go through the firewall. Such rules are entered in the firewall's "rule table". A rule table entry has the following format where each of the entry's five components can be a wildcard. A wildcard entry matches all values of the corresponding field in an actual packet.

For example, a wildcard entry in the sourceIP field means that packets from every source IP can match the rule. When a packet arrives at the firewall's external interface, the firewall first checks to see if the packet matches one of the entries in the flow table. If not, then the firewall determines if the packet matches one of the entries in the rule table. If this is true, then the firewall generates two entries in the flow table (one matching the forward path and another matching the reverse) and lets the packet go through. If the packet matches a rule table entry but the flow table is full then an ICMP response is returned and an entry is added to the firewall's log.

Entries in the rule table are added through the configuration file.

Generating Outbound Traffic

In order to fully test the firewall's functionality, you will need to generate outbound traffic from within your topology. You can do this by connecting to the application server IP via SSH and then using ping and wget to generate outbound requests that will establish TCP/IP flows between the (internal) application server and an external server.

In order to support connecting to your application server IP via SSH, your firewall will need to have at least one inbound allowed flow defined in its configuration: you must allow inbound connections on port 22 (the standard SSH port) to the IP of your applications servers.

Full instructions for loggin in via SSH were included with the email you received describing your topology.

To generate traffic using ping, you must specifiy the IP address to use as the source address. You can do this with the following command:

ping -I <IP Address> host
For example, if I were logged into the IP and wanted to ping the server at, I would use the following command:
ping -I
You can also generate outbound HTTP requests using the wget utility.
wget --bind-address <IP> URL
For example, to retrieve the VNS homepage from, I would use the following command:
wget --bind-address

Not Supported

There is no support for fragment reassembly for firewall purposes. That is if a packet fragment arrives with the transport level header missing then the fragment (as well all other subsequent fragments) are dropped.