3

I have a little Linux (Ubuntu based) server with 2 network cards, which acts as a router, dhcp, dns server, firewall, etc. One network card is connected to the LAN, while the other is connected to my ISP. When the Internet link is down, I would like to redirect all http requests to my local Apache server, which would display a little webpage informing my LAN users, that their LAN connection is OK, the server itself is OK, only the ISP link is currently down. How would I do that?

  1. I found no reliable way to detect if the Internet connection is down, other than periodically pinging a bunch of external hosts that are known to be up most of the time. (The status of the interface is UP all the time).

  2. What tool should I use for redirection? Iptables? Something else?

2
  • 1
    You should ping your default gateway's IP address.
    – user
    Dec 9, 2013 at 14:30
  • Unfortunately pinging default gateway will usually work, because default gateway for me is a device connected to a radio antenna and that works. The link is broken some devices further (its a radio link to my ISP and another high-speed radio link from my ISP to some station connected to the backbone)
    – Eiver
    Dec 9, 2013 at 14:42

2 Answers 2

3

I found no reliable way to detect if the Internet connection is down, other than periodically pinging a bunch of external hosts that are known to be up most of the time. (The status of the interface is UP all the time).

To know whether your link is active, send an ICMP echo request (also known as "ping") to a known-reliable host at the other end of the link you are trying to test. Usually this will be the ISP's default gateway, but there are other possibilities. If you cannot use the ISP's default gateway for such testing, I'd suggest targetting your ISP's DNS servers; if they are down, things are pretty bad anyway and if you don't need for this to be 100% accurate, that's probably good enough. Remember IP is best-effort only, and ICMP does not have TCP's connection-oriented nature and guarantees.

Don't flood a host with pings unless you have a mutual agreement with the administrator of the remote system. Once every 30 seconds is probably quite enough, possibly increasing when the link is detected as down and decreasing during periods of low use such as during the night. The interval should be chosen based on how quickly you want to respond to a link-down situation and what the remote server's administrator is likely to tolerate. More than one ping every few seconds is almost certainly over the top, and if you don't need an "immediate" response to a link-down situation there's nothing saying you can't test once every few minutes or even more seldom.

What tool should I use for redirection? Iptables? Something else?

Since you are talking about putting up a web page when the link is down, I suspect that you are mostly concerned with web browsing. When browsing the web, using IP addresses directly is the exception.

So set up a local caching DNS resolver, and point your clients to it. Set it to forward to your ISP's DNS servers, or set it to go out and fetch answers on its own based on root hints, that's up to you.

When the link fails, swap out the configuration for the local DNS server for one that is authoritative for the root zone . and answers any A (and possibly AAAA) queries to it with the IP address of your local web server, and issue a configuration reload command. Make sure the local web server is not differentiating based on the requested host name (put the web page in question on the default virtual host). You'd have something like the following in a BIND configuration that gets swapped in when you detect a link failure:

zone "." { type master; file "failed-connection.root.zone"; };

and then in failed-connection.root.zone you'd have:

$ORIGIN .
$TTL 10
@ SOA <your SOA record details here>
* A 192.168.9.10
* AAAA fe80:123:45::1

Make sure to use a short TTL (I used 10 seconds in the above example) to avoid inadvertant caching of the "failure" response. Also make sure to use IP addresses that do not depend on external connectivity. (Strictly speaking fe80::/16 is deprecated, but it's good enough for illustrative purposes.) The "link down detected" script may also need to flush the DNS server's cache. Also, make very sure that this does not leak onto the Internet. In BIND 9, make good friends with the views feature; with other software, investigate alternatives before making something like this live.

When you detect the link coming back up, just put back the original BIND (or other DNS server) configuration file and issue another configuration reload command and possibly cache flush.

You could of course use e.g. iptables with pre-routing address rewriting, but then you'd risk needing something that can handle basically anything anyone might want to throw at anything on the Internet, for marginal additional utility. To me, doing it that way doesn't seem worth the potential trouble.

6
  • +1 AFAIK it's impossible to say whether a connection can exist without a transmission, and that's pretty much what the ICMP ping is for. When a connection becomes impossible because of a failure somewhere in the middle, there's no magical feature of the networking stack that can alert you of this.
    – goldilocks
    Dec 9, 2013 at 16:16
  • @goldilocks Well, I suspect something like BGP could in principle help, but it still won't be guaranteed and someone asking this question probably isn't in a position to be able to rely on BGP anyway. The best way then is to simply do something that is known to solicit a response from the other end of the link. For which ICMP echo requests are ideally suited.
    – user
    Dec 9, 2013 at 19:24
  • BGP is not an option, therefore - ping. Pinging every 5 mins a host taken randomly from a list of a dozen or so hosts shouldn't count as a DoS attack I hope. Redirecting with BIND is absolutely great idea as I already have BIND configured as a caching DNS. Bonus points for configuration examples.
    – Eiver
    Dec 9, 2013 at 21:21
  • @Eiver Just use some known host on your ISP's network, like their DNS resolvers or the next hop gateway. Pick a reasonable interval and I doubt anyone will make a fuss. The appropriate interval depends mostly on how quickly you want to detect a link outage and take steps to mitigate the situation. By the time the link is down you can decrease the time between attempts in order to recover soon after the link comes back up, since it won't really have an impact on anyone else anyway. The most important thing is to make absolutely sure you don't leak a fake root zone onto the Internet.
    – user
    Dec 9, 2013 at 21:47
  • I already have a split horizon DNS with 2 views, because I wanted to be authoritative for my own domain and I wanted it to be resolved on LAN to 192.168.0.1, rather than the public IP address. Zone "." is currently inside view LANView{}, with match-clients { 192.168.0.0/24; 127.0.0.0/8; }; Zone "." is currently set to type hint. If I change hint to master and define the zone correctly, that should do the trick. Correct?
    – Eiver
    Dec 10, 2013 at 8:45
0

Since you say you have a "little" server, I assume that traffic volume is low enough to be handled by an HTTP proxy such as Squid. If you set up the router as a transparent proxy (a.k.a interception proxy), the clients should have a normal Internet experience until the Internet connection fails. Then, I would expect clients to get HTTP 504 (Gateway Timeout) responses.

If your Internet connection is unreliable, you might consider it a side benefit that pages that happen to be in the HTTP proxy's cache could still be available to clients during the outage.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .