\section{Test of the DPF}
In this chapter the testing environment used for verifying the DPF
functions will be discussed.
Several network applications are tried, including Telnet, FTP and NFS. 
The Telnet sessions are first tried
from the DPF host itself, then it is run from a host on the
intranet. The other applications are only run from hosts on the intranet.

\section{Physical setup}
\label{sec:dpf-test}

The testing environment is shown in Figure~\ref{fig:setup}.
Flagdnag and Odorf are on the same 10Mbps ethernet, 128.198.4.0.
Gandalf and Bilbo are on the 100Mbps HP net, 128.198.9.0. One possible
setback of the setup is that both hubs are connected to the UCCS
backbone. See Section~\ref{sec:router} for a discussion of hubs,
segments, subnets and the UCCS backbone. 
Since the hubs are implicitly coupled, it means that if Bilbo and
Frodo are communicating, their packets may travel the intended way
through Gandalf, or through the UCCS backbone.

The routing tables on all computers have therefore been carefully setup to use 
the Gandalf as a router.

The routing table setup can be tested by making Gandalf to refuse any 
forwarding between its two ethernet cards. 
If the default PF policy is to accept, it is possible to do network
activity between the two computers, and if the PF policy is set to 
reject/deny it is not. The test proves that
packets can only travel the intended way, and not by the UCCS backbone.

The following IP addresses corresponds to these hosts:
\begin{itemize}
  \item
    128.198.9.116 = Bilbo on the 100Mbps ethernet.
  \item
    128.198.9.118 = Gandalf on the 100Mbps ethernet.
  \item
    128.198.4.144 = Odorf on the 10Mbps ethernet.
  \item
    128.198.4.145 = Fladnag on the 10Mbps ethernet.
\end{itemize}
Note that Gandalf and Fladnag are actually the same host but on different
subnets. The Odorf host is actually called Frodo, but like Gandalf the
name is reversed when accessed through the 10Mbps ethernet
device. Independent of which ethernet device they are accessed from,
both Frodo and Gandalf state their real name on the command prompt.

\subsection{Routing tables}
The following routing table is the result of running the netstat program on Bilbo. 
The -rn switch sets the program to produce the routing table without trying to 
translate addresses to names.

\tiny
\begin{verbatim}
bilbo# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
128.198.4.144   128.198.9.118   255.255.255.255 UGH    1500 0          0 eth1
128.198.9.0     0.0.0.0         255.255.255.0   U      1500 0          0 eth1
127.0.0.0       0.0.0.0         255.0.0.0       U      3584 0          0 lo
0.0.0.0         128.198.9.254   0.0.0.0         UG     1500 0          0 eth1
\end{verbatim}
\normalsize

Bilbo is on the 100Mbps ethernet. The first line is a specific rule to reach 
Odorf. The second line is a route to the .9 subnet. The third line is a rule to
reach the loopback (lo) interface which is used for internal routing.
A specific rule in the routing table is used before a generic one.
This means that the rule in the first line of a route to Odorf via Gandalf will 
take precedence over using the default router of 128.198.9.254.

The other fields in the output is the Genmask which specifies the network mask 
used to find routing entries. 
The Flags field usually contains U, G or H. 
U means that the routing table entry is Up, and the entry may be used. 
G means that the routing entry uses a Gateway (router). 
Section~\ref{sec:router} explains why the term router should be used instead of gateway. 
Finally the H means that the target is a Host. 
The MSS field shows the Maximum Segment Size of the device. 
Note the larger size of the loopback interface. 
A MSS of 1500 is suspicious, and I assume that it really means MTU instead. 
MSS, MTU and Window are discussed in Section~\ref{sec:telnet-out}.
The Window field is the window size to use. 
Zero means the default size, that is to let the TCP layer figure out what window 
size to use.
The irtt field is the initial round trip time (rtt) estimation, which is used to avoid
congestion of a network. A large rtt may fool the TCP layer to make unnecessary
retransmissions, as the TCP layer thinks the packets are lost when
they simply take too long time to arrive. Zero means the default, 
and thus the TCP layer calculates a rtt based on the the timing of the
packets sent/received.

The following routing table is used on Odorf:

\tiny 
\begin{verbatim}
frodo# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
128.198.9.116   128.198.4.145   255.255.255.255 UGH    1500 0          0 eth0
128.198.4.0     0.0.0.0         255.255.255.0   U      1500 0          0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U      3584 0          0 lo
0.0.0.0         128.198.4.254   0.0.0.0         UG     1500 0          0 eth0
\end{verbatim}
\normalsize

Odorf is on the 10Mbps ethernet. To reach Bilbo via Gandalf, a rule
similar to the one used on Bilbo, has been added to override the default router.

The following routing table is used on Gandalf:

\tiny 
\begin{verbatim}
gandalf# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
128.198.4.0     0.0.0.0         255.255.255.0   U      1500 0          0 eth0
128.198.9.0     0.0.0.0         255.255.255.0   U      1500 0          0 eth1
127.0.0.0       0.0.0.0         255.0.0.0       U      3584 0          0 lo
0.0.0.0         128.198.9.254   0.0.0.0         UG     1500 0          0 eth1
\end{verbatim}
\normalsize

Gandalf is connected to both ethernets, and a host on the .4 subnet will 
be accessed through the eth0 device, and a host on the .9 subnet will be
accessed through the eth1 device. If any routing has to be done, the 
kernel will figure out which device to use.

Any other destination will be reached through the default router of 128.198.9.254.

\section{Test of Telnet}
\subsection{Telnet from DPF host to internet}
\label{sec:telnet-out}

This is a typical case of sending packets which is described in Section~\ref{sec:output}.
The telnet protocol is commonly used to login to remote hosts and should thus 
be supported by a firewall. 
Telnet uses the TCP protocol, and no special considerations has to be done by the DPF.

