I often find myself working out of a café.
Nearly all of my work requires an internet connection at some point or another, which means that most of the cafés I frequent have some sort of WiFi that I take advantage of1. While I’m not generally one to complain about the quality of free WiFi in the small, locally run establishments in my neighbourhood, it does frustrate me that they are often misconfigured to the point where the staff must reset the router every few hours.
Generally, the cause of this is simple: an improperly configured DHCP lease expiration time.
A DHCP Primer
The Dynamic Host Configuration Protocol (DHCP) is how your standard public wireless networks allow a client (usually a laptop, smartphone, or tablet) to request the necessary configuration parameters from the server (in the case of a café, a wireless router). DHCP is actually a successor2 to an older protocol, BOOTP, which is a fact that will become important shortly.
It’s All About That IP
One of the more important parameters that the router (we’ll assume it’s a router and not something fancier from this point onward) sends back to the requesting client is a local IP address, which most of the time looks something like
192.168.0.123. The point of this address is to uniquely identify the client on the local network so that data payload being transmitted is correctly routed to-and-from the appropriate destination. Otherwise, the router would have no way of knowing which device on the local network should receive which packets: every device on a TCP/IP-based network must have a unique unicast address.
This IP address, among other information, is sent back in the
DHCPOFFER stage of the DHCP negotiation, and is encapsulated in a variable length UDP packet4:
This packet is, for the most part, almost identical to the original BOOTP packet, but includes a few DHCP specific extensions, most notably the ability for a client to request a particular IP address during the
DISCOVER phase, and the ability for a client and a server to agree on lease time (during either
DHCPREQUEST) for which that address will be considered bound to the client and unavailable to any other device that joins the local network.
Finite Address Space
Due to the finite number of available IP addresses5 in a given subnet pool and the finite memory that a router has access to, there are only so many IP addresses that can be assigned in a single local network. For most non-commercial grade routers, this means that a grand total of 256 addresses (from
192.168.1.255 if we keep our class C address example from before) are available. Since class C networks generally reserve addresses ending in
255 for broadcast purposes, we’re left with an effective 254 addresses that may be assigned.
For typical home networks, 254 addresses is more than enough: even in a household with a half dozen family members, each with three personal devices (e.g. laptop, tablet, mobile phone) and a few household items such as network-aware televisions, sound systems, a Roku/Apple TV, etc., we’re still left with 200+ unused addresses, ensuring ample room for the foreseeable future6.
Networks with a large number of client devices, however, can burn through those addresses within minutes.
It’s All So Very Exhausting
So what happens when you’ve got 300+ people at a conference, all attempting to get on the wireless network during the morning coffee break? Well, network congestion (queueing delay/packet loss) effects aside, there’s a very real chance that the first 254 people will get online just fine.
If the router and network they’re connecting to hasn’t been properly configured, however, every subsequent person will have no such luck due to the exhaustion of assignable addresses. That’s a bummer, of course, and hopefully the organizers or the networking people they’ve hired are able to perform a resubnetting (and add more equipment!) to extend the space of available addresses7, or they will be confronted by quite a few angry conference-goers.
Dynamic Networks and Lease Expirations
Some networks are highly dynamic, in that the number of devices that are connected varies in a short amount of time. A great example of this is your typical café that provides wireless internet for its patrons.
These highly dynamic networks often suffer a similar address exhaustion problem, but not due to hundreds of people attempting to access the network simultaneously. Rather, they exhaust the pool of available addresses gradually throughout the day, due to a subtle but obvious fact: a wireless router does not know8 the difference between a device disconnecting from the network (e.g. you’ve left the building and gone home), and simply having no traffic routed to device in question.
As the day goes on, more and more addresses are scooped up by people connecting to the local wireless network, many of whom are only on-site for a brief amount of time. At one point the last available address is assigned, and the moment that every barista dreads occurs: a customer complains that “The WiFi isn’t working”.
As many who have been in this situation can attest to, the naïve solution is typically quite effective: by restarting the router, the DHCP server’s memory is cleared9, and the previously assigned addresses are nullified. Clients that were connected to the router at the time the restart occurred momentarily lose their connection, and then renegotiate with the DHCP server once it has come back online for a new (sometimes the same, depending on the circumstances) address and associated lease time.
Depending on the foot traffic in the establishment, though, some of these cafés go through several restarts a day. And then you realize that the IT Crowd wasn’t a comedy, it was a biodrama.
Can We Prevent All This Router Restarting?
The reason most of these dynamic-but-low-density networks run out of addresses is due to a very simple oversight: the DHCP lease time that a commodity router is configured with by default is an appropriate one for a home, but not for a business. While the lease length may differ across the various brands and models available, most will have it set to something between 24-72 hours. That makes sense for a home environment (heck, you could kick it up to a week or even a month, depending on how many guests you entertain), but makes absolutely no sense for an environment where the average time spent connected to the local network is most likely in the 1-2 hour range.
Thus, a possible solution is a combination of increasing the number of available addresses, probably to their maximum, and ensuring that the DHCP lease is commensurate with the average amount of time a device will be connected to the network: say two hours for an average café or restaurant. Both of these options can usually be configured within the administrative interface for the router in question. While each manufacturer will have their own interface, it will more often than not resemble something like the iconic Linksys configuration panels:
With these modifications in place, most busy cafés/restaurants should be able to reduce the number of times where a hapless employee is required to pull the plug on the router to ensure that customers are able to utilize the wireless local network. Some tweaking of the DHCP lease time may be required, but you generally don’t want to go too short – the original DHCP RFC explicitly specified a 1-hour minimum lease time, which was later removed in RFC 2132, but going below one hour is asking for trouble10.
Determining Your DHCP Client Lease Time
If you’re in a café or restaurant where you believe the DHCP server may be poorly configured for the volume and frequency of guests coming through the door, it’s relatively easy to determine the lease time that your client (we’ll assume laptop) has been given.
Linux-based operating systems can differ wildly, but the DHCP information is usually written to a file on disk that is updated when new connections are made. This file is typically located at
/var/lib/dhclient/dhclient-<interface>.leases for RedHat/CentOS based systems, and at
/var/lib/dhcp/dhclient.<interface>.leases for Debian-based systems. Other distributions may place these files in slightly different locations, but the idea is similar.
Assuming your distribution of choice runs some variant of
dhclient and that your wireless card is configured to listen on the
en0 network interface, the contents of
/var/lib/dhcp/dhclient.en0.leases on a Debian-based system should resemble this:
Note that the DHCP lease length is listed as the value to the
dhcp-lease-time, and according to the DHCP specification, the unit for this field is seconds.
For OS X, we can fetch the contents of the UDP packet that the DHCP server responded with during the
DHCPACK phase of the protocol once the connection has been established.
Assuming again that
en0 is the interface that your wireless card is currently listening on:
will return the packet payload. Your results will differ, but they should look something like this:
While there’s a lot going on in that payload data, the
lease_time field is what we’re primarily concerned with. The value is specified as an unsigned 32-bit integer and has the hexadecimal representation
0x127500, which is
1209600 in base 1011. That means that this particular lease is valid for 14 days. As you may have surmised, this is most definitely too long a lease time for an establishment that receives significant foot traffic.
Much to my chagrin, they continue to reset their router on an almost daily basis.
- Always enable a Virtual Private Network (VPN) connection when using a public wireless network. You never know who might be listening in, especially with the generally shoddy networking equipment (and default passwords!) that many public access points utilize. ⏎
- In a somewhat odd symbiosis, parts of BOOTP are used to bootstrap the newer DHCP functionality, and DHCP is then able to provide BOOTP functionality when required. ⏎
There are a total of three IP address ranges (usually called “blocks”) that have been allocated for private use by the IETF, but the
192.168.0.0/16block is the most common. If you're not familiar with the
/16notation, you'll want to brush up on classless inter-domain routing (CIDR). We're going to skip the equivalent IPv6 discussion for the sake of simplicity, but if you're interested, there's an equivalent Unique Local Address (ULA) specification. It turns out that most local, private networks are quite well served by IPv4, and thus IPv6 is not often encountered on public WiFi networks. ⏎
- Thanks to UDP being connectionless, it is rather well suited for the purposes of broadcasting connection bootstrap information from a DHCP server so that all connected devices may receive it without requiring prior configuration. ⏎
- Again, we're mostly concerned with the IPv4 address space. IPv6's ULA specification allows for a subnet 264 bits in size, which is roughly large enough to uniquely identify every single grain of sand on our planet. ⏎
- I guess when your toaster is able to speak to your AC unit and your freezer thanks to the Internet of Things, we might need to revisit this. ⏎
- Hopefully the equipment they used actually lets them do this — many stock non-commercial routers don't have the ability. ⏎
- This is not entirely true: more expensive routers will often have the ability for the DHCP server to send a ping to connected clients on regular intervals to determine which assigned addresses may be released (telling the difference between a timeout and a disconnect is yet another problem that is left as an exercise to the reader), but most public WiFi networks on commodity hardware don't have this ability/are not configured to do so. ⏎
- Somewhat humourously, higher quality routers will ensure that their DHCP lease assignments persist between restarts. So if you have a good quality router that is configured rather poorly, this method will most likely not work! ⏎
- While you may be tempted to simply set a very, very low lease expiration time, say 5 minutes, you may find that some applications (e.g. some mail clients) running on your laptop/mobile phone/tablet aren't very fond of having the local IP address change so frequently while they are active. ⏎
If you're using a Bash-compatible shell, you can convert a hexadecimal value to the equivalent decimal representation via the built-in method for evaluating arithmetic expressions, including base conversions :
echo $((0x127500)) # prints 1209600. Note that the typical
0xprefix can be replaced with
16#, indicating explicitly that the input is a base-16 number, and will produce the same result. The
ARITHMETIC EVALUATIONsection of the bash man page includes additional details, if you're into that kind of thing. ⏎