Allowing access to services through VPN

1. Caddy version (caddy version):

2.0

2. How I run Caddy:

Systemctl

a. System environment:

Raspberry Pi (Buster Lite)

b. Command:

N/A

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:


    portainer.mydomain.duckdns.org {
    	log {
    		output file /var/log/caddy/portainer.log
    	}
    	@internal {
    		remote_ip 192.168.1.0/24 10.13.13.2/32
    	}
    	handle @internal {
    		reverse_proxy 127.0.0.1:9000
    	}
    	respond 403
    }

3. The problem I’m having:

I would like to be able to access my services while using Wireguard VPN. Currently when I direct tunnel to my house my phone uses 10.13.13.2 as it’s IP but adding this IP to my Caddyfile doesn’t give me access to those services.

Now technically my phones IP becomes my houses IP (seen on whatsmyip) due to the tunneling and if I add my houses public IP to the Caddyfile I can access my services without problem. The reason I don’t want to use that public IP in the Caddyfile is in the event that it changes I’m now unable to use them and someone else may get that address.

I can access my NAS HDDs just fine through the VPN but none of the Caddyfile pages load while connected unless I put my homes public IP in the file after remote_ip.

Is there a way to use my domain_name instead of an actual IP? Maybe a matcher being handled a certain way? Since my domain is pointed to my ip and I use DDNS I shouldn’t have a problem even if it changes.

Should I be able to use my 10.x.x.x subnet addressing and access my services? If so is there some kind of configuration I need to make on my server before Caddy will process the request?

4. Error messages and/or full log output:

Pages load https but blank

5. What I already tried:

remote_ip 10.13.13.2/32
remote_ip 10.13.13.1
remote_ip 10.13.13.0/24
remote_ip homes.public.ip (works)
remote_ip mydomain.duckdns.org (error)

Thank you!

6. Links to relevant resources:

Add this to the top of your Caddyfile:

{
  debug
}

Wireguard in from your phone and make a request.

Then, copy the Caddy debug output from stdout and paste it here.

It should give us a good idea what’s going on from Caddy’s perspective. That said…

This makes it sound like the request is being made through the public internet (i.e. originating from your house) rather than from Wireguard’s subnet. Do you have Wireguard providing a full tunnel or a split tunnel?

What IP address does portainer.mydomain.duckdns.org resolve to from inside your private network? Does it properly resolve to Caddy’s host directly? Or does it resolve to your external IP? (If the latter, your phone’s request might be coming in via Wireguard, then straight back out to the external IP just to be port forwarded back in, and when it heads out and comes back in it’ll look like the request is coming from your external IP instead of the phone’s internal / Wireguard subnet IP.)

Here is my log from the console using caddy run:

2020/06/11 12:22:37.675 ERROR   http.log.access.log0    handled request {"request": {"method": "GET", "uri": "/", "proto": "HTTP/2.0", "remote_addr": "***publicipaddress***:59558", "host": "portainer.mydomain.duckdns.org", "headers": {"User-Agent": ["Mozilla/5.0 (iPhone; CPU iPhone OS 13_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 EdgiOS/45.3.19 Mobile/15E148 Safari/605.1.15"], "Accept-Language": ["en-us"], "Accept-Encoding": ["gzip, deflate"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"], "Pragma": ["no-cache"], "Cookie": ["portainer.LOGIN_STATE_UUID=5039ae8e-505e-41cf-952f-98bd4cfd931b"], "Cache-Control": ["no-cache"], "Upgrade-Insecure-Requests": ["1"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4867, "proto": "h2", "proto_mutual": true, "server_name": "portainer.jnorth007.duckdns.org"}}, "common_log": "***publivipaddress*** - - [11/Jun/2020:08:22:37 -0400] \"GET / HTTP/2.0\" 403 0", "duration": 0.000070906, "size": 0, "status": 403, "resp_headers": {"Server": ["Caddy"], "Content-Type": []}}

I didn’t see a DEBUG pop up when I tried to access the page.

ping from my windows pc shows it resolves to my raspberry pi:

Pinging portainer.mydomain.duckdns.org [192.168.1.29] with 32 bytes of data:
Reply from 192.168.1.29: bytes=32 time=2ms TTL=64
Reply from 192.168.1.29: bytes=32 time=2ms TTL=64
Reply from 192.168.1.29: bytes=32 time=2ms TTL=64
Reply from 192.168.1.29: bytes=32 time=2ms TTL=64

Ping statistics for 192.168.1.29:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 2ms, Maximum = 2ms, Average = 2ms

And I’m pretty certain it’s a full tunnel as everything I do goes through my server before the internet. I set allowed ip’s to 0.0.0.0/0 which should mean all traffic goes through the tunnel.

Thank you!

My guess is, this is a problem with routing and forwarding. As using duckdns means you try to access your service via your external IP. If you use wireguard to access the pi “from intern”, you should add your pi - wireguard IP to the line with your domain name (separate by comma of course)

I think it may be also. Unfortunately I can’t figure out where

Do you mean add it at the beginning

Mydomain.duckdns.org, 10.13.13.2 {
            Reverse_proxy....
}

Tried that and no luck. I can’t seem to find any answer for how to get the routing properly configured. Maybe I’m searching for the wrong stuff.

Is 10.13.13.2 the IP of your pi or your mobile? And what address did you enter to reach service? Both must be IP of your pi. I think using an own DNS for your mobile which inserts the local IP for your domain would be able to fix this, but I think that’s not practical right now

So my iPhone wireguard ip is 10.13.13.2. My ‘DNS server’ in the Wiregurd app is set to 10.13.13.1 (Wireguard server on my RPi). I have also made the ‘DNS server’ option in the app my RPi IP address as it uses Pihole/dnsmasq to resolve.

I have set Pihole to listen on all interfaces just incase that was causing and issues.

If you pi has 10.13.13.1 you must change your caddy file to

Mydomain.duckdns.org, 10.13.13.1 {
            Reverse_proxy....
}

And from mobile you don’t open https://Mydomain.duckdns.org but https://10.13.13.1

Then it should work

Here’s what I tried

portainer.mydomain.duckdns.org, 10.13.13.1/24 {
	log {
		output file /var/log/caddy/portainer.log
	}
	@internal {
		remote_ip 192.168.1.0/24 10.13.13.2
	}
	handle @internal {
		reverse_proxy 127.0.0.1:9000
	}
	respond 403 {
                close
        }
}

I also tried it wothout the /24 CIDR

I am wondering if it’s something in iptables that needs to be configured. Caddy is definitely getting the request because I get https but nothing but a blank page.

I think at this stage your most likely problem is this one:

@Whitestrake this is basically what I am saying. I am pretty new to caddy but had my fair share of wireguard configuration.

@jfirestorm44 what’s your http request from mobile? Do you try your domain name or the IP address of your pi? Because as Whitestrake is saying if you try to access the service via domain name there’s a DNS request, returning your external IP. As you have in your wireguard configuration the 0 0.0.0 as allowed IP range all traffic is routed by your pi and I guess you activated IP forwarding in kernel and iptables.

If you cannot make it work you should really check your logs (maybe someone can help with a good log configuration) and check the source IP when requesting from mobile.

@Florian_Braun, you’ve advised that he change his Caddyfile’s site addresses to include his Pi’s IP address, but I don’t think that’s appropriate.

The request is reaching Caddy with the correct server name and requested Host, which is his DuckDNS subdomain.

Caddy is correctly attributing the request to to the site configuration. The issue is the site configuration is set only to execute the reverse proxy if the remote IP address (the client’s IP address) matches a whitelist; because it doesn’t, he gets a 403. His remote_addr shows up to Caddy as ***publicipaddress***:59558 (per his log entry above). It shows this instead of the local IP because of NAT loopback.

To fix this, he needs to either:

  1. Add his own public IP address to the whitelist (almost certainly not feasible; his public IP is dynamic, hence DuckDNS)
  2. Have the request go directly from his Wireguard IP to the Caddy host, over LAN, so his remote address is in fact the local address instead of the external address

To achieve #2, he must have split DNS resolve Caddy’s internal IP address for requests to his DuckDNS subdomain, instead of Caddy’s external IP (his public address).

I agree with you @Whitestrake, but from my experience it’s a lot harder to get the right DNS entry for his pi. I don’t have much experience with pihole. From another Linux computer I would add the subdomain to the hosts file with the pi’s wireguard IP. But I never did this on a mobile

Ok so what you’re both saying makes sense. I’ll take a look at my hosts file and see about changing it to the Wireguard ip. Right now it looks like this

# IP-Address  Full-Qualified-Hostname  Short-Hostname
#
192.168.1.29 mydomain.duckdns.org. jellyfin.mydomain.duckdns.org. portainer.mydomain.duckdns.org.

I had to point dnsmasq at my pi for those domains so it wouldn’t go out and loopback in. Now I’m having that problem with Wireguard but am not exactly sure what to put for it to fix it.

Thank you

This topic was automatically closed after 30 days. New replies are no longer allowed.