The test of Telnet is done by setting all default policies to reject, and then allowing
only outgoing connections from Gandalf.

This is done by running the following script called setfirewall.

\tiny
\begin{verbatim}
#!/bin/sh

# Set default policy to reject on the PFs
ipfwadm -I -p reject
ipfwadm -O -p reject
ipfwadm -F -p reject

# Flush PF chains
ipfwadm -I -f
ipfwadm -O -f
ipfwadm -F -f

# Allow Gandalf to send
ipfwadm -O -a accept -S gandalf -D 0/0
ipfwadm -O -a accept -S fladnag -D 0/0

# Now list the contents of the PFs
ipfwadm -I -l
ipfwadm -F -l
ipfwadm -O -l
\end{verbatim}
\normalsize

When running the script the last three lines generate the following:

\tiny
\begin{verbatim}
gandalf# ./setfirewall
IP firewall input rules, default policy: reject
IP firewall forward rules, default policy: reject
IP firewall output rules, default policy: reject
type  prot source               destination          ports
acc   all  gandalf.uccs.edu     anywhere             n/a
acc   all  fladnag.uccs.edu     anywhere             n/a
\end{verbatim}
\normalsize

This is the starting point of the test, nothing is allowed to get in, and
only Gandalf is able to send on both ethernet devices.

Now do a telnet to odorf:

\tiny
\begin{verbatim}
gandalf> telnet odorf
Trying 128.198.4.144...
Connected to odorf.uccs.edu.
Escape character is '^]'.
Debian Linux 1.1
Copyright (C) 1993-1996 Debian Association, Inc. and others

frodo login: jhjulkun
Password: 
Last login: Mon Aug 26 11:09:00 from fladnag.uccs.edu
Linux frodo 2.0.6 #1 Wed Aug 14 06:28:10 MDT 1996 i586
Copyright (C) 1993-1996 Debian Association, Inc. and others

frodo>
\end{verbatim}
\normalsize

Let the connection stay open and check the rules in the PF chains:
\tiny\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   tcp  odorf.uccs.edu       fladnag.uccs.edu     telnet -> 1042
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP Outgoing 128.198.4.145:1042    128.198.4.144:23        87532  133
\end{verbatim}\normalsize

The ipfwadm program tells us that the incoming PF chain now accepts incoming
packets from odorf.
By checking the /proc/net/ip\_dynamic `file' which actually invokes a
function in the DPF code, the status of the DPF is printed.
The printout from the DPF code is printed in dotted decimal only, it
is not converted to host names as the output from the ipfwadm program.

Note the expiration timer, it tells us that the rule will be in effect
for $87532$ `ticks'. The timer is decreased by $6000$ ticks each minute, thus the
rule will be in effect for $87532/6000\approx15min$.
The timer is reset to $90000$ every time a packet goes by.
The difference of 90000 and 87532 is the time it takes for me to type
the commands to list the contents of the incoming PF and list the
/proc/net/ip\_dynamic entries.

Now, lets close the telnet session:

\tiny
\begin{verbatim}
frodo> exit
logout
Connection closed by foreign host.
gandalf> 
\end{verbatim}
\normalsize

When both sides have closed the connection, the timer is set to $2$ minutes,
which is $12000$ ticks.

Let's confirm this:

\tiny
\begin{verbatim}
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash 
TCP Outgoing 128.198.4.145:1042    128.198.4.144:23        11636  133
\end{verbatim}
\normalsize

The rule is thus in effect for another two minutes after the session has
been closed. The timeout is required by the TCP state diagram.
This is to allow a final ACK to be resent in case the previous ACK
was lost (the remote host will timeout and send a FIN message to remind the 
host about this).
Unless the host is infected by some malicious users who checks all connections,
it is unlikely that this might be a security hole, as TCP
never allows the same endpoint (proto:IP:port) to be used 
within 2*MSL. See Section~\ref{sec:timeouts} for common values of MSL.

\subsection{TCP dump of a telnet session}
\label{sec:tcpdump}
Even though telnet seems to work, I want to include a tcpdump listing of what
happens to really verify the correct behavior of the DPF.

The tcpdump program has been tremendously useful for tracing what actually
happens on the ethernet. To be able to run tcpdump you have to be root.

The tcpdump program uses a very condensed output to cram in as much
information as possible in a limited space.
The output lines has the following syntax:\\
\mbox{timestamp source $>$ dest Flags [other info]}

The flags shown in Table~\ref{tab:flags} means the following:
\begin{itemize}
  \item
    URG = Urgent data.
  \item
    ACK = The Acknowledge number is valid.
  \item
    PSH = The receiver should Push the data to the receiving application as
    quickly as possible. Not really used, usually set.
  \item
    SYN = Synchronize sequence numbers to initiate a connection.
  \item
    FIN = Finished sending data.
\end{itemize}

\begin{table}[h]
\begin{center}
\begin{tabular}{|c|c|c|} \hline
\emph{Tcpdump flag}  & \emph{Acronym} & \emph{Means} \\
\hline\hline
A & ACK & Acknowledge \\
F & FIN & Finish \\
P & PSH & Push \\
R & RST & Reset \\
S & SYN & Synchronize \\
U & URG & Urgent \\
. &     & No flags set \\
\hline
\end{tabular}
\caption{Tcpdump flags}
\label{tab:flags}
\end{center}
\end{table}


The following lines is the start of a telnet session:

\tiny
\begin{verbatim}
11:09:58.607781 fladnag.uccs.edu.1042 > odorf.uccs.edu.telnet: S 185302925:185302925(0) win 512 <mss 1460>
11:09:58.607781 odorf.uccs.edu.telnet > fladnag.uccs.edu.1042: S 2527100738:2527100738(0) ack 185302926 win 15360 <mss 1460>
\end{verbatim}
\normalsize

