<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: jagadeesh k s</title>
    <description>The latest articles on DEV Community by jagadeesh k s (@jagadeesh0074).</description>
    <link>https://dev.to/jagadeesh0074</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3792008%2Ff5bcdd4b-5aa9-461b-89d3-a8294f63ccfb.jpg</url>
      <title>DEV Community: jagadeesh k s</title>
      <link>https://dev.to/jagadeesh0074</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jagadeesh0074"/>
    <language>en</language>
    <item>
      <title>Exposing services behing CGNAT | My home-Lab experience with Jio-Fiber</title>
      <dc:creator>jagadeesh k s</dc:creator>
      <pubDate>Wed, 25 Feb 2026 19:25:30 +0000</pubDate>
      <link>https://dev.to/jagadeesh0074/exposing-services-behing-cgnat-my-home-lab-experience-with-jio-fiber-2ed2</link>
      <guid>https://dev.to/jagadeesh0074/exposing-services-behing-cgnat-my-home-lab-experience-with-jio-fiber-2ed2</guid>
      <description>&lt;p&gt;Escaping CGNAT: Exposing Self-Hosted Services over IPv6 (No Public IPv4 Required)&lt;/p&gt;

&lt;p&gt;I’ve just begun my self-hosting journey.&lt;/p&gt;

&lt;p&gt;I repurposed an old laptop and installed Ubuntu Server on it. On top of&lt;br&gt;
that, I spun up several services using Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Nextcloud – Personal cloud storage&lt;/li&gt;
&lt;li&gt;  Vaultwarden – Lightweight password manager&lt;/li&gt;
&lt;li&gt;  Pi-hole – DNS-level ad blocking&lt;/li&gt;
&lt;li&gt;  Jellyfin – Media streaming server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I installed Ubuntu Server, configured Docker, and had everything running&lt;br&gt;
in a single day. It was smooth, fun, and surprisingly satisfying.&lt;/p&gt;

&lt;p&gt;Then came the final step: exposing my services to the public internet.&lt;/p&gt;

&lt;p&gt;That’s when things got complicated.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem: CGNAT
&lt;/h2&gt;

&lt;p&gt;My ISP (Jio Fiber) uses CGNAT (Carrier-Grade NAT).&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  My router does not get a public IPv4 address.&lt;/li&gt;
&lt;li&gt;  Traditional port forwarding is impossible.&lt;/li&gt;
&lt;li&gt;  Devices on the public internet cannot directly reach my server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In simple terms: I had no public “return address”.&lt;/p&gt;


&lt;h2&gt;
  
  
  Options I Considered (and Why I Avoided Them)
&lt;/h2&gt;

&lt;p&gt;I explored a few alternatives, but each came with trade-offs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Buy a Public IPv4 from ISP&lt;br&gt;
→ Extra cost and additional hassle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a VPN (Tailscale, WireGuard, etc.)&lt;br&gt;
→ Friends and family outside my network would need client setup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a VPS or reverse proxy (e.g., Cloudflare Tunnel)&lt;br&gt;
→ Introduces dependency and potential privacy concerns&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something simpler and more native.&lt;/p&gt;

&lt;p&gt;That’s when I rediscovered IPv6.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why IPv6 Solves This
&lt;/h2&gt;

&lt;p&gt;CGNAT exists because IPv4 addresses are exhausted.&lt;/p&gt;

&lt;p&gt;IPv6 does not have this limitation.&lt;/p&gt;
&lt;h3&gt;
  
  
  With IPv6:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Every device can have a globally routable address&lt;/li&gt;
