<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>IPv4 on Clément Joly – Open-Source, Rust &amp; SQLite</title><link>https://cj.rs/tags/ipv4/</link><description>Recent content in IPv4 on Clément Joly – Open-Source, Rust &amp; SQLite</description><image><title>Clément Joly – Open-Source, Rust &amp; SQLite</title><url>https://cj.rs/images/open-graph-pages.jpg</url><link>https://cj.rs/images/open-graph-pages.jpg</link></image><generator>Hugo</generator><language>en</language><copyright>Clément Joly</copyright><lastBuildDate>Mon, 04 May 2026 19:41:10 +0100</lastBuildDate><atom:link href="https://cj.rs/tags/ipv4/index.xml" rel="self" type="application/rss+xml"/><item><title>You “Own” 16 Milion+ IPv4 Addresses!</title><link>https://cj.rs/blog/tips/you-own-16-milion-ipv4-addresses/</link><pubDate>Sat, 05 Mar 2022 21:13:22 +0000</pubDate><guid>https://cj.rs/blog/tips/you-own-16-milion-ipv4-addresses/</guid><description>What can you do with the huge loopback range (127.0.0.0/8)? Is it future-proof?</description><content:encoded><![CDATA[



  
  
  
  

  <div class="alert alert-tldr">
    <p class="alert-heading">
      ⚡
      
        TL;DR
      
    </p>
    <p>For the foreseeable future, you can likely use <code>127.0.0.0/8</code> freely (or at least <code>127.0.0.0/16</code>).</p>
  </div>



<h2 id="introducing-1270008-the-loopback-range">Introducing <code>127.0.0.0/8</code>, the Loopback Range</h2>
<figure>
    <img loading="lazy" src="/blog/tips/you-own-16-milion-ipv4-addresses/opengraph.webp"
         alt="If you have a Cidr range 127.0.0.0/8 visualized with 4 colors, one color per number." width="1941" height="855"/> <figcaption>
            Visualization of the 127.0.0.0/8 range<p>From <a href="https://cidr.xyz">cidr.xyz</a> by <a href="https://yuv.al/">Yuval Adam</a></p>
        </figcaption>
</figure>

<p>If you have ever done web development or otherwise set up a local server, you have most likely used the IP address <code>127.0.0.1</code> to communicate with a local server. Often, <a href="https://en.wikipedia.org/wiki/Localhost"><code>localhost</code></a> is even internally translated to that address. But what if you want to run another server on the same computer? Easy, make the first one use, say, port <code>8080</code> and the second one, port <code>8181</code>!</p>
<p>Something more difficult now: say you can convince<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> your browser that your local service is serving a valid HTTPS connection only if you use port number <code>443</code>. How can you run many of those services? In turns out in IPv4, you have many such local addresses: <code>127.0.0.1</code>, <code>127.0.0.2</code>,  <code>127.0.0.3</code>, <code>127.0.0.4</code>… So you just need to spawn the various servers on the same <code>443</code> port number with different addresses and packets will go straight to your <a href="https://en.wikipedia.org/wiki/Localhost">localhost</a>.</p>
<p>But how many such addresses do we have? According to <a href="https://www.rfc-editor.org/rfc/rfc990.txt">RFC990</a> from 1986:</p>




  <figure>
    <blockquote cite="https://www.rfc-editor.org/rfc/rfc990.txt">
      <pre><code>   The class A network number 127 is assigned the &quot;loopback&quot;
   function, that is, a datagram sent by a higher level protocol
   to a network 127 address should loop back inside the host.  No
   datagram &quot;sent&quot; to a network 127 address should ever appear on
   any network anywhere.
</code></pre>

    </blockquote>
    
      <figcaption class="blockquote-caption">
        
          <cite style="text-align: right"><a href="https://www.rfc-editor.org/rfc/rfc990.txt">https://www.rfc-editor.org/rfc/rfc990.txt</a></cite>
          <br/>
        
        
      </figcaption>
    
  </figure>