The sequence starts by Gandalf sending a synchronization message to Odorf.
Explanation:
\begin{itemize}
  \item
    185302925:185302925(0) means that the starting sequence is the 
    first number, and the implied ending sequence is the second.
    (0) means that there are zero bytes of data.
  \item
    win 512 means that the window size of the receiver is 512 bytes.
    The window size is the maximum number of bytes which the sender is
    willing to accept currently. If a large window is offered, there
    may be more packets in transition and a higher bandwidth is achieved.
    In this case the window size is tiny, on Linux it is usually
    16KB. The window size is different from OS to OS, for example the
    4.2BSD has 2048 bytes, 4.3BSD has 4096 bytes. Solaris and 
    AIX uses 8192 or 16384 bytes.
  \item
    $<$mss 1460$>$ means that the Maximum Segment Size (MSS) is 1460 bytes.
    The ethernet frame (MTU) is 1500 bytes, and with a IP and TCP header of
    20 bytes each this leaves 1460 bytes for TCP payload.
\end{itemize}
    
Odorf returns its synchronization number. It also acknowledges the start of the
next sequence number, 185302926, and sends its window size and MSS.
From here on, the tcpdump program will only show the relative sequence number to
make it easier to read, as is indicated by the `1' in the next tcpdump line.

Usually another field is present, the Type Of Service field. The TOS field is
usually not used, and it seems like Linux does not use it.

\tiny
\begin{verbatim}
11:09:58.607781 fladnag.uccs.edu.1042 > odorf.uccs.edu.telnet: . ack 1 win 31744 (DF)
\end{verbatim}
\normalsize

Gandalf now ACKs the synchronization number from Odorf. The data transfer can now begin.
This handshake before any data transfer is called the \textbf{three way handshake}.
Lets summarize the steps:
\begin{enumerate}
\item
  The client sends a TCP message with the SYN flag and its synchronization number.
\item
  The server responds with a SYN and its own synchronization number. The server
  also ACKs the synchronization number received from the client by increasing the number
  by one.
\item
  The client ACKs the synchronization number received from the server by increasing it.
\end{enumerate}

The following data is part of the login sequence. The trailing (DF) means that
the Don't Fragment flag is set, and the packet must not be fragmented on its
way to the destination. If it is not possible for a router on the way to keep the packet
unfragmented, it will send the ICMP `host unreachable' message to the originating host.
The host has then to step down to a smaller payload, and retransmit.

\tiny
\begin{verbatim}
11:09:58.667781 fladnag.uccs.edu.1042 > odorf.uccs.edu.telnet: P 1:28(27) ack 1 win 31744 (DF)
11:09:58.687782 odorf.uccs.edu.telnet > fladnag.uccs.edu.1042: . ack 28 win 15360
\end{verbatim}
\normalsize

