You can use the DNS verification method. Either using nsupdate with bind or what ever protocol your DNS provider and favorite ACME (certbot, acme, lego, etc) utility supports. As long as your DNS server is publically reachable that will work, even if the subdomain itself doesn't exist publically.
This is what I do as well. I have a public DNS record for my internal reverse proxy IP (no need to expose my public IP and associate it with my domain). I let NPM reach out to the DNS provider to complete verification challenge using an account token, NPM can then get a valid cert from Let’s Encrypt and nothing is exposed. All inbound traffic on 80/443 remains blocked as normal.
I’m using this right now but I’m switching to having all my services under one domain and blocking non internal ips. Technically someone can access your site by providing the host manually, althought it’s unlikely since they would need to know it
Then you're all set, issue certs over DNS-01 challenge in NPM, and create records in your local DNS server that point to the NPM IP for each domain you want to use.
Put domain on cloudflare or another registrar that supports an API. Generate a token with the right privs.
Use certbot with the cloudflare plugin, and that token, and generate whatever certs you need within that domain using the DNS01 method.
No need to have port 80 open to the world, no need for a reverse proxy, no need for NAT rules to point it to the right machine, no need to even have DNS set up for the hostname. All of that BS is removed.
The token proves your authentication and LetsEncrypt will generate the certs.
If you have wildcard certs, you just install them everywhere your services are running.
As far as redirects go, you just 302 redirect from one host to another.
Unless you're asking about resolving hosts on your internal network and public ones differently, which is a lot more complicated than you probably want to deal with if you're already kind of lost. Just setup a VPN to your internal network and be done with it. Otherwise setup a local DNS resolver to bridge your public DNS and local requests.