<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Dhyaan's Blog]]></title><description><![CDATA[A personal blog about cybersecurity, software engineering, open-source projects, developer tools, and hands-on technical learning.]]></description><link>https://dhyaan11.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 04:11:09 GMT</lastBuildDate><atom:link href="https://dhyaan11.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why Is My Local Service Exposed? I Built Lantern to Find the Root Cause]]></title><description><![CDATA[You run a service locally.
You check the port.
It is listening.
But then comes the question:
Why is it exposed?
Tools like ss, lsof, and nmap are useful for discovering what is listening or reachable.]]></description><link>https://dhyaan11.hashnode.dev/why-is-my-local-service-exposed-i-built-lantern-to-find-the-root-cause</link><guid isPermaLink="true">https://dhyaan11.hashnode.dev/why-is-my-local-service-exposed-i-built-lantern-to-find-the-root-cause</guid><category><![CDATA[Go Language]]></category><category><![CDATA[golang]]></category><category><![CDATA[vibecoding]]></category><category><![CDATA[cybersecurity]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Dhyaan Kanoja]]></dc:creator><pubDate>Sat, 03 Oct 2026 13:09:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/647a21f71f6827e37f7055bb/96788773-0e22-4f4c-bb56-4d2eb9ac1391.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You run a service locally.</p>
<p>You check the port.</p>
<p>It is listening.</p>
<p>But then comes the question:</p>
<p><strong>Why is it exposed?</strong></p>
<p>Tools like <code>ss</code>, <code>lsof</code>, and <code>nmap</code> are useful for discovering what is listening or reachable. But they don't necessarily answer the next question:</p>
<blockquote>
<p><strong>What configuration caused this service to become exposed?</strong></p>
</blockquote>
<p>That was the problem I wanted to solve.</p>
<p>So I built <strong>Lantern</strong>, an open-source Go CLI that traces a local service from its configuration to its network exposure and explains the root cause.</p>
<h2>The Problem</h2>
<p>Consider a PostgreSQL container running on port <code>5432</code>.</p>
<p>You run:</p>
<pre><code class="language-bash">ss -lnt
</code></pre>
<p>and see:</p>
<pre><code class="language-text">*:5432
</code></pre>
<p>You now know something is listening on port <code>5432</code>.</p>
<p>But several questions remain:</p>
<ul>
<li>Which process owns the port?</li>
<li>Is it running inside Docker?</li>
<li>Which container exposed it?</li>
<li>Which configuration created the binding?</li>
<li>Which network interfaces can reach it?</li>
<li>What should be changed to make it local-only?</li>
</ul>
<p>Answering those questions manually means jumping between multiple tools and configuration files.</p>
<p>I wanted to connect those pieces.</p>
<h2>The Idea Behind Lantern</h2>
<p>The core idea is simple:</p>
<pre><code class="language-text">Configuration
      ↓
Process / Container
      ↓
Socket
      ↓
Bind / Interface
      ↓
Network Reachability
      ↓
Root Cause
      ↓
Recommended Fix
</code></pre>
<p>Instead of only reporting:</p>
<pre><code class="language-text">Port 5432 is listening
</code></pre>
<p>Lantern tries to explain <strong>why it is listening that way</strong>.</p>
<h2>A Simple Docker Example</h2>
<p>Suppose a <code>docker-compose.yml</code> contains:</p>
<pre><code class="language-yaml">services:
  postgres:
    image: postgres
    ports:
      - "5432:5432"
</code></pre>
<p>That publishing rule can result in the host exposing port <code>5432</code> beyond localhost.</p>
<p>The important question isn't only:</p>
<blockquote>
<p>Is <code>5432</code> open?</p>
</blockquote>
<p>It is:</p>
<blockquote>
<p><strong>What caused <code>5432</code> to be exposed?</strong></p>
</blockquote>
<p>The configuration itself provides an important part of that answer.</p>
<p>Now compare it with:</p>
<pre><code class="language-yaml">ports:
  - "127.0.0.1:5432:5432"
</code></pre>
<p>The second configuration explicitly binds the host side to localhost.</p>
<p>A developer can therefore trace the exposure back to the configuration instead of manually searching through files.</p>
<h2>What Lantern Does</h2>
<p>The main command is:</p>
<pre><code class="language-bash">lantern why 5432
</code></pre>
<p>The intended output looks roughly like:</p>
<pre><code class="language-text">PostgreSQL :5432

EXPOSURE PATH

docker-compose.yml
       ↓
5432:5432
       ↓
Docker
       ↓
0.0.0.0:5432
       ↓
LAN reachable

ROOT CAUSE
docker-compose.yml:18