&lt;li&gt;  NAT is not required&lt;/li&gt;
&lt;li&gt;  Port forwarding is unnecessary&lt;/li&gt;
&lt;li&gt;  Direct end-to-end connectivity is restored&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Tactical advantages I observed:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  ✅ No port forwarding required&lt;/li&gt;
&lt;li&gt;  ✅ Reduced exposure to IPv4 bot noise&lt;/li&gt;
&lt;li&gt;  ✅ Typically stable addressing (or use dynv6 if dynamic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s exactly what I did.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Verify IPv6 Connectivity
&lt;/h2&gt;

&lt;p&gt;What this does&lt;/p&gt;

&lt;p&gt;Checks whether your ISP provides IPv6.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ip -6 addr show&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Look for a global IPv6 address (starts with 2xxx: or 3xxx:).&lt;br&gt;
Ignore fe80:: — those are link-local addresses.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ping6 -c 4 google.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Validation&lt;/p&gt;

&lt;p&gt;If ping6 succeeds → IPv6 works.&lt;/p&gt;

&lt;p&gt;If not → Contact your ISP and ask them to enable IPv6.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Enable IPv6 in Netplan
&lt;/h2&gt;

&lt;p&gt;What this does&lt;/p&gt;

&lt;p&gt;Configures Ubuntu Server to accept IPv6 router advertisements and&lt;br&gt;
DHCPv6.&lt;/p&gt;

&lt;p&gt;Edit your Netplan configuration:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nano /etc/netplan/00-installer-config.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    network:
      version: 2
      ethernets:
        eno1:  # Replace with your interface name
          addresses:
            - 192.168.29.100/24
          routes:
            - to: default
              via: 192.168.29.1
          nameservers:
            addresses: [8.8.8.8, 8.8.4.4]
          dhcp6: true
          accept-ra: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply changes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo netplan apply&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Validation&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -6 ifconfig.co&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If this returns an IPv6 address, you’re good to go.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Configure Firewall Rules (Critical)
&lt;/h2&gt;

&lt;p&gt;With IPv6, your server is globally reachable.&lt;/p&gt;

&lt;p&gt;That makes firewall configuration extremely important.&lt;/p&gt;

&lt;p&gt;Using UFW:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo ufw allow 80/tcp&lt;br&gt;
    sudo ufw allow 443/tcp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That’s it. I only exposed HTTP and HTTPS.&lt;/p&gt;

&lt;p&gt;⚠️ Do not expose unnecessary ports.&lt;br&gt;
⚠️ I did NOT expose Pi-hole publicly.&lt;/p&gt;

&lt;p&gt;Everything runs behind HTTP/HTTPS via reverse proxy.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4: Configure Nginx to Listen on IPv6
&lt;/h2&gt;

&lt;p&gt;Inside your server block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    server {
        listen 80;
        listen [::]:80;

        server_name example.com;

        location / {
            proxy_pass http://172.18.0.2:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For HTTPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name example.com;

        ssl_certificate /etc/ssl/certs/fullchain.pem;
        ssl_certificate_key /etc/ssl/private/privkey.pem;

        location / {
            proxy_pass http://172.18.0.2:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listen [::]:80;&lt;br&gt;
    listen [::]:443 ssl;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That ensures Nginx accepts IPv6 connections directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Forwarding to Docker Containers
&lt;/h2&gt;

&lt;p&gt;My applications run inside Docker.&lt;/p&gt;

&lt;p&gt;Docker uses private IPv4 subnets internally (e.g., 172.18.0.0/16).&lt;/p&gt;

&lt;p&gt;To find the container IP:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker inspect &amp;lt;container_name&amp;gt; | grep IPAddress&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nginx (host) proxies traffic to that internal Docker IP.&lt;/p&gt;

&lt;p&gt;Everything up to this point happens on Ubuntu Server.&lt;/p&gt;

&lt;p&gt;Next: DNS and router configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: DNS Configuration (AAAA Record)
&lt;/h2&gt;

&lt;p&gt;To make the service reachable:&lt;/p&gt;

&lt;p&gt;Add an AAAA record pointing to your IPv6 address.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mydomain.dynv6.net → AAAA → 2001:db8:abcd::1234&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I used dynv6 because it’s simple and works well for dynamic IPv6&lt;br&gt;
addresses.&lt;/p&gt;

&lt;p&gt;Now clients accessing the domain will connect via IPv6.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Jio Router IPv6 Firewall Rules
&lt;/h2&gt;

&lt;p&gt;Before opening access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Use strong firewall rules&lt;/li&gt;
&lt;li&gt;  Install Fail2ban&lt;/li&gt;
&lt;li&gt;  Keep services updated&lt;/li&gt;
&lt;li&gt;  Use HTTPS only&lt;/li&gt;
&lt;li&gt;  Consider rate limiting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Login to your router admin page:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://192.168.29.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Go to:&lt;/p&gt;

&lt;p&gt;Security → Firewall → IPv6 Firewall Rules&lt;/p&gt;

&lt;p&gt;Add rules only for the ports you want (80 and 443).&lt;/p&gt;

&lt;p&gt;⚠️ The more ports you expose, the larger your attack surface.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;Once configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Your services are accessible from any IPv6-enabled network&lt;/li&gt;
&lt;li&gt;  No public IPv4 needed&lt;/li&gt;
&lt;li&gt;  No CGNAT workaround&lt;/li&gt;
&lt;li&gt;  No VPS&lt;/li&gt;
&lt;li&gt;  No port forwarding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just clean, native IPv6 connectivity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Self-hosting taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Networking fundamentals matter&lt;/li&gt;
&lt;li&gt;  IPv6 is underused but powerful&lt;/li&gt;
&lt;li&gt;  CGNAT is frustrating — but not unbeatable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re stuck behind CGNAT, try IPv6 before paying for a VPS.&lt;/p&gt;

&lt;p&gt;If you’ve faced similar pain points, drop them in the comments — it&lt;br&gt;
might help someone else.&lt;/p&gt;

&lt;p&gt;Good day! 🚀&lt;/p&gt;

</description>
      <category>ipv6</category>
      <category>cgnat</category>
      <category>jiofiber</category>
      <category>selfhosting</category>
    </item>
  </channel>
</rss>
