Table of Contents

DNS Split-Horizon Setup for digital guides with BYOD or loaner mobile devices

Visitors using Bring Your Own Device (BYOD) loaner devices to access a local audio guide or digital guide over wifi.

This guide explains how to provide a seamless experience for users who may access your audio guide or digital guide either from your local WiFi. By using a DNS split-horizon setup, you can automatically redirect devices to the internal server when on the local network while showing a fallback page with information for visitors still not connected to the wifi.

Why This Setup Helps

When visitors open your audioguide URL:

Internet-Facing Requirements

To handle requests from outside your LAN

Domain Name: Register a public domain, e.g., myaudioguide.net.

DNS Configuration: Point the myaudiogude.net to a publicly accessible web server (your droplet ip). (Typically a small droplet on e.g. digital ocean) Point int.myaudioguide.net to th elocal servers local ip e.g. 10.2.0.10.

HTTPS Certificate: Ensure the certificate is valid for the public domain.

Fallback Webpage: This page will attempt to probe the local server:

Note: Ensure the fallback page is served over HTTPS to avoid browser mixed-content warnings.

Local LAN Requirements

To make the audioguide work seamlessly on local WiFi:

DNS Configuration: Configure your local DNS so that both myaudioguide.net and int.myaudioguide.net resolve to the local audioguide server’s IP e.g. 10.2.0.10.

HTTPS Certificate: Use a certificate valid for both internal and public domain names (wildcard or SAN certificate).

Reverse Proxy: Nginx is recommended to handle internal routing and serve certificates.

Tip: Using Certbot with DNS-01 challenges can simplify automatic certificate renewal for mixed public/private setups.

Internet fallback page

On the internet it is recommended to host a webpage that will give the visitor useful information in case the visitor never joined the local wifi. This page can contain instructions in how to join and other useful information.

A minimal fallback webpage containing some javascript that probes the local server for a resource, if the resource is found the visitor is redirected to the local server automatically. This also helps in the case the mobile device finds the dns over its internet connection while connected to local wifi. Example code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="description" content="Internet redirect notice for local WiFi" />
  <meta name="keywords" content="audioguide myaudioguide digitalguide">
  <title>PIXILAB Guide</title>
  <style>
    body {
      margin: 1em;
      box-sizing: border-box;
      background: #000;
      color: #fff;
      font-family: "Trebuchet MS", sans-serif;
      font-size: 8vmin;
      text-align: center;
    }
    h1 { font-size: 1.5em; margin: 0.5em 0; }
    a { color: aliceblue; }
    #blurb { font-size: 0.6em; }
  </style>
</head>
<body>
  <div>
    <h1>PIXILAB Guide</h1>
    <p>You are not connected to the local WiFi required to access the audio guide.</p>
    <p>Please connect to the recommended WiFi, then return to this page.</p>
    <hr/>
    <p id="blurb">Learn more about PIXILAB's <br/><a href="http://pixilab.se/blocks">mobile guide</a>.</p>
  </div>
</body>
<script>
  // Probe the internal server to detect local network access
  retrySoon(100); // Initial quick probe

  function retrySoon(delay) {
    delay = delay || 4000;
    setTimeout(() => {
      const xhr = new XMLHttpRequest();
      xhr.timeout = 5000;
      xhr.onload = handleSuccess;
      xhr.onerror = handleError;
      xhr.ontimeout = handleTimeout;
      xhr.open("GET", "http://int.myaudioguide.net/img/invisible.png?buster=" + Date.now());
      xhr.send();
    }, delay);
  }

  function handleSuccess() {
    setTimeout(() => {
      location.href = "http://int.myaudioguide.net" + location.pathname + location.search;
    }, 200);
  }

  function handleError(evt) {
    console.log("Error connecting to internal server", evt.target.status);
    retrySoon();
  }

  function handleTimeout(evt) {
    console.log("Internal server probe timed out");
    retrySoon();
  }
</script>
</html>