The above two lines show that data is flowing from Fladnag to Odorf,
and I will skip the rest of the trace until the connection is closed.
The `P 1:28(27)' may need some explanation. The P is the Push flag
mentioned above. The 1:28(27) means that the sequence number starts at
1, and the expected ACK sequence number should be 28. There are 27
bytes of data.

\tiny
\begin{verbatim}
11:10:36.747974 odorf.uccs.edu.telnet > fladnag.uccs.edu.1042: F 721:721(0) ack 141 win 15360
11:10:36.747974 fladnag.uccs.edu.1042 > odorf.uccs.edu.telnet: . ack 722 win 31744 (DF)
11:10:36.787974 fladnag.uccs.edu.1042 > odorf.uccs.edu.telnet: F 141:141(0) ack 722 win 31744
11:10:36.787974 odorf.uccs.edu.telnet > fladnag.uccs.edu.1042: . ack 142 win 15360
\end{verbatim}
\normalsize

As it is Odorf that closes the connection, it will send the FIN flag.
Gandalf sees the flag, returns an ACK and then sends a FIN itself.
Both the client and the server must ACK the FIN message before the session is terminated.

\subsection{Telnet from an intranet host behind DPF to internet}

The DPF has to work more if the telnet occurs from one of the hosts
behind the DPF host. 
Section~\ref{sec:forwarding} explains what the DPF has to do.

The same setup is used as in Section~\ref{sec:telnet-out}, with the exception that
the hosts on the intranet has to be added to the incoming PF chain. 
This is because the packets have to pass the incoming PF
before anything else is considered. 

Adding hosts on the intranet to the incoming PF is done by:

\tiny
\begin{verbatim}
gandalf# ipfwadm -I -a accept -S 128.198.9.0/24 -D 0/0
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
\end{verbatim}
\normalsize

Note the -S 128.198.9.0/24 which means that all IP addresses which
match 128.198.9.0 ANDed with 24 bits of ones (starting at the most
significant bit) are
allowed to pass the incoming PF. Bilbo has an IP address of 0x80c60974 which
ANDed with 0xffffff00 is 0x80c60900. This matches the rules IP
address of 0x80c60900.

If a telnet session is opened from Bilbo to Odorf, it will have
the following effect on the PFs.

\tiny\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1030 -> telnet

gandalf# ipfwadm -F -l
IP firewall forward rules, default policy: reject
type  prot source               destination          ports
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1030 -> telnet

gandalf# ipfwadm -O -l
IP firewall output rules, default policy: reject
type  prot source               destination          ports
acc   all  gandalf.uccs.edu     anywhere             n/a
acc   all  fladnag.uccs.edu     anywhere             n/a
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1030 -> telnet
\end{verbatim}\normalsize

The last line of each PF listing are the specific rules added by the
DPF for a telnet session from Bilbo to Odorf.
The PF can be set to accept a bidirectional rule, which means that either
Bilbo:port -$>$ Odorf:port is accepted or Odorf:port -$>$ Bilbo:port.
However, I have not found out how to set ipfwadm to show this.

Let's check the status of the DPF:

\tiny
\begin{verbatim}
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP  Forward 128.198.9.116:1030    128.198.4.144:23        82418  116
\end{verbatim}
\normalsize

As it is indicated below the expiration time is set to the default
timeout value when the telnet session is closed.

\tiny
\begin{verbatim}
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP  Forward 128.198.9.116:1030    128.198.4.144:23        11398  116
\end{verbatim}
\normalsize

\section{Test of FTP}
\label{sec:ftp}

FTP uses the TCP protocol. 
It opens a connection to port 21 on the remote server, where commands
are sent and responses are received.
If data is to be received from the server, a PORT command is sent to the server
with the port number to receive data on the client. The client then
listens to the port, and waits for the server to start sending data
from port 20.

This will not work with the DPF! This is because the port numbers used
are different than the ones used for the command connection, and worst
of all it is the server that initiates the data connection. As the DPF
never is notified, it will not add a rule to the PFs and thus the data
packets from the server will be dumped. The FTP client will eventually
timeout without receiving any data.

In order to use FTP there are two solutions:

\begin{itemize}
  \item
    Scan the client-server command data for the PORT keyword, and
    setup rules in the affected PFs for the port specified.
  \item
    Newer versions of the FTP client/server also understands the PASV command, which
    makes the server listen, and the client to initiate the connection.
\end{itemize}

If the second solution is used, the DPF does not need any modifications,
but if older versions of FTP clients are used, then something must be
done. I have chosen to implement the first approach to make the DPF
work with all FTP clients.

The DPF thus scans for the PORT command in the control-stream to the
remote server and installs appropriate rules.
Figure~\ref{fig:ftp} shows the actual PORT command sent to the host
Odorf corresponding to the tcpdump of Section~\ref{sec:ftpdump}. In
this scenario the data port on Bilbo is 40001. The PORT command is
sent as six bytes with the IP address bytes first and then the port
number as two bytes. Bilbos IP address is 128.198.9.144, 
and the port is 40001, which in two byte format is 156*256+65. The
PORT command is thus: PORT 128,198,9,144,156,65.

\subsection{FTP from intranet host behind DPF to internet}
\label{sec:ftpdump}

The following is the starting setup:
\tiny
\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a

gandalf# ipfwadm -F -l
IP firewall forward rules, default policy: reject

gandalf# ipfwadm -O -l
IP firewall output rules, default policy: reject
type  prot source               destination          ports
acc   all  gandalf.uccs.edu     anywhere             n/a
acc   all  fladnag.uccs.edu     anywhere             n/a
\end{verbatim}
\normalsize

Now, if a FTP session is started from Bilbo to Odorf, and after the user
has typed DIR, the following rules are in effect:

\tiny
\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1031 -> ftp
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       40001 -> ftp-data

gandalf# ipfwadm -F -l
IP firewall forward rules, default policy: reject
type  prot source               destination          ports
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1031 -> ftp
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       40001 -> ftp-data

gandalf# ipfwadm -O -l
IP firewall output rules, default policy: reject
type  prot source               destination          ports
acc   all  gandalf.uccs.edu     anywhere             n/a
acc   all  fladnag.uccs.edu     anywhere             n/a
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       1031 -> ftp
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       40001 -> ftp-data
\end{verbatim}
\normalsize

The status so far is visualized in Figure~\ref{fig:ftp}, where the client
has sent the PORT command to the server, and the DPF has intercepted this message
and allows the server to negotiate a connection to the client.

\begin{figure}[h]
  \epsfig{figure=ftp.eps,width=15cm}
  \caption{FTP port command.}
  \label{fig:ftp}
\end{figure}

Let's check the status of the DPF:

\tiny
\begin{verbatim}
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP  Forward 128.198.9.116:40001   128.198.4.144:20         1399   51
TCP  Forward 128.198.9.116:1031    128.198.4.144:21        79398  117
\end{verbatim}
\normalsize

As the data-connection is closed when the data is transferred, the expiration
time is set to the default time for a closing tcp connection.

When the session is closed, the expiration time should have decreased:

\tiny
\begin{verbatim}
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP  Forward 128.198.9.116:1031    128.198.4.144:21        11217  117
\end{verbatim}
\normalsize

\subsection{TCP dump of FTP transfer}

In the following trace the initial handshaking already is done, and
the trace shows what happens after the user has sent the command DIR to
the remote server. The actual PORT command cannot be seen as I have
not enabled the `dump data' switch of the tcpdump which prints the
data in the packets\footnote
{The tcpdump included in the Debian distribution seems to be
  compiled without this switch, as by enabling it, a huge security
  hole is made as passwords to remote logins can be displayed.}.

