← Back to Lab Journal
Lab Note

Troubleshooting Split DNS with Cloudflare Pages

Diagnosing an SSL failure that only occurred on my home network and VPN after moving a public site to Cloudflare Pages.

DNSPi-holeCloudflareNginx Proxy ManagerTLSTroubleshooting

The Problem

I recently deployed a public technical blog using Astro, GitHub, and Cloudflare Pages.

The public deployment itself worked correctly, and the custom domain was active through Cloudflare.

However, I noticed an unusual problem:

  • The site worked normally over cellular data
  • The site failed from my home network
  • The site also failed while connected through my VPN

The browser returned:

ERR_SSL_UNRECOGNIZED_NAME_ALERT

Because the same hostname worked from cellular, this immediately suggested that the Cloudflare Pages deployment itself was probably healthy.

The difference had to be somewhere in the network path used by local and VPN clients.

Initial Hypothesis

My homelab uses split DNS for internally hosted applications.

Many internal service hostnames resolve to an internal Nginx Proxy Manager instance rather than following public DNS.

That allows services to use normal hostnames and HTTPS while keeping the traffic inside the homelab.

The simplified internal path is:

Internal Client
      |
      v
Pi-hole
      |
      v
Internal Reverse Proxy
      |
      v
Self-Hosted Application

The new blog was different.

It was intentionally hosted on Cloudflare Pages, not inside the homelab.

Its correct path should be:

Client
  |
  v
Public DNS
  |
  v
Cloudflare
  |
  v
Cloudflare Pages

I suspected my internal DNS configuration was still treating the new hostname as though it belonged to the internal reverse proxy.

Comparing Internal and Public DNS

I started by checking the hostname using the DNS server supplied by my home network:

nslookup blog.coleshomelab.com

The answer contained Cloudflare IPv6 addresses, but it also contained a private IPv4 address belonging to my internal reverse proxy.

I then compared that with Cloudflare’s public resolver:

nslookup blog.coleshomelab.com 1.1.1.1

The public result returned only Cloudflare addresses.

That was the important difference.

Conceptually:

Internal DNS
blog.coleshomelab.com
        |
        +---- Cloudflare addresses
        |
        +---- Internal reverse-proxy address  <-- Problem

while public DNS returned:

Public DNS
blog.coleshomelab.com
        |
        +---- Cloudflare addresses only

This explained why the behavior changed depending on which network I was using.

Why the SSL Error Occurred

The browser requested:

https://blog.coleshomelab.com

but internal DNS was capable of sending the connection to Nginx Proxy Manager instead of Cloudflare Pages.

Nginx Proxy Manager was not hosting that site.

The client therefore reached the wrong TLS endpoint.

The request path effectively became:

Browser
   |
   v
Internal DNS
   |
   v
Nginx Proxy Manager
   |
   X
No matching site / certificate

which resulted in:

ERR_SSL_UNRECOGNIZED_NAME_ALERT

The certificate error was therefore only the visible symptom.

The actual problem was DNS.

Finding the Wildcard Rule

The next step was checking the Pi-hole configuration.

I inspected its custom dnsmasq settings:

sudo pihole-FTL --config misc.dnsmasq_lines

The resolver contained a wildcard rule equivalent to:

address=/coleshomelab.com/<internal-reverse-proxy>

This was intentional.

It allows arbitrary internal application hostnames under the homelab domain to resolve to the reverse proxy without manually creating a DNS record for every service.

The problem was that the wildcard also matched:

blog.coleshomelab.com

even though that hostname now belonged to an externally hosted service.

The Fix

Rather than removing the wildcard and breaking the internal services that depended on it, I added a more-specific DNS exception for the blog hostname.

Conceptually:

*.coleshomelab.com
        |
        v
Internal Reverse Proxy


blog.coleshomelab.com
        |
        v
Normal Upstream DNS
        |
        v
Cloudflare Pages

A specific hostname rule takes precedence over the broader wildcard behavior.

This allowed the existing split-DNS architecture to remain intact while letting the externally hosted blog resolve publicly.

Redundant DNS Complication

My environment uses more than one Pi-hole resolver.

That meant fixing the rule on only one DNS server would not be enough.

If clients could query either resolver, the result could become intermittent:

Query
  |
  +----> Pi-hole A ----> Correct public answer
  |
  +----> Pi-hole B ----> Internal reverse proxy

Depending on which resolver answered, the blog might work or fail.

I therefore applied the same exception to both Pi-hole systems.

This is an important consideration with redundant infrastructure:

Redundancy only behaves predictably when the redundant systems have consistent configuration.

Validation

After applying the exception, I restarted Pi-hole’s DNS service and tested the hostname directly.

For the public blog hostname, I wanted:

blog.coleshomelab.com
        |
        v
Public Cloudflare addresses

and specifically did not want the internal reverse-proxy address.

I then checked an internally hosted hostname to confirm that the wildcard still worked:

Internal application hostname
        |
        v
Internal reverse proxy

This confirmed that the fix was limited to the intended hostname.

Finally, I cleared the DNS cache on my Windows client:

ipconfig /flushdns

and tested the site again.

It now behaved consistently across:

  • the home network
  • VPN access
  • cellular data

Troubleshooting Process

The useful part of this problem was the order in which I approached it.

1. Compare environments

The site worked on cellular but failed at home.

That suggested the application itself was probably healthy.

2. Identify what changes between environments

The hostname and browser were the same.

DNS and routing were different.

3. Compare DNS answers

nslookup blog.coleshomelab.com

versus:

nslookup blog.coleshomelab.com 1.1.1.1

immediately revealed a difference.

4. Trace the unexpected answer

The private address led directly back to the internal reverse proxy.

5. Find the rule responsible

The Pi-hole wildcard explained why the hostname was being intercepted.

6. Make the smallest possible change

Rather than removing a working wildcard configuration, I added an exception for one hostname.

7. Validate both the exception and the original behavior

The public hostname needed to resolve publicly while existing internal applications still needed to resolve privately.

What I Learned

This issue reinforced several useful troubleshooting lessons:

  • A TLS error does not necessarily mean TLS is the root cause
  • Comparing behavior across networks can quickly narrow the search area
  • Internal and public DNS answers should be compared when split DNS is involved
  • Wildcard DNS rules are convenient but can affect more hostnames than intended
  • Publicly hosted services may need exceptions from internal DNS overrides
  • Redundant DNS servers need consistent configuration
  • Fixes should preserve working infrastructure whenever possible
  • Testing the original behavior after a change is just as important as testing the fix

The most important observation was simple:

The site worked from cellular.

That single detail made it much less likely that Cloudflare Pages or the application itself was broken and pushed the troubleshooting process toward the local network.

Current Status

The blog now resolves through Cloudflare Pages regardless of whether the client is on the home network, connected remotely through VPN, or using a normal public connection.

Internally hosted services continue to use the existing split-DNS wildcard and reverse-proxy architecture.

The final behavior is:

Self-Hosted Applications
        |
        v
Internal DNS
        |
        v
Nginx Proxy Manager


Public Blog
        |
        v
Public DNS
        |
        v
Cloudflare Pages

Technologies Involved

  • Pi-hole
  • dnsmasq / FTL
  • Split DNS
  • Cloudflare DNS
  • Cloudflare Pages
  • Nginx Proxy Manager
  • TLS
  • PowerShell
  • Linux
  • VPN DNS