<p>The “class A network” translate to a <code>/8</code> in <a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing">CIDR notation</a>, so that’s all addresses between <code>127.0.0.0</code> and <code>127.255.255.255</code>. A quite sizeable 2²⁴ or <em>16,777,216</em> addresses<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>!</p>
<p>Note the wording of the RFC: IPs are not “owned”, there are just “allocated”. For addresses routable on the wider Internet, it’s usually done by <a href="https://en.wikipedia.org/wiki/Regional_Internet_registry">Regional Internet Registeries</a>. And allocations could change, as we will see at the end of this article.</p>
<h2 id="other-use-cases">Other Use Cases</h2>
<p>What can you do with so many IPs? A couple of things.</p>
<h3 id="multiple-servers-on-the-same-port-number">Multiple Servers on the Same Port Number</h3>
<p>As we have seen earlier with the port number <code>443</code> example, the <code>127.0.0.0/8</code> range is handy to run multiple local services on the same port. Thus, it’s not surprising to see <code>systemd-resolved</code> – a local DNS resolver that needs to listen on port <code>53</code> – use a couple addresses from that range. The <a href="https://man.archlinux.org/man/core/systemd/systemd-resolved.8.en">man page</a> reads:</p>




  <figure>
    <blockquote cite="https://man.archlinux.org/man/core/systemd/systemd-resolved.8.en">
      <p>Additionally, systemd-resolved provides a local DNS stub listener on the IP addresses 127.0.0.53 and
127.0.0.54 on the local loopback interface.</p>

    </blockquote>
    
      <figcaption class="blockquote-caption">
        
          <cite style="text-align: right"><a href="https://man.archlinux.org/man/core/systemd/systemd-resolved.8.en">https://man.archlinux.org/man/core/systemd/systemd-resolved.8.en</a></cite>
          <br/>
        
        
      </figcaption>
    
  </figure>



<p>In this case, <code>systemd-resolved</code> <em>has to</em> bind on the default port, because one of the main ways (on Unix-like systems) that DNS resolution is configured is through the file <a href="https://man.archlinux.org/man/resolv.conf.5.en"><code>/etc/resolv.conf</code></a>. This file does not widely support setting a port number, forcing the configured server to be reachable on the default port. Thanks to the use of a loopback addresse though, <code>systemd-resolved</code> can become the default resolver just by adding this line to <code>resolv.conf</code>:</p>
<pre tabindex="0"><code>nameserver 127.0.0.53
</code></pre><h3 id="naming-things">Naming Things</h3>
<p>On Unix-like systems, the <code>/etc/hosts</code> file associates IP addresses with names, like so:</p>
<pre tabindex="0"><code>127.0.0.1	localhost
::1		localhost
</code></pre><p>That’s how <code>localhost</code> is associated with <code>127.0.0.1</code> (and IPv6 <code>::1</code>).</p>
<p>You can edit this file and add useful aliases to other IPs (not necessarily in the local range by the way). Then, you just bind your multiple services to their default ports and access to them by name. No more complicated ports to remember! This benefit comes as a byproduct of using default ports but with different IPs for different services.</p>
<p>For instance, you could name one of the aforementioned <code>systemd-resolved</code> IPs by adding this line to <code>/etc/hosts</code>:</p>
<pre tabindex="0"><code>127.0.0.1	localhost
::1		localhost

127.0.0.53	sd
</code></pre><p>And then query it like so:</p>
<pre tabindex="0"><code>dig @sd s.cj.rs
</code></pre><p>instead of</p>
<pre tabindex="0"><code>dig @127.0.0.53 s.cj.rs
</code></pre><p>if you did not have the setting.</p>
<p>I’m using this trick to make the <a href="https://syncthing.net/">Syncthing</a> web interface accessible on a memorable port on an address with a memorable name in my web browser.</p>
<h2 id="future-of-1270008">Future of <code>127.0.0.0/8</code></h2>
<p>Even if the ability to give various services different IPs is handy, 16 milion addresses is huge. Given how IPv4 is sometimes called “internet <a href="https://fly.io/blog/32-bit-real-estate/">real-estate</a>”, there have been discussions to drastically limit the size of this loopback range, and use some of it as “normal” IPs. For instance, this <a href="https://www.ietf.org/id/draft-schoen-intarea-unicast-127-00.html">IETF draft</a> proposes to cut the loopback range to <code>127.0.0.0/16</code> (so only addresses between <code>127.0.0.0</code> and <code>127.0.255.255</code>) and make the rest (addresses between <code>127.1.0.0</code> and <code>127.255.255.255</code>) routable on the public internet. The 65536 addresses in <code>127.0.0.0/16</code> should to be enough for almost everyone on a local machine and nearly 16 million IPs could be used as a fresh supply of IPv4 addresses<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<h3 id="and-ipv6">And IPv6?</h3>
<p>Even though IPv6 has a huge namespace, your IPv6 loopback only has one address <code>::1</code>. And that’s quite a shame because, as we have just seen, multiple loopback addresses are quite handy.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>For instance using <a href="https://mkcert.dev/">mkcert</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Admittedly, some addresses like <code>127.0.0.0</code> or <code>127.255.255.255</code> are reserved, but there is still plenty of space.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Whether more useable IPv4 addresses is a good thing is debated. It might divert efforts from the IPv6 transition and even with a few millions more IPv4 addresses, these are still scarce.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>