-----------------[ Reading ]----------------- Depending on your learning style, you may choose to read the textbook's detailed descriptions first, or first read Shalunov's concise explanations, then the textbook. Textbook: Ch. 4 (ARP) and Ch.5 (IP). You may skip details about IPv6 at first reading; we only looked at IPv4 in class. Shalunov's book: Ch. 3 (IP). The chapter starts with explaining the design choices of connecting two LANs together, and the thinking that was the likely origin of IP, the *global* addressing scheme, as opposed to the *local* MAC-based addressing. Ch. 3.1.3 concisely describes ARP. You may skip discussion in 3.2.5--8 on a first reading. -----------------[ BGP ]----------------- Skim Shalunov's Ch. 10 on BGP, to get an idea of what the protocol does. Sadly, we cannot see BGP in action: one must be an ISP to do so, or get the feed of advertised routes from an ISP. Attacking BGP is not theoretical. Here is a talk describing attacks by injecting false routes: https://www.defcon.org/images/defcon-16/dc16-presentations/defcon-16-pilosov-kapela.pdf (if you have trouble getting this file, look in local/ of the class directory). "Wired" wrote about it: https://www.wired.com/2008/08/revealed-the-in/ Smaller scale events occur, too: https://bgpmon.net/accidentally-stealing-the-internet/ -----------------[ IP blocks ]----------------- In class, we used an address inside MIT's domain to look up MIT's block of IP addresses. My first try was to ask for the address of www.mit.edu, but that only led us to computers clearly outside MIT: firefly:~ user$ dig www.mit.edu ; <<>> DiG 9.8.3-P1 <<>> www.mit.edu ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41078 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 9, ADDITIONAL: 9 ;; QUESTION SECTION: ;www.mit.edu. IN A ;; ANSWER SECTION: www.mit.edu. 1800 IN CNAME www.mit.edu.edgekey.net. www.mit.edu.edgekey.net. 60 IN CNAME e9566.dscb.akamaiedge.net. e9566.dscb.akamaiedge.net. 20 IN A 23.192.14.93 So my next attempt is to ask for an MX record, i.e., "which server do I need to contact to send mail to someuser@mit.edu"? firefly:~ user$ dig mx mit.edu ; <<>> DiG 9.8.3-P1 <<>> mx mit.edu ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17663 ;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 8, ADDITIONAL: 1 ;; QUESTION SECTION: ;mit.edu. IN MX ;; ANSWER SECTION: mit.edu. 120 IN MX 100 dmz-mailsec-scanner-3.mit.edu. mit.edu. 120 IN MX 100 dmz-mailsec-scanner-4.mit.edu. mit.edu. 120 IN MX 100 dmz-mailsec-scanner-7.mit.edu. mit.edu. 120 IN MX 100 dmz-mailsec-scanner-1.mit.edu. ;; ADDITIONAL SECTION: dmz-mailsec-scanner-1.mit.edu. 1800 IN A 18.9.25.12 So: firefly:~ user$ whois 18.9.25.12 NetRange: 18.0.0.0 - 18.255.255.255 CIDR: 18.0.0.0/8 NetName: MIT NetHandle: NET-18-0-0-0-1 Parent: () NetType: Direct Assignment OriginAS: AS3 Organization: Massachusetts Institute of Technology (MIT-2) RegDate: 1994-01-01 Updated: 2010-09-28 Ref: https://whois.arin.net/rest/net/NET-18-0-0-0-1 Such huge address ranges used to be called "Class A". Note the really low number of the AS (autonomous system, the number an ISP gets for its routers as a group, used by BGP and other routing protocols; see https://en.wikipedia.org/wiki/Autonomous_system_%28Internet%29) -----------------[ Routes ]----------------- A router is a computer connected to two or more networks. A Linux box with several Ethernet interfaces (e.g., one built-in, one added via USB) is already a router capable of sophisticated packet forwarding and rewriting logic; the only difference from an expensive professional router is hardware optimizations for performance. Routing is essentially taking a packet, looking at its destination IP address, and deciding along which of the router's links to send it onwards. Say, when a Dartmouth border router sees a packet for 8.8.8.8, it decides to send it to Vermont Telecom (and not back into the Dartmouth network). VTel looks at the address 8.8.8.8 and finds the peering ISP that appears to have a better path to Google, and so on. A route is looked up by an IP range, or, more precisely, by an IP prefix (so many bits of an IP address fixed, the rest vary to create the range). In IP routing, only prefix ranges are considered. This lookup gets you an interface to send the packet out of, and, when the target is not immediately in your LAN---that is, this is not the packet's last hop to the target---a *gateway*: the IP address of the router that will forward the packet onward. ISPs advertize routes for the IP blocks they serve---to other ISPs they peer with. E.g., VTel advertises that it knows what to do with packets addressed to the 129.170.0.0--129.170.255.255 range, 129.170/16 for short. Once this propagates through the peer ISPs' routers via their BGP sessions, it will be handed to these ISPs' peers, and so on, until every ISP on Earth knows how to send packets either to 129.170/16 or to some prefix thereof, like 129/8 (routes are aggregated whenever possible on today's Internet; the ISP that advertises the 129/8 block had better know what to do with each sub-block of it). A general principle of IP routing is that the most specific route (the route with the longest fixed prefix) wins. Suppose we had routes for 129.170/16, 129.170.212/22, and 0/0, and we get a packet for 129.170.215.100, then the second route wins (even though the first one matches too, the second's match is longer); for 129.170.17.4, the first route wins; and for 8.8.8.8, the third one wins (after the first two fail to match). -----------------[ Netmasks == Network prefixes ]----------------- There are two equivalent forms to specify a prefix-based IP range: with /N notation (where N is an integer between 0 and 32) or with a *netmask*. The netmask is 4 bytes long, with exactly the first N bits set to 1 and the rest to 0. For example: /24 corresponds to 255.255.255.0 (in bits, 11111111 11111111 11111111 00000000) /22 is 255.255.252.0 (in bits, 11111111 11111111 11111100 00000000) /8 is 255.0.0.0 (in bits, 11111111 00000000 00000000 00000000) /16 is 255.255.0.0 (in bits, 11111111 11111111 00000000 00000000) /32 is 255.255.255.255 (in bits, 11111111 11111111 11111111 11111111) /30 is 255.255.255.252 (in bits, 11111111 11111111 11111111 11111100) (/30 gives you a range of four IP addresses, but only two would be in use, because the addresses with all 0s and all 1s after the network prefix have special uses: all 1s is the broadcast address, and all 0s is not used, by convention). What is /12 ? Write out the address range covered by 172.16/12 . -----------------[ Why ARP? ]----------------- We humans cannot remember MAC addresses. At best, we can remember IP addresses, and even so prefer domain names (and use the global Domain Name System to translate names to IP addresses). But to put a packet out on an Ethernet link, a computer (more specifically, its OS kernel) must start the packet with the destination MAC address. But you are normally only supplying the target's IP address, not its MAC (say, to ping) or even the name (translated to an IP address automatically). So where does the MAC at the start of the packet come from? It comes from ARP (address resolution protocol). The kernel, upon receiving a call with an IP address (I'll call it target IP) does the following: - compares the IP address with entries in the kernel's routing table and selects the longest match (if any). - If this matching route has a gateway IP address specified, then the kernel checks if that gateway IP has a MAC address in the kernel's ARP table. If a MAC is there, the kernel uses it. If not, the kernel sends a who-has ARP request for that IP, listens to the response, and uses the MAC address from the ARP reply. The MAC is entered into the ARP table for the gateway IP. Thus the outgoing packet's first 6 bytes, dst MAC, is the MAC corresponding to the gateway's IP. Inside the IP header, the target IP is unchanged. If the ARP who-has request does not receive a reply, you may see "Host unreachable" error. - If this matching route has no gateway, then the kernel looks up the target IP in its ARP table. If a MAC address for the target IP is there, it uses it. If not, the kernel sends a who-has ARP request for the target IP, and uses the MAC in the response for the dst MAC. The MAC is entered into the ARP table for the target IP. Thus the dst MAC in the Ethernet header is the MAC of the target IP on the local network. - If there is no matching route, you may see the "Network unreachable" error. What if there are no entries in the routing table at all? Then the kernel may send the ARP request for the target IP anyway, or report an error. Routers differ in such edge cases. Remember, though, that sending a packet to an IP address over Ethernet always involves getting a MAC address to put into the packet: either the target's or the gateway's. Exercise: In Wireshark, observe ARP packets (use Wireshark's display filter text box to enter "arp" as a filter). How many MACs and IPs do you see? Which one do you see most frequently (and why?). -----------------[ ARP security == NONE ]----------------- There is no authentication in the ARP protocol. Whoever can send ARP packets fast enough to have its responses heard first wins. Switches can try to watch for such behavior---too many unsolicited ARP replies---and block ports from which such packets come---but most don't. There are tools to send fake ARP replies. Read about such a tool and the theory behind it here: http://sid.rstack.org/arp-sk/ (for explanations, skip to "Quick guide of what you can do with ARP") -----------------[ Building a small Linux network ]----------------- Here are the steps I took in class to build a small Linux LAN. I dropped my Wi-Fi connection from my Mac laptop, connected a Thunderbolt Ethernet adapter, and got my connectivity through my Linux laptop, using it as a router. I configured my Thunderbolt Ethernet adapter manually, to have the address of 192.168.57.100 (and netmask of 255.255.255.0 aka /24, conventional for 192.168.x.x private networks) I brought a Debian Linux laptop to serve as my router. This laptop has a built-in Ethernet interface called eth0 . I connected this interface to the Dartmouth wired network. I get my root shell with "sudo bash". NOTE: None of these steps will work with Linux's NetworkManager running. NetworkManager is a piece of software that takes over networking and tries to guess what the user wants. It typically guesses wrong for routing or for anything other than connecting to a single Wi-Fi network. I disabled my NetworkManager with "service network-manager stop" or "/etc/init.d/network-manager stop" Always start with this command if you want to play with networking. Wiring diagram: Debian +-----------+ +--- .100 (Mac) 129.170.48.0/22 | | 192.168.57.0/24 | ------------------|eth1 eth0|---------------- LAN switch --|--- (empty port) <- gw .48.1 |DHCP .1 | | +-----------+ +--- (empty port) (In this diagram, .48.1 stands for 129.170.48.1, the Dartmouth network gateway serving the room; .1 for 192.168.57.1, the Linux box interface connected to my switch; .100 for 192.168.57.100 for Thunderbolt Ethernet on my Mac, connected to my switch; DHCP on the interface means that it gets its address dynamically via DHCP requests) First, I need to get an IP address for eth0. I do this by sending a DHCP request with a tool called dhclient. Just in case, I kill any dhclient process running previously: root@debian:~# /etc/init.d/network-manager stop root@debian:~# killall dhclient root@debian:~# dhclient -v eth0 Internet Systems Consortium DHCP Client 4.2.2 Copyright 2004-2011 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ Listening on LPF/eth0/28:d2:44:6a:0a:60 Sending on LPF/eth0/28:d2:44:6a:0a:60 Sending on Socket/fallback DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 7 DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 12 DHCPREQUEST on eth0 to 255.255.255.255 port 67 DHCPOFFER from 129.170.48.1 DHCPACK from 129.170.48.1 bound to 129.170.50.153 -- renewal in 8861 seconds. Checking: root@debian:/home/sergey# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 28:d2:44:6a:0a:60 inet addr:129.170.50.153 Bcast:129.170.51.255 Mask:255.255.252.0 <<-- my IP address inet6 addr: fe80::2ad2:44ff:fe6a:a60/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Note the netmask 255.255.252.0. So this is a /22, just as in Sudikoff. So I got 129.170.50.153. Normally, I would be able to ping external hosts like 8.8.8.8 at this point; but the college interferes with traffic on ports in classrooms, intercepting packets going to the outside, and redirecting any web request to the "Web Auth" site. This may be a part of "CALEA compliance", i.e., being able to legally claim that the network is not available to anyone not affiliated with the college. So if you start a browser, you get redirected to the "Network Registration" page, and your MAC will be recorded alongside with your student ID. Then normal routing will happen. We will discuss the security implications of this scheme later in this class. Now I can ping. It's a good, steady ping you get on a good wired network: root@debian:~# ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_req=1 ttl=54 time=11.5 ms 64 bytes from 8.8.8.8: icmp_req=2 ttl=54 time=11.6 ms 64 bytes from 8.8.8.8: icmp_req=3 ttl=54 time=11.5 ms 64 bytes from 8.8.8.8: icmp_req=4 ttl=54 time=11.9 ms ^C --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3005ms rtt min/avg/max/mdev = 11.535/11.679/11.987/0.226 ms My IP address of 129.170.50.153 is not the only thing I got from dhclient! I also got the default gateway and the DNS server IP addresses, and dhclient ran a script that configured my system to use them. Evidence: root@debian:~# cat /etc/resolv.conf domain dartmouth.edu search dartmouth.edu nameserver 129.170.17.4 <-- this is my DNS server This is my routing table with the default router: root@debian:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 129.170.48.1 0.0.0.0 UG 0 0 0 eth0 <-- default route 129.170.48.0 0.0.0.0 255.255.252.0 U 0 0 0 eth0 <-- route to LAN So my packets to any IP address within 129.170.48/22 will go directly to that target IP, provided that ARP requests for that IP bring back the MAC address of a computer that answers to this IP. My packets to 8.8.8.8, though, will first trigger an ARP lookup of 129.170.48.1's MAC, and will go out with that MAC as the first 6 bytes of the Ethernet header. Another Linux utility, "ip", which is a part of a later IProute2 package, shows routes with / notation rather than netmask notation: root@debian:~# ip route show default via 129.170.48.1 dev eth0 129.170.48.0/22 dev eth0 proto kernel scope link src 129.170.50.153 Since I already ran a ping to the outside world, ARP request for the gateway has been made and recorded in the ARP table: root@debian:~# arp -a life-sciences.remsen1-crt.dartmouth.edu (129.170.48.1) at 00:26:98:2b:18:c1 [ether] on eth0 Incidentally, since I arm arp -a without -n (no name lookup), the arp tool makes a request for the name of 129.170.48.1 (if any). The network is nice enough to provide a name (this is called "reverse name resolution", from an IP to a name, if any). So we see that name, life-sciences.remsen1-crt.dartmouth.edu, alongside with the address. Now it's time to add another interface for my internal network (i.e., my Mac) to connect to. Plugging in my USB adapter into the Debian laptop, I check "dmesg" and see it was added as "eth1". root@debian:~# ifconfig eth1 192.168.57.1 up That brings in an automatic route for 192.168.57/24, as per RFC 1918 convention: root@debian:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 129.170.48.1 0.0.0.0 UG 0 0 0 eth0 129.170.48.0 0.0.0.0 255.255.252.0 U 0 0 0 eth0 192.168.57.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 <-- new route root@debian:~# ip route show default via 129.170.48.1 dev eth0 129.170.48.0/22 dev eth0 proto kernel scope link src 129.170.50.153 192.168.57.0/24 dev eth1 proto kernel scope link src 192.168.57.1 I run a ping to my Mac, which I configured manually to be 192.168.57.100 on the Thunderbolt Ethernet interface (en4). After this: root@debian:/home/sergey# arp -a life-sciences.remsen1-crt.dartmouth.edu (129.170.48.1) at 00:26:98:2b:18:c1 [ether] on eth0 ? (192.168.57.100) at 40:6c:8f:39:68:cb [ether] on eth1 Note that reverse name resolution of 192.168.57.100 fails, because no software anywhere is configured to provide it. So we get "?" Checking what eth1 looks like after some pings: root@debian:/home/sergey# ifconfig eth1 eth1 Link encap:Ethernet HWaddr 00:50:b6:0d:f2:61 inet addr:192.168.57.1 Bcast:192.168.57.255 Mask:255.255.255.0 inet6 addr: fe80::250:b6ff:fe0d:f261/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1132 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:84159 (82.1 KiB) TX bytes:62899 (61.4 KiB) <-- some packets sent & received So I have two interfaces, but my Debian laptop does not yet act as a router. Its kernel must be told to start forwarding packets _not_ addressed to it, rather than discarding them (which is the default behavior for an end-point host). Luckily, Linux provides a simple interface, /proc, to change the kernel behavior, by writing to a pseudo-file /proc/sys/net/ipv4/ip_forward . There is no such file on disk; the kernel intercepts reads and writes to /proc/* files and serves up its interval variables under these names instead to commands that would normally read files---and lets you set these variables with commands that normally write to files. root@debian:~# cat /proc/sys/net/ipv4/ip_forward 0 (no routing) Make it route! root@debian:~# echo 1 > /proc/sys/net/ipv4/ip_forward (and now it does:) root@debian:~# cat /proc/sys/net/ipv4/ip_forward 1 So from my Mac (192.168.57.100) I am now pinging 8.8.8.8. The pings go out, but no responses come back. Sadly, I cannot forward a Wireshark window from Debian to show on my Mac; with Linux this is trivial, but Apple broke this functionality. So instead of Wireshark I use a text-only utility tcpdump, which uses the same mechanism to capture and filter packets, but runs in the terminal. Let's have a look at what comes in on the internal inteface eth1: root@debian:/home/sergey# tcpdump -i eth1 -n tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 18:28:08.200705 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 2325371622:2325371814, ack 1326965115, win 276, options [nop,nop,TS val 1812589 ecr 3508417668], length 192 18:28:08.201020 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 192:416, ack 1, win 276, options [nop,nop,TS val 1812589 ecr 3508417668], length 224 18:28:08.201147 IP 192.168.57.100.64786 > 192.168.57.1.22: Flags [.], ack 192, win 4090, options [nop,nop,TS val 3508417735 ecr 1812589], length 0 18:28:08.201237 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 416:624, ack 1, win 276, options [nop,nop,TS val 1812589 ecr 3508417735], length 208 18:28:08.201297 IP 192.168.57.100.64786 > 192.168.57.1.22: Flags [.], ack 416, win 4089, options [nop,nop,TS val 3508417735 ecr 1812589], length 0 18:28:08.201305 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 624:816, ack 1, win 276, options [nop,nop,TS val 1812589 ecr 3508417735], length 192 18:28:08.201371 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 816:1024, ack 1, win 276, options [nop,nop,TS val 1812589 ecr 3508417735], length 208 18:28:08.201499 IP 192.168.57.100.64786 > 192.168.57.1.22: Flags [.], ack 624, win 4089, options [nop,nop,TS val 3508417735 ecr 1812589], length 0 18:28:08.201537 IP 192.168.57.100.64786 > 192.168.57.1.22: Flags [.], ack 816, win 4090, options [nop,nop,TS val 3508417735 ecr 1812589], length 0 18:28:08.201548 IP 192.168.57.1.22 > 192.168.57.100.64786: Flags [P.], seq 1024:1216, ack 1, win 276, options [nop,nop,TS val 1812589 ecr 3508417735], length 192 18:28:08.201617 IP 192.168.57.100.64786 > 192.168.57.1.22: Flags [.], ack 1024, win 4089, options [nop,nop,TS val 3508417735 ecr 1812589], length 0 My screen fills up in an instant! Of course: I am connected into my Linux laptop over SSH from my Mac, and every character that shows in my Mac terminal is sent over eth1 from the Debian laptop. So the more output I generate by running commands on the Debian laptop, the more packets I see! It's a vicious circle. Luckily, it's easy to filter out these packets, as tcpdump accepts a filtering expression. SSH connections use port 22, so I ask to not show me the packets that come from or to this port on eth1: root@debian:/home/sergey# tcpdump -i eth1 -n not port 22 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 18:28:17.686942 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 189, length 64 18:28:17.765505 IP 192.168.57.100.62740 > 8.8.8.8.53: 35975+ A? 14-courier.push.apple.com. (43) 18:28:18.635280 IP 192.168.57.100.52074 > 8.8.8.8.53: 41535+ A? userstream.twitter.com. (40) 18:28:18.691941 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 190, length 64 18:28:19.066596 IP 192.168.57.100.62447 > 8.8.8.8.53: 61383+ A? safebrowsing.google.com. (41) 18:28:19.697196 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 191, length 64 18:28:20.702489 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 192, length 64 18:28:21.707155 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 193, length 64 18:28:22.166728 IP 192.168.57.100.62447 > 8.8.8.8.53: 61383+ A? safebrowsing.google.com. (41) 18:28:22.708257 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 194, length 64 18:28:23.713529 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 195, length 64 18:28:24.715986 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 196, length 64 So you see ping requests (ICMP echo requests) coming in, and some other queries (we'll understand them later). So they go from my Mac 192.168.57.100 and reach my Debian router. Do they go out to the Dartmouth network? That interface, eth0, sees a lot of traffic, because it faces the college network. So I apply a filter for what I want to see, "icmp", from the start: root@debian:/home/sergey# tcpdump -i eth0 -n icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 18:28:35.752540 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 207, length 64 18:28:36.757795 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 63140, seq 208, length 64 ^C So the packets are leaving for 8.8.8.8 as they should. The Debian router is doing its job of forwarding them. But, of course, any packets from (or to) a 192.168.x.x range get dropped by the Internet routers, as these are not supposed to leave private networks (a lot of private networks use these ranges; routing back to them would be impossible, because how would ISPs know which private network these packets came from?) So they get dropped, because of their source IP being 192.168.57.100. We need to use one final trick. This trick is called NAT, Network Address Translation. This trick is used by all home routers that get just one and exactly one publicly routable IP address from the ISP serving that home, and must use it for any outgoing connection, for any of the multiple devices in the home. The trick is this: when a device with a private IP address sends a packet, the router makes a note of the source IP and other features of the packet in a special table (NAT table). What goes into the NAT table? Well, it's a bit messy and heuristic, and depends on the protocol. In the simplest case of TCP and UDP packets, the source and destination ports typically allow a pretty good mapping of responses back to the original request. For ICMP, which has no ports but only id and sequence numbers, this is a bit trickier. For protocols like VoIP, it is trickier yet. A NAT box must have modules with heuristic logic for especially tricky protocols, or they simply don't work over NAT. VoIP and SIP are good examples. Some game protocols are another. After making a note of the packet in the NAT table, the router rewrites the source IP on the packet to its public IP address (in our case, this will be 129.170.50.153) and sends the packet onwards. When the response arrives (it can now be routed back to 129.170.50.153), the router consults its NAT table, figures out which internal computer this response is meant for, and rewrites the _destination_ IP of the response packet to that internal IP (in our case, 192.168.57.100). This is heavy packet rewriting, but it's the only hope for small IP networks that can only afford to purchase just one publicly routable IP address from an ISP, or need to hide several machines behind one such address. This functionality is present in the Linux kernel's subsystem called Netfilter/IPtables. To activate it, I use this command: root@debian:/home/sergey# iptables -t nat -A POSTROUTING -o eth0 -s 192.168.57/24 -j MASQUERADE I made a few mistakes when typing this rule. To clear the NAT tables of my Debian laptop, I used "iptables -t nat -F" (-t for "table", -F for "flush"). It means: "any packet that goes out of eth0 and has the source IP in the range of 192.168.57/24 should be rewritten to appear to come from the source IP of that interface eth0 [in our case, 129.170.50.153]; notice of the original source IP [192.168.57.100] where it came from should be made, so that packets that look like a response could be sent back to that original IP." This is called a "masquerading NAT". Now we see ping requests leaving out of eth0 _and_ being responded to! root@debian:/home/sergey# tcpdump -i eth0 -n icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 18:32:08.120061 IP 129.170.50.153 > 8.8.8.8: ICMP echo request, id 64676, seq 30, length 64 18:32:08.139140 IP 8.8.8.8 > 129.170.50.153: ICMP echo reply, id 64676, seq 30, length 64 18:32:09.125296 IP 129.170.50.153 > 8.8.8.8: ICMP echo request, id 64676, seq 31, length 64 18:32:09.161049 IP 8.8.8.8 > 129.170.50.153: ICMP echo reply, id 64676, seq 31, length 64 18:32:10.130491 IP 129.170.50.153 > 8.8.8.8: ICMP echo request, id 64676, seq 32, length 64 18:32:10.145982 IP 8.8.8.8 > 129.170.50.153: ICMP echo reply, id 64676, seq 32, length 64 18:32:11.135387 IP 129.170.50.153 > 8.8.8.8: ICMP echo request, id 64676, seq 33, length 64 18:32:11.147218 IP 8.8.8.8 > 129.170.50.153: ICMP echo reply, id 64676, seq 33, length 64 18:32:12.140672 IP 129.170.50.153 > 8.8.8.8: ICMP echo request, id 64676, seq 34, length 64 18:32:12.159406 IP 8.8.8.8 > 129.170.50.153: ICMP echo reply, id 64676, seq 34, length 64 They all appear to come from the publicly routable address of eth0, 129.170.50.153, on the Debian laptop/router, but they actually come from my Mac, 192.168.57.100. Yet they get rewritten to appear to come from 129.170.50.153. But on the eth1 of the same machine we see a different picture. The requests come from 192.168.57.100, and the replies appear to be addressed to it directly: root@debian:/home/sergey# tcpdump -i eth1 -n icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 18:32:31.205790 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 64676, seq 53, length 64 18:32:31.217344 IP 8.8.8.8 > 192.168.57.100: ICMP echo reply, id 64676, seq 53, length 64 18:32:32.206000 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 64676, seq 54, length 64 18:32:32.220396 IP 8.8.8.8 > 192.168.57.100: ICMP echo reply, id 64676, seq 54, length 64 18:32:33.206231 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 64676, seq 55, length 64 18:32:33.218500 IP 8.8.8.8 > 192.168.57.100: ICMP echo reply, id 64676, seq 55, length 64 18:32:34.211310 IP 192.168.57.100 > 8.8.8.8: ICMP echo request, id 64676, seq 56, length 64 18:32:34.223028 IP 8.8.8.8 > 192.168.57.100: ICMP echo reply, id 64676, seq 56, length 64 Yet no such direct response to a 192.168.x.x host would survive on the Internet. What we are seeing is packets rewritten by the NAT logic of the Linux on the Debian box. So we now have the connection from the Mac laptop, using an internal private IP address, to the Internet, thanks to NAT and the forwarding done by the Debian laptop. This is the essence of all private LANs, including "Dartmouth Public". One little piece of configuration remains on my Mac before I can use my browser, my Skype, my Twitter app, and any other app. I need to configure a DNS server for the Mac. I set it manually, through the control panel, to Google's public 8.8.8.8. Now I can browse and tweet and skype. I have a fully functional routed LAN, with Dartmouth as my "ISP". In future classes, we will look more into these mechanisms, and will get to implement some of them in C code.