Create a "My IP address" tool

Ash_Crow Software Français

I was wondering about how "My IP address" tools can get both the user's IPv4 and IPv6 address when a web page request is, by definition, done from one address only. It turns out it is a simple trick: after the page is loaded, queries are made through Javascript to webservices responding only on either IPv4 or IPv6. This in turn is made easy by the fact that we can configure Nginx to return a Json object with this info without using any backend at all.

I did found explanations on the web on how to do some parts of it, but not the whole thing, so this page explains how to create such a tool with Nginx and vanilla JS.

DNS configuration

The first step is to configure a domain name so that certain subdomains are only accessible through IPv4 or IPv6. Here is what I did for the domain ash.bzh:

ip 1800 IN A 54.37.75.168
ip 10800 IN AAAA 2001:41d0:701:1100::3ec
ipv4 1800 IN A 54.37.75.168
ipv6 10800 IN AAAA 2001:41d0:701:1100::3ec

The subdomain ip.ash.bzh can answer with both version, while ipv4.ash.bzh can only be reached through IPv4, and ipv6.ash.bzh through IPv6.

Nginx configuration

The Nginx configuration for the server side is also really simple to setup:

# /etc/nginx/sites-available/ip.conf
server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name ip.ash.bzh ipv4.ash.bzh ipv6.ash.bzh;
        location / {
                add_header Access-Control-Allow-Origin *;
                default_type application/json;
                return 200 "{\"ip\":\"$remote_addr\"}";
        }
        # [...]
}

Here, any path on any of the three subdomains will return the same thing: a well formated, and CORS-enabled, JSON file with an ip key and the IP used for the query as value.

HTML

Now, for the user-facing page, all we need is a call to a Javascript file that will hold all the logic, and a HTML table where the JS queries will append their results:

<!-- ip.html -->
<!-- [...] -->
<table id="ip-info">
  <caption>IP info</caption>
  <tbody>
  </tbody>
</table>
<script src="/static/js/ip.js"></script>
<!-- [...] -->

Javascript

The script itself is also really simple:

  • A pingIP function is called twice, with the name of each protocol used as parameter. It fetches the JSON file, extracts the IP address and passes it to the addRow function.
  • The addRow function transforms the data into a table row and inserts it into the HTML table.
// static/js/ip.js
function addRow(protocol, ip) {
    let tbody = document.getElementById('ip-info').getElementsByTagName('tbody')[0];
    let new_row = tbody.insertRow();
    new_row.outerHTML = `<tr><th>${protocol}</th><td>${ip}</td></tr>`
}

function pingIP(protocol) {
    let url = `https://${protocol.toLowerCase()}.ash.bzh/`;

    fetch(url, {
        headers: {
            'Accept': 'application/json'
        }
    })
        .then(response => response.json())
        .then(json => addRow(protocol, json.ip))
}

pingIP('IPv4');
pingIP('IPv6');

And that's pretty much it!

You can see the result at https://tools.ash.bzh/en/tools/ip/

Header image:

Photo of a passenger information display with diagnostic data, including an IP address, taken at Hawarden railway station, Flintshire, Wales. CC-BY-SA 3.0 Rept0n1x.

0 comments posted.

Comments

Comments are closed.