\tiny
\begin{verbatim}
12:13:08.677104 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: S 3245975086:3245975086(0) win 512 <mss 1460> [tos 0x8]
12:13:08.677104 bilbo.uccs.edu.40001 > odorf.uccs.edu.ftp-data: S 256500895:256500895(0) ack 3245975087 win 15360 <mss 1460>
12:13:08.677104 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: . ack 1 win 15360 [tos 0x8]
12:13:08.677104 odorf.uccs.edu.ftp > bilbo.uccs.edu.1031: P 204:257(53) ack 70 win 15360 (DF) [tos 0x10]
12:13:08.697105 bilbo.uccs.edu.1031 > odorf.uccs.edu.ftp: . ack 257 win 15360 [tos 0x10]
12:13:08.727105 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: P 1:1025(1024) ack 1 win 15360 (DF) [tos 0x8]
12:13:08.727105 odorf.uccs.edu.ftp > bilbo.uccs.edu.1031: P 257:281(24) ack 70 win 15360 (DF) [tos 0x10]
12:13:08.747105 bilbo.uccs.edu.1031 > odorf.uccs.edu.ftp: . ack 281 win 15360 [tos 0x10]
12:13:08.747105 bilbo.uccs.edu.40001 > odorf.uccs.edu.ftp-data: . ack 1025 win 15360 [tos 0x8]
12:13:08.747105 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: P 1025:1265(240) ack 1 win 15360 (DF) [tos 0x8]
12:13:08.747105 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: F 1265:1265(0) ack 1 win 15360 [tos 0x8]
12:13:08.747105 bilbo.uccs.edu.40001 > odorf.uccs.edu.ftp-data: . ack 1266 win 15360 [tos 0x8]
12:13:08.757105 bilbo.uccs.edu.40001 > odorf.uccs.edu.ftp-data: F 1:1(0) ack 1266 win 15360 [tos 0x8]
12:13:08.757105 odorf.uccs.edu.ftp-data > bilbo.uccs.edu.40001: . ack 2 win 15360 [tos 0x8]
\end{verbatim}
\normalsize

The trace shows the three-way-handshake between Odorf:ftp-data(20) and
Bilbo:40001 which is the ephemeral port number chosen by the ftp
client. If the PORT command would not have been intercepted by the DPF,
the three-way-handshake would not have been successful as the incoming
PF never would have allowed the SYN message to pass to Bilbo.

After the three-way-handshake the DIR data is sent to Bilbo, and the
last lines show the closing sequence. 

The new field in the tcpdump-dump output is the Type Of Service (TOS), 
whose bit-mapped values are shown in table~\ref{tab:tos}. By looking
at the TOS bits above, one can see that the control connection
requests a TOS of 0x10, minimize delay. The data connection on the
other hand requests a TOS of 0x08, maximize throughput.

\begin{table}[h]
\begin{center}
\begin{tabular}{|l|r|} \hline
\emph{Bit mask}  & \emph{Meaning} \\
\hline\hline
0x02 & Minimize-monetary cost \\
0x04 & Maximize-reliability \\
0x08 & Maximize-throughput \\
0x10 & Minimize-delay \\
\hline
\end{tabular}
\caption{TOS bits}
\label{tab:tos}
\end{center}
\end{table}


\subsection{TCP dump of passive FTP session}

Let's see what happens when a passive FTP session is used.
I have omitted the synchronization sequence and only shows the difference to
the usual behavior.
The sequence shows that it is Bilbo (the client) that starts
the three-way-handshake. This allows the DPF to append a rule in the
incoming PF, and the data resulting from the DIR command is sent to Bilbo.
The command port is 1034 on Bilbo, and the data port is 1035. Note
that the data is not transferred from the usual data port of 20 from
the server, this time an ephemeral port of 40000 is chosen on the server.

\tiny
\begin{verbatim}
12:41:16.146458 bilbo.uccs.edu.1035 > odorf.uccs.edu.40000: S 764469348:764469348(0) win 512 <mss 1460>
12:41:16.146458 odorf.uccs.edu.40000 > bilbo.uccs.edu.1035: S 2298515571:2298515571(0) ack 764469349 win 15360 <mss 1460>
12:41:16.146458 bilbo.uccs.edu.1035 > odorf.uccs.edu.40000: . ack 1 win 15360
12:41:16.146458 bilbo.uccs.edu.1034 > odorf.uccs.edu.ftp: P 43:49(6) ack 224 win 15360 (DF) [tos 0x10]
12:41:16.146458 odorf.uccs.edu.ftp > bilbo.uccs.edu.1034: P 224:277(53) ack 49 win 15360 (DF) [tos 0x10]
12:41:16.166458 bilbo.uccs.edu.1034 > odorf.uccs.edu.ftp: . ack 277 win 15360 [tos 0x10]
12:41:16.186458 odorf.uccs.edu.40000 > bilbo.uccs.edu.1035: P 1:1025(1024) ack 1 win 15360 (DF) [tos 0x10]
12:41:16.186458 odorf.uccs.edu.ftp > bilbo.uccs.edu.1034: P 277:301(24) ack 49 win 15360 (DF) [tos 0x10]
12:41:16.186458 odorf.uccs.edu.40000 > bilbo.uccs.edu.1035: P 1025:1265(240) ack 1 win 15360 (DF) [tos 0x10]
12:41:16.186458 odorf.uccs.edu.40000 > bilbo.uccs.edu.1035: F 1265:1265(0) ack 1 win 15360 [tos 0x10]
12:41:16.186458 bilbo.uccs.edu.1035 > odorf.uccs.edu.40000: . ack 1266 win 15360 [tos 0x8]
12:41:16.206458 bilbo.uccs.edu.1034 > odorf.uccs.edu.ftp: . ack 301 win 15360 [tos 0x10]
12:41:16.206458 bilbo.uccs.edu.1035 > odorf.uccs.edu.40000: F 1:1(0) ack 1266 win 15360 [tos 0x8]
\end{verbatim}
\normalsize