RECOMMENDED CHANGE
127.0.0.1:5432:5432
</code></pre>
<p>The goal is to turn several disconnected pieces of system information into one understandable explanation.</p>
<h2>Lantern Isn't Another Port Scanner</h2>
<p>Lantern is not intended to replace existing tools.</p>
<p>They answer different questions:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Main question</th>
</tr>
</thead>
<tbody><tr>
<td><code>ss</code></td>
<td>What sockets are listening?</td>
</tr>
<tr>
<td><code>lsof</code></td>
<td>Which process owns this socket?</td>
</tr>
<tr>
<td><code>nmap</code></td>
<td>What ports are reachable?</td>
</tr>
<tr>
<td><strong>Lantern</strong></td>
<td><strong>Why is this service exposed?</strong></td>
</tr>
</tbody></table>
<p>Lantern focuses on <strong>configuration causality</strong>.</p>
<p>That distinction is the main reason I built it.</p>
<h2>Safe Remediation</h2>
<p>Lantern also has a remediation workflow.</p>
<p>Before changing anything, you can use:</p>
<pre><code class="language-bash">lantern fix 5432 --dry-run
</code></pre>
<p>This allows you to inspect the proposed change.</p>
<p>For supported Docker Compose bindings, the actual remediation can then be invoked with:</p>
<pre><code class="language-bash">lantern fix 5432
</code></pre>
<p>The design principle is simple:</p>
<blockquote>
<p><strong>A security tool should explain what it is going to change before changing it.</strong></p>
</blockquote>
<h2>What Lantern Is Not</h2>
<p>Lantern deliberately has a narrow scope.</p>
<p>It is not:</p>
<ul>
<li>a replacement for Nmap</li>
<li>a vulnerability scanner</li>
<li>a generic network monitor</li>
<li>a Docker security scanner</li>
<li>an Internet exposure detector</li>
<li>an AI wrapper around existing security tools</li>
</ul>
<p>Its purpose is much more specific:</p>
<blockquote>
<p><strong>Explain the local configuration path that resulted in a service being exposed.</strong></p>
</blockquote>
<h2>Built With Go</h2>
<p>Lantern is written in Go and currently targets Linux and WSL2.</p>
<p>The project separates the investigation into several stages, including:</p>
<ul>
<li>listener discovery</li>
<li>process attribution</li>
<li>Docker correlation</li>
<li>network reachability</li>
<li>configuration evidence</li>
<li>root-cause analysis</li>
<li>remediation</li>
</ul>
<p>The project is also tested with:</p>
<pre><code class="language-bash">go test ./...
go test -race ./...
go vet ./...
</code></pre>
<p>The current release is <strong>v0.1.1</strong>.</p>
<h2>An Important Limitation</h2>
<p>One thing I intentionally don't want Lantern to do is pretend it knows something when it doesn't.</p>
<p>Docker Desktop on Windows with WSL2 introduces additional networking and forwarding layers.</p>
<p>In some configurations, Lantern can detect that a port is reachable but may not have enough local evidence to confidently attribute that socket back to a specific Docker container.</p>
<p>In those situations, the correct result is an unresolved explanation rather than a fabricated one.</p>
<p>For a security-oriented tool, uncertainty should be visible.</p>
<h2>Try It Yourself</h2>
<p>Clone the repository:</p>
<pre><code class="language-bash">git clone [https://github.com/DhyaanKanoja11/Lantern.git](https://github.com/DhyaanKanoja11/Lantern.git)
cd Lantern
</code></pre>
<p>Build it:</p>
<pre><code class="language-bash">go build ./cmd/lantern
</code></pre>
<p>Then:</p>
<pre><code class="language-bash">./lantern version
./lantern doctor
./lantern scan
</code></pre>
<p>There is also a reproducible Docker example in the repository:</p>
<pre><code class="language-bash">cd examples
docker compose up -d
</code></pre>
<p>Then:</p>
<pre><code class="language-bash">lantern scan
lantern why 5432
</code></pre>
<p>You can test the remediation without changing anything:</p>
<pre><code class="language-bash">lantern fix 5432 --dry-run
</code></pre>
<p><strong>GitHub:</strong> <a href="https://github.com/DhyaanKanoja11/Lantern">https://github.com/DhyaanKanoja11/Lantern</a></p>
<h2>Why I Built It</h2>
<p>The original idea was straightforward.</p>
<p>I didn't want another tool telling me:</p>
<blockquote>
<p>"Port 5432 is open."</p>
</blockquote>
<p>I wanted something that could answer:</p>
<blockquote>
<p><strong>"Why is port 5432 open, and where do I change it?"</strong></p>
</blockquote>
<p>That difference becomes important in development environments, where a single configuration line can determine whether a service is available only locally or accessible from other interfaces.</p>
<p>Lantern is my attempt to connect those layers:</p>
<pre><code class="language-text">Configuration
      ↓
Container
      ↓
Process
      ↓
Socket
      ↓
Interface
      ↓
Reachability
</code></pre>
<p>and turn them into an explanation a developer can actually act on.</p>
<h2>Feedback</h2>
<p>Lantern is still early, and real-world usage is more useful than adding features based on assumptions.</p>
<p>If you try it, I'm particularly interested in:</p>
<ul>
<li>Where the explanation becomes unclear</li>
<li>Cases where attribution fails</li>
<li>Docker/WSL2 edge cases</li>
<li>Configurations Lantern doesn't understand</li>
<li>Whether the recommended fix makes sense</li>
</ul>
<p>The goal isn't simply to detect an open port.</p>
<p><strong>The goal is to explain why it is exposed.</strong></p>
<p><strong>GitHub:</strong> <a href="https://github.com/DhyaanKanoja11/Lantern">https://github.com/DhyaanKanoja11/Lantern</a></p>
]]></content:encoded></item></channel></rss>