My wife and I had run out for errands and had stopped at a D'Angelo sub shop. We were just about to get out of the car when the phone rang. My wife rolled her eyes but I took the call because, well, because that's what I do. Somebody has a problem, I try to answer the phone.
This was a long time customer. He explained that he had someone that needed remote access to an aplication running on port 7000 on a SCO machine. He said it was working fine within his office, but that he couldn't get remote access working. We did the usual things: telnet localhost 7000 (yup, that connected), ssh out to another box and try telnet back on 7000 (which just hung). I asked him to double check his router, and he did, but still no luck.
"Oh wait a minute,", I said, "you said this was a SCO box? You mean that old test box you've had for years?"
This guy sells accounting software and some of his customers still run on SCO. Most of them use Linux now, but he keeps the SCO up and running for testing and support. But I was pretty sure that box had never been connected to the internet.
"You need a default route. Packets can get to it, but it doesn't know how to send them back."
This comes up fairly frequently. It also happens sometimes with remote TCP printers: if you haven't given them a gateway address, they can't communicate back to you. Packets need routes.
But why? That's what my caller wondered. Why doesn't it just figure out where to send the packets?
Well, for starters, the only machines any box can talk to are machines on its local physical lan. So obviously it needs to send any other packets through a router. Is it supposed to guess where the router is?
No, of course not. Either somebody tells it (route add) or it finds out through some protocol like router broadcasts. But if it doesn't have either of those advantages, it's blind and dumb.
But is it really? Let's look at some tcpdump output.
On my Mac, I first ssh'ed to a local (on my network) Linux box. In another Window on the Mac, I typed "sudo tcpdump -e host redhat1". Over on the Linux box, I simply tapped the space bar (to avoid a lot of packets). Here's the result:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes 07:55:59.946527 00:16:cb:8d:48:f7 (oui Unknown) > 00:c0:f0:6b:b4:18 (oui Unknown), ethertype IPv4 (0x0800), length 114: 192.168.4.21.50050 > redhat1.ssh: P 1320087778:1320087826(48) ack 1103513747 win 65535
07:55:59.947496 00:c0:f0:6b:b4:18 (oui Unknown) > 00:16:cb:8d:48:f7 (oui Unknown), ethertype IPv4 (0x0800), length 114: redhat1.ssh > 192.168.4.21.50050: P 1:49(48) ack 48 win 10336 07:55:59.947565 00:16:cb:8d:48:f7 (oui Unknown) > 00:c0:f0:6b:b4:18 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.4.21.50050 > redhat1.ssh: . ack 49 win 65535
Those hex digits following the date on each line should look familiar to you: those are MAC addresses. One of them is the address of the MacBook itself (00:16:cb:8d:48:f7) and the other is the RedHat box. Specifically, if I run "arp -a", I can see that, yes, that Mac address matches redhat1:
$ arp -a redhat1 (192.168.4.237) at 0:c0:f0:6b:b4:18 on en0 [ethernet] router (192.168.4.249) at 0:8:0:c0:fa:4 on en0 [ethernet] $
Now what about if I go somewhere off-lan?
$ sudo tcpdump -e host website tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes 07:57:51.020660 00:16:cb:8d:48:f7 (oui Unknown) > 00:08:00:c0:fa:04 (oui Unknown), ethertype IPv4 (0x0800), length 106: 192.168.4.21.50027 > website.ssh: P 3652278386:3652278426(40) ack 193102205 win 65535
07:57:51.057326 00:08:00:c0:fa:04 (oui Unknown) > 00:16:cb:8d:48:f7 (oui Unknown), ethertype IPv4 (0x0800), length 106: website.ssh > 192.168.4.21.50027: P 1:41(40) ack 40 win 16752 07:57:51.057409 00:16:cb:8d:48:f7 (oui Unknown) > 00:08:00:c0:fa:04 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.4.21.50027 > website.ssh: . ack 41 win 65535
If you look carefully at those, you see that the packets are identified as coming from my router ( 0:8:0:c0:fa:4). We'd expect that - that is the only place they could come from.
So, back to our port 7000 problem. If the SCO box knows where the packets come from, why doesn't it just use that knowledge to route them back?
Well, I suppose it could. Someone could write an IP stack that configured routes from level 2 header information when there was nothing better to go by. That's pretty much what a switch does for its ports. I wouldn't want that feature on a computer, though: I like to be able to tear down routing entirely when I want to.
So I guess the answer to "Why?" is just "Because that's the way it is. Add the route, and my wife and I will go split a sub."
Got something to add? Send me email.
More Articles by Anthony Lawrence © 2009-11-06 Anthony Lawrence