\section{Test of NFS}
\label{sec:nfs}
Network File System is used to share a common hard-disk partition on the network 
as it were a local drive. 
Historically NFS used UDP as NFS was mainly used on intranets,
where the traffic can be controlled and thus implicitly
congestion can be avoided. Another reason for using UDP is that UDP 
has less overhead than
TCP and thus a better performance should be possible. Newer version of
NFS servers and clients support both UDP and TCP, and by using TCP it is better suited
for NFS mounted\footnote
{The Unix jargon is to `mount' a NFS shared drive.}
 remote drives that are not on the intranet.

The NFS is useful if two joint corporations need to share data in an
easy manner. It would be very bad if a third rivalling company successfully
mounts the drive and copies all the data!

The DPF can help, as the only allowed incoming packets on the server are from
the hosts that are allowed to share the drive. Note that this is not really 100\% safe
as an intruder might try to use IP-spoofing, discussed in 
Section~\ref{sec:ip-spoofing}, to mount the drive. 
Even though DPF allows NFS to be used in a safer way,
the DPF cannot help if the packets themselves are modified. 
This is true for all network applications. If some
really secured data is to be stored on a host, the only safe way is to put
the computer in an environment without any network and where physical access to
the host is hard to gain.

I use NFS as an example of a more complex situation where the DPF
might be used.
There are several things that has to work in order to make
the NFS work behind a DPF firewall. The DPF does not have to be
modified to make NFS work.

\subsection{How NFS works}
\label{sec:nfs-details}
I will not go into the NFS very deeply, just touch on the parts that are of concern
to get it working. As stated earlier, NFS is a way to access remote data
as it was local. This is shown in Figure~\ref{fig:nfs}
Most of the information about NFS is fetched from~\cite{tcp:stevens},
which is an absolutely excellent reference.

\begin{figure}[h]
  \epsfig{figure=nfs.eps,width=15cm}
  \caption{NFS client and server}
  \label{fig:nfs}
\end{figure}

As many other network programs, NFS uses Sun Remote Procedure Call (RPC), an
application protocol that enables different computers with different 
architecture and operating systems to communicate with each other.

In short, a RPC call works as if the procedure call is done on the local computer, 
when in fact a function id and the parameters are sent to a server which
executes the corresponding function with the supplied parameters and
then returns the result. To make this work the data has to written 
in a byte and bit independent fashion. 

When using RPC programs, the easiest way to connect to a remote server would 
have been to connect to certain known ports, which are hard-coded into the RPC 
application. This would certainly work, but it would be difficult to make
changes. Therefore all RPC servers registers the ports to
a registrar program called \emph{portmapper}.

The portmapper program is then queried by the RPC clients about which
ports the wanted services resides on.

The NFS server is stateless, meaning that it does not keep track of what
files the clients are accessing and what they are doing.
This works well on the commands that are \emph{idempotent}. Idempotent
commands are commands that can be executed more than once without
any ill effects. Some commands are not idempotent, like removing a file.

Example: If a command is sent to the NFS server to remove a file and the 
result is lost by congestion (and assuming that the command was successfully 
received and executed by the server), the client will timeout and reissue the command. 
The second time the command is to be executed, the server will not respond by
OK as the file does not exist anymore, and the client will erroneously report
that the file could not be removed!

The problem with non-idempotent commands are usually solved by caching
the non-idempotent commands and their results. 
If the client reissues the same command, the result
from the cache is returned instead of executing the command again.

NFS is the actual protocol used to transfer the data, but in order to use 
a remote file system, it has to be mounted first. This is done by the \emph{mount} 
program.

The steps taken to mount a NFS file-system are described in the
sequence below. The numbers correspond to the numbers in Figure~\ref{fig:mount}.

\begin{figure}[h]
  \epsfig{figure=mount.eps,width=15cm}
  \caption{Steps taken to mount a remote file-system}
  \label{fig:mount}
\end{figure}

\begin{enumerate}
  \item
    The \emph{mountd} daemon registers itself on the server with the portmapper 
    program which is started when the system boots.
  \item
    The \emph{mount} program is executed on the client to mount a remote server. 
    First the mount must know to what mount daemon it should send the request
    to. This is done by querying the portmapper on the server.
  \item
    The portmapper returns the port of the mount daemon.
  \item
    The mount program sends a request to the server that it wants to mount
    some parts of the server's file-system. The server checks if the client
    has access to the file-systems in question (several file-systems
    may be exported by the server) by checking the IP address of
    the client. 
  \item
    The mount daemon sends back a file-handle to the file-system in question.
  \item
    The file-handle is passed to the NFS portion of the client kernel. When actual
    files are later accessed, the NFS will use the file-handle to
    reference files.
\end{enumerate}

\subsection{Using NFS from intranet host behind DPF}

In the test NSF Bilbo will mount a file-system on Odorf. Gandalf is the router
with the DPF.

To be able to export any file-systems at all, the nfs and mount daemons have to be 
started on Odorf. Also, the file /etc/exports on Odorf have to be modified to allow Bilbo
to mount a file system.

\tiny
\begin{verbatim}
frodo# cat /etc/exports
# See exports(5) for a description.
# This file contains a list of all directories exported to other computers.
# It is used by rpc.nfsd and rpc.mountd.

/tmp            bilbo(rw,no_root_squash) 
\end{verbatim}
\normalsize

The above means that Bilbo is allowed to access the /tmp directory of
Odorf.
The IP address of Bilbo (or any other host) is resolved either through
the /etc/hosts file or a DNS lookup. The order in which this is done is
specified in the /etc/host.conf file.
The keywords in the parenthesis are options for the mount daemon. In this case they
mean that Bilbo has read and write access, and the superuser root is not 
mapped to the user id of -1\footnote
{The number is then resolved to a name in the /etc/passwd file. 
-1 is usually `nobody'.}
when writing. 
The last option is a safety feature to avoid that the `root' user on a mounted 
file-system accidentally erases the files on the mounted drive, as the system will
not give permissions for user `nobody' to erase `root' files.

As the research computers used are unknown to UCCS's DNS resolver, the
host names has to be specified in the /etc/hosts below.

\tiny\begin{verbatim}
frodo# cat /etc/hosts
#
# hosts         This file describes a number of hostname-to-address
#               mappings for the TCP/IP subsystem.  It is mostly
#               used at boot time, when no name servers are running.
#               On small systems, this file can be used instead of a
#               "named" name server.  Just add the names, addresses
#               and any aliases to this file...

# For loopbacking.
127.0.0.1       localhost

128.198.4.143   oblib.uccs.edu          oblib obli
128.198.4.144   odorf.uccs.edu          odorf odor
128.198.4.145   fladnag.uccs.edu        fladnag flad

128.198.9.116   bilbo.uccs.edu          bilbo bilb
128.198.9.117   frodo.uccs.edu          frodo frod
128.198.9.118   gandalf.uccs.edu        gandalf gand
\end{verbatim}\normalsize

The order keyword in the /etc/host.conf file determines in what order
the hosts are looked up. In this case the /etc/hosts file is searched
first. Bind is the name of the DNS daemon.

\tiny\begin{verbatim}
frodo# cat /etc/host.conf
order hosts,bind
\end{verbatim}\normalsize

Now we can try to mount the file-system on /tmp of Odorf to /mnt on Bilbo, and
see the status of the mounted drive.

\tiny\begin{verbatim}
bilbo# mount -t nfs odorf:/tmp /mnt
bilbo# df
Filesystem         1024-blocks  Used Available Capacity Mounted on
/dev/hda4             560060  438806    92325     83%   /
odorf:/tmp            560060  210009   321122     40%   /mnt
\end{verbatim}\normalsize

Now, lets see what rules the DPF has added:

\tiny\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       911 -> sunrpc
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       912 -> 947
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       914 -> sunrpc
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       913 -> 2049
gandalf# ipfwadm -F -l
IP firewall forward rules, default policy: reject
type  prot source               destination          ports
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       911 -> sunrpc
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       912 -> 947
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       914 -> sunrpc
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       913 -> 2049
gandalf# ipfwadm -O -l
IP firewall output rules, default policy: reject
type  prot source               destination          ports
acc   all  gandalf.uccs.edu     anywhere             n/a
acc   all  fladnag.uccs.edu     anywhere             n/a
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       911 -> sunrpc
acc   tcp  bilbo.uccs.edu       odorf.uccs.edu       912 -> 947
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       914 -> sunrpc
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       913 -> 2049
gandalf# cat /proc/net/ip_dynamic 
Pro Firewall Source IP:Port        Dest IP:Port          Expires Hash
TCP  Forward 128.198.9.116:912     128.198.4.144:947        6862  226
UDP  Forward 128.198.9.116:911     128.198.4.144:111       24848  234
UDP  Forward 128.198.9.116:913     128.198.4.144:2049      25698  244
UDP  Forward 128.198.9.116:914     128.198.4.144:111       24861  247
\end{verbatim}\normalsize

As discussed in Section~\ref{sec:nfs-details} and in shown Figure~\ref{fig:mount}, the
mount program first queries the RPC portmapper on port 111 (shown as sunrpc in
the ipfwadm listings) to find out the TCP port of the mountd daemon which in
this case is on port 947. The second RPC call is a bit unclear. It
might be a call to find out the TCP port number of the nfs daemon.
The Linux version of NFS can use either UDP or TCP, but if nothing is
specified it defaults to UDP. It also seems like the Linux version of
the mount program prefers to use TCP when communicating with the
mountd daemon.

The ports used by the different daemons running on Odorf can be shown
by running the rpcinfo program shown below. The services used when
mounting the NFS drive in this case
were the UDP version of portmapper at port 111, the TCP version of
mountd at port 947 and the UDP version of NFS at port 2049. 

\tiny
\begin{verbatim}
frodo# rpcinfo -p odorf
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100003    2   udp   2049  nfs
    100003    2   tcp   2049  nfs
    100005    1   udp    945  mountd
    100005    1   tcp    947  mountd
\end{verbatim}
\normalsize

Now, if the rules appended to the PF chain are allowed to timeout,
(by not accessing anything on the mounted drive) only the following
rules are in effect:

\tiny
\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
\end{verbatim}
\normalsize

All rules have timed out. The only rule left is the statically added
rule.

If some operations are performed in the mounted file-system, see 
Section~\ref{sec:dump-nfs}, the following rules show up:

\tiny\begin{verbatim}
gandalf# ipfwadm -I -l
IP firewall input rules, default policy: reject
type  prot source               destination          ports
acc   all  localnet/24          anywhere             n/a
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       913 -> 2049
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       1000 -> sunrpc
acc   udp  bilbo.uccs.edu       odorf.uccs.edu       1001 -> 945
\end{verbatim}\normalsize

Here we can see that the NFS port 913 on Bilbo again has been connected to
the NFS port 2049 on Odorf.

It seems like it works OK to use NFS behind the DPF host.

\subsection{TCP dump of NFS}
\label{sec:dump-nfs}

Refer to Section~\ref{sec:nfs-details} about the following steps.
Bilbo asks the portmapper about the port number of the mount daemon,
and the portmapper returns the answer. The data of the actual 
transaction is not shown.

\tiny\begin{verbatim}
12:15:18.679911 bilbo.uccs.edu.911 > odorf.uccs.edu.sunrpc: udp 56
12:15:18.689911 odorf.uccs.edu.sunrpc > bilbo.uccs.edu.911: udp 28
\end{verbatim}\normalsize

Bilbo connects to the mount daemon with TCP and the request is negotiated
by Odorf. The server allows Bilbo to mount a file system.
The second connect on port 914 to the RPC is a bit unclear, but it
might be used to find out the address of the TCP port of NFS on Odorf.

\tiny\begin{verbatim}
12:15:18.689911 bilbo.uccs.edu.912 > odorf.uccs.edu.947: S 3230347247:3230347247(0) win 512 <mss 1460>
12:15:18.689911 odorf.uccs.edu.947 > bilbo.uccs.edu.912: S 1621665009:1621665009(0) ack 3230347248 win 15360 <mss 1460>
12:15:18.689911 bilbo.uccs.edu.912 > odorf.uccs.edu.947: . ack 1 win 15360
12:15:18.689911 bilbo.uccs.edu.912 > odorf.uccs.edu.947: P 1:85(84) ack 1 win 15360 (DF)
12:15:18.709911 odorf.uccs.edu.947 > bilbo.uccs.edu.912: . ack 85 win 15360
12:15:18.819912 odorf.uccs.edu.947 > bilbo.uccs.edu.912: P 1:65(64) ack 85 win 15360 (DF)
12:15:18.819912 bilbo.uccs.edu.914 > odorf.uccs.edu.sunrpc: udp 56
12:15:18.819912 odorf.uccs.edu.sunrpc > bilbo.uccs.edu.914: udp 28
12:15:18.819912 bilbo.uccs.edu.912 > odorf.uccs.edu.947: F 85:85(0) ack 65 win 15360
12:15:18.819912 odorf.uccs.edu.947 > bilbo.uccs.edu.912: . ack 86 win 15360
12:15:18.819912 odorf.uccs.edu.947 > bilbo.uccs.edu.912: F 65:65(0) ack 86 win 15360
12:15:18.829912 bilbo.uccs.edu.912 > odorf.uccs.edu.947: . ack 66 win 15360
\end{verbatim}\normalsize

A file handle of the mounted file system is passed to Bilbo.
Note that the tcpdump program does not show the port of the sender, instead
it shows the XID number. The XID is the transaction ID of the RPC request.
Every time the client sends a RPC request it increases the XID, and the
server responds with the same XID. If the XID is the same, the client
uses the response, otherwise it discards the packet.

\tiny\begin{verbatim}
12:15:18.849912 bilbo.uccs.edu.5051675f > odorf.uccs.edu.nfs: 104 getattr [|nfs]
12:15:18.859912 odorf.uccs.edu.nfs > bilbo.uccs.edu.5051675f: reply ok 96 getattr [|nfs]
12:15:27.179960 bilbo.uccs.edu.50516760 > odorf.uccs.edu.nfs: 104 getattr [|nfs]
12:15:27.179960 odorf.uccs.edu.nfs > bilbo.uccs.edu.50516760: reply ok 96 getattr [|nfs]
12:15:27.189960 bilbo.uccs.edu.50516761 > odorf.uccs.edu.nfs: 112 readdir [|nfs]
12:15:27.189960 odorf.uccs.edu.nfs > bilbo.uccs.edu.50516761: reply ok 100 readdir [|nfs]
\end{verbatim}\normalsize

The above tcpdump shows when the NFS filehandle of the mounted drive
is passed to Bilbo. Note the increasing XID. 

\section{ARP and RARP}
\label{sec:arp}
Address Resolution Protocol is used to get the physical ethernet
address of an ethernet card. The ethernet card has an unique hardware
address stored in eprom set by the manufacturer of the device.
The ethernet card receives a packet when
the packet is addressed to the device, the packet is a general broadcast, or the
device is set to promiscuous mode. A router places its ethernet device
in promiscuous mode in order to receive packets which perhaps has to be
forwarded. This makes the IP layer receive and process much more packets than
it usually does.

The DPF has actually nothing to do with ARP and RARP, but as ARP
queries are quite common when sniffing for packets, I thought it might
be worthwhile to include a brief note anyway.

RARP is the opposite of ARP, the host knows its ethernet address but
wants to find its IP address. The rarpd daemon must be running on
some server to answer the query. Today RARP is usually replaced by the BOOTP
protocol.

ARP is not supported by the DPF, as arp packets don't contain any
useful data which can be misused. Only hosts on the same segment of the
ethernet can send arp requests. ARP packets are thus handled at such a
low level that the DPF is never involved at all.

ARP is initiated if the IP layer does not know which hardware address
matches an IP address. In the following example Fladnag wants to find
the hardware address of Odorf. Odorfs ARP layer responds with the
hardware address. The ARP request is a broadcast with the
question: ``Who has IP address a.b.c.d ?'', and any host that matches
the address will answer. If the same IP address is used on several
hosts problems arise!

\tiny
\begin{verbatim}
12:12:59.147052 arp who-has odorf.uccs.edu tell fladnag.uccs.edu
12:12:59.147052 arp reply odorf.uccs.edu is-at 8:0:9:cc:5b:64
\end{verbatim}
\normalsize

The ARP cache is flushed now and then (it must be possible to replace
a faulty ethernet device on a host), and by judging on the timestamps
of the following arp packets, the flush seems to happen every five
minutes on Linux. 128.198.4.254 is the default router of Odorf. 

\tiny
\begin{verbatim}
12:19:32.761391 arp who-has fladnag.uccs.edu tell odorf.uccs.edu
12:19:32.761391 arp reply fladnag.uccs.edu is-at 8:0:9:cc:6b:3d
12:19:32.761391 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:19:37.761420 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:19:42.761450 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:19:47.761479 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:19:47.761479 arp reply 128.198.4.254 is-at 0:0:c:17:bd:d
12:25:32.743274 arp who-has fladnag.uccs.edu tell odorf.uccs.edu
12:25:32.743274 arp reply fladnag.uccs.edu is-at 8:0:9:cc:6b:3d
12:25:32.743274 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:25:32.743274 arp reply 128.198.4.254 is-at 0:0:c:17:bd:d
12:30:41.084682 arp who-has odorf.uccs.edu tell fladnag.uccs.edu
12:30:41.084682 arp reply odorf.uccs.edu is-at 8:0:9:cc:5b:64
12:31:32.724926 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:31:37.724950 arp who-has 128.198.4.254 tell odorf.uccs.edu
12:31:37.724950 arp reply 128.198.4.254 is-at 0:0:c:17:bd:d
\end{verbatim}
\normalsize


%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "main"
%%% End: 
