If you have a Linux laptop, try
% ssh -l oxyX frenulum.lcs.mit.edu
You may wish to consult the Click documenation while working on this lab. You can also find the Click source code on the Click web site http://pdos.lcs.mit.edu/click/.
% clickCopy the following Click configuration (with control-C in your browser), then paste it into your putty window (with Shift-Insert or right-click):
FromDevice(de0, PROMISC true) -> Print("hi") -> Discard;Then type return and control-D. You should see lots of hex output from Click, one packet per line, perhaps like this:
hi: 84 | 0800460d 3fd00007 b3d44300 08004500 0034f69b 4000fb2f hi: 60 | ffffffff ffff0030 65b83cee 08060001 08000604 00010030 hi: 66 | 00e02905 d6230007 b3d44300 08004500 00348be7 40003906You can type control-C to stop Click.
The Click configuration reads all packets from the local Ethernet (with FromDevice) and prints the first 24 bytes of each packet (with Print). The "PROMISC true" argument to FromDevice puts it in promiscuous mode, so that it sees all packets on the local Ethernet, not just the ones addressed to the host you're using. Each packet starts with the 14-byte Ethernet header. For example, the first line in the example above is a packet to Ethernet host 08:00:46:0d:3f:d0, from host 00:07:b3:d4:43:00, and of type IP (0x0800). This page contains descriptions of header formats.
You will find Print useful for debugging. You can add it almost anywhere in a Click configuration to see what packets flow through that part of the configuration.
hi: 106 | 00e02905 d6230007 b3d44300 08004500 005cffa0 40007f06 xx: 106 | 00e02905 d6230007 b3d44300 08004500 005cffa0 40007f06 hi: 60 | ffffffff ffff0007 b3d44300 08060001 08000604 00010007 xx: 60 | ffffffff ffff0007 b3d44300 08060001 08000604 00010007
Run this configuration:
FromDevice(de0, PROMISC true) -> cl :: Classifier(12/0800, 12/0806); cl[0] -> Strip(14) -> CheckIPHeader -> IPPrint("IP") -> Discard; cl[1] -> Print("ARP") -> Discard;
You might see output like this from Click:
ARP: 60 | ffffffff ffff00e0 8103ad99 08060001 08000604 000100e0 IP: 1106485059.379213: 24.61.43.128.49435 > 18.26.4.123.22: . 3382018920:3382018920(0,52,52) ack 579108457 win 33304 ARP: 60 | ffffffff ffff0007 b3d44300 08060001 08000604 00010007This configuration uses IPPrint for the IP packets; IPPrint knows how to parse the IP headers, much like tcpdump. IPPrint expects packets to start with the IP header, so the configuration uses Strip(14) to remove the Ethernet header. IPPrint also requires that packets first be processed by CheckIPHeader to ensure that they are valid IP packets.
The output of your new configuration should look something like this:
IP: 1106484913.008497: 18.18.0.3 > 18.26.4.133: ip-proto-47 UDP: 1106484913.008853: 18.26.4.127.2049 > 18.26.4.123.989: udp 244 TCP: 1106484913.022493: 24.61.43.128.49435 > 18.26.4.123.22: . 3382017972:3382017972(0,52,52) ack 579105741 win 33158 ARP: 60 | ffffffff ffff0002 b315b7bb 08060001 08000604 00010002
When host H1 first tries to send an IP packet to host H2, H1 must find H2's ethernet address using ARP. Host H1 sends out an ARP broadcast containing H2's IP address, and H2 sends back an ARP response containing H2's ethernet address. Here is a configuration that will respond to ARP queries for your IP address. You should replace 18.26.4.X with your IP address.
in :: FromDevice(de0, PROMISC true); out :: Queue -> ToDevice(de0); in -> cl :: Classifier(12/0800, 12/0806 20/0001); cl[0] -> Strip(14) -> CheckIPHeader -> IPClassifier(dst host 18.26.4.X) -> IPPrint("IP") -> Discard; cl[1] -> ARPResponder(18.26.4.X 00:e0:29:05:d6:23) -> Print("ARP resp") -> out;Here's a diagram. The ARPResponder element looks for queries with the indicated IP address, and sends out responses with the indicated Ethernet address. The Classifier sends only ARP queries to the ARP responder (Ethernet type 0x0806 and ARP operation 0001).
Now ping your IP address from you laptop. After a few seconds you should see output like this:
ARP resp: 42 | 0007b3d4 430000e0 2905d623 08060001 08000604 000200e0 IP: 1106752295.767113: 128.30.5.187 > 18.26.4.X: icmp: echo request (2, 15) IP: 1106752301.266950: 128.30.5.187 > 18.26.4.X: icmp: echo request (2, 16)The "ARP resp" line indicates that your Click configuration has sent an ARP response. You will only see one "ARP resp" line, because once the router between your laptop and frenulum sees your ARP response, it stops sending ARP queries. The "IP...icmp: echo request" lines are the ping packets from your laptop. Your laptop will complain "Request timed out" because this Click configuration does not send ping responses.
in :: FromDevice(de0, PROMISC true); out :: Queue -> ToDevice(de0); in -> cl :: Classifier(12/0800, 12/0806 20/0002); aout :: ARPQuerier(18.26.4.X, 00:e0:29:05:d6:23); cl[1] -> [1]aout; aout[0] -> out; cl[0] -> Strip(14) -> CheckIPHeader -> IPClassifier(dst host 18.26.4.X and ip proto icmp) -> IPPrint("in") -> Discard; ICMPPingSource(18.26.4.X, 128.2.222.173) -> SetIPAddress(18.26.4.1) -> IPPrint("out") -> aout;Here's a diagram. When you run this configuration, the output should look like this:
out: 1106498717.503013: 18.26.4.X > 128.2.222.173: icmp: echo request (0, 256) in: 1106498717.523577: 128.2.222.173 > 18.26.4.X: icmp: echo reply (0, 256) out: 1106498718.503018: 18.26.4.X > 128.2.222.173: icmp: echo request (0, 512) in: 1106498718.522998: 128.2.222.173 > 18.26.4.X: icmp: echo reply (0, 512)The configuration uses three new elements. ICMPPingSource generates an ICMP packet once per second. ARPQuerier accepts an IP packet as input, sends ARP queries to resolve the IP address to an ethernet address, and then sends the IP packet. Finally, SetIPAddress sets an IP packet's "address annotation". Every Click packet has an address annotation, which contains the IP address of the host to which a packet should be forwarded. This differs from the packet's destination IP address (in the IP header) when the packet must be forwarded through a router, in this case 18.26.4.1. ARPQuerier queries for the IP address in the address annotation, not the address in the IP header's destination field. Note that the Classifier sends ARP responses to the ARPQuerier (Ethernet type 0x0806 and ARP operation 0002).
You should be able to ping your new configuration from your laptop, and your laptop should receive the replies. Ping should produce output that looks like this:
C:\>ping 18.26.4.X Pinging 18.26.4.X with 32 bytes of data: Reply from 18.26.4.X: bytes=32 time=2ms TTL=254 Reply from 18.26.4.X: bytes=32 time=2ms TTL=254 Reply from 18.26.4.X: bytes=32 time=2ms TTL=254 Reply from 18.26.4.X: bytes=32 time=2ms TTL=254
in :: FromDevice(de0, PROMISC true); out :: Queue -> ToDevice(de0); in -> cl :: Classifier(12/0800, 12/0806 20/0001, 12/0806 20/0002); aout :: ARPQuerier(18.26.4.X, 00:e0:29:05:d6:23); cl[2] -> [1]aout; aout[0] -> out; cl[1] -> ARPResponder(18.26.4.X 00:e0:29:05:d6:23) -> out; cl[0] -> Strip(14) -> CheckIPHeader -> IPClassifier(dst host 18.26.4.X and ip proto tcp and port 80) -> IPPrint("in") -> rw1 :: IPRewriter(pattern 18.26.4.X 50000-60000 68.142.226.37 - 0 1); rw1[0] -> SetIPAddress(18.26.4.1) -> IPPrint("out0") -> aout; rw1[1] -> SetIPAddress(18.26.4.1) -> IPPrint("out1") -> aout;Now go to the URL http://18.26.4.X in your laptop's browser. You should see a familiar website!
Here's a diagram of the redirector configuration. The IPRewriter element modifies incoming TCP HTTP (port 80) packets so that they have destination 68.142.226.37, and sends them back out on the Ethernet. The IPRewriter keeps track of the original packet sources in an internal table, and changes reply packets from 68.142.226.37 so that they are addressed to the original source.
For example, if the original packet had src=10.0.0.1 and dst=18.26.4.X, the IPRewriter changes it to be src=18.26.4.X and dst=68.142.226.37. When a reply packet arrives with src=68.142.226.37 and dst=18.26.4.X, IPRewriter modifies it with src=18.26.4.X and dst 10.0.0.1.
A redirector like this might be useful as a load-balancing front end to a cluster of Web servers. IPRewriter can also be used to implement a network address translator (NAT).
You should also see output like this from Click:
in: 1106504619.659793: 24.61.43.128.62800 > 18.26.4.X.80: S 631525024:631525025(1,64,64) win 65535 out0: 1106504619.659793: 18.26.4.X.51383 > 68.142.226.37.80: S 631525024:631525025(1,64,64) win 65535 in: 1106504619.672205: 68.142.226.37.80 > 18.26.4.X.51383: S 1707715834:1707715835(1,60,60) ack 631525025 win 65535 out1: 1106504619.672205: 18.26.4.X.80 > 24.61.43.128.62800: S 1707715834:1707715835(1,60,60) ack 631525025 win 65535
C:\> telnet 18.26.4.X 25 Trying 18.26.4.X... Connected to nephron.lcs.mit.edu. Escape character is '^]'. 220 cs.cmu.edu SMTP, Problems to: Help@FAC.CS.CMU.EDU