1. Output of caddy version
:
root@birb:/srv# caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=
root@FriendlyWrt:~# caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=
2. How I run Caddy:
VPS: SystemD
OpenWrt: /etc/rc.local
+ caddy reload/stop/start/...
a. System environment:
VPS:
- Debian 11
OpenWrt:
# cat /etc/openwrt_release
DISTRIB_ID='OpenWrt'
DISTRIB_RELEASE='22.03.2'
DISTRIB_REVISION='r19803-9a599fee93'
DISTRIB_TARGET='rockchip/armv8'
DISTRIB_ARCH='aarch64_generic'
DISTRIB_DESCRIPTION='OpenWrt 22.03.2 r19803-9a599fee93'
DISTRIB_TAINTS='busybox'
b. Command:
Not applicable here... handled by init systems.
c. Service/unit/compose file:
VPS: Default systemd unit
OpenWrt:
# /etc/rc.local:
/usr/bin/caddy start --resume --config /srv/Caddyfile
d. My complete Caddy config:
Ok, this is where it becomes a little messy.
First, my VPSā config:
birb.it {
root * /srv/birb.it
file_server
}
# ... cutting out other unrelated domains ...
#*.birb.it {
# # Home server link
# reverse_proxy * 192.168.222.11:80 {
# transport http {
# # Add to nanopi: trusted_proxies 123.123.123.123
# # maybe? tls_trusted_ca_certs <pem_files...>
# compression on
# }
# }
#}
And my OpenWrt one:
# Globals
{
log {
level info
output file /var/log/caddy.log {
roll_size 10mb
roll_keep 10
roll_keep_for 720h
}
}
trusted_proxies 192.168.222.0/24 # <- Error, invalid!
}
(php) {
php_fastcgi unix//var/run/php8-fpm.sock {
capture_stderr true
}
}
:80 {
# Set this path to your site's directory.
root * /srv/default
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
# Basic ping-pong
echo.birb.it:80 {
respond "hello"
}
# LuCi
router.birb.it:80 {
reverse_proxy * localhost:8080
}
# Home Assistant
hass.birb.it:80 {
reverse_proxy * localhost:8123
}
# TVHeadend
tvh.birb.it:80 {
reverse_proxy * localhost:9981 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
# Jellyfin
video.birb.it:80 {
reverse_proxy * localhost:8096
}
# Navidrome
audio.birb.it:80 {
reverse_proxy * localhost:4533
}
# Photoprism...?
# photo.birb.it:80 { reverse_proxy * localhost:x }
# NextCloud
cloud.birb.it:80 {
root * /sdcard/srv/nextcloud/
import php
file_server
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
redir /.well-known/webfinger /index.php/.well-known/webfinger 301
redir /.well-known/nodeinfo /index.php/.well-known/nodeinfo 301
@forbidden {
path /.htaccess /data/* /config/* /db_structure /.xml /README /3rdparty/* /lib/* /templates/* /occ /console.php
}
respond @forbidden 404
}
# Monica
monica.birb.it:80 {
root * /sdcard/srv/monica/public
import php
file_server
}
# Grocy
grocy.birb.it:80 {
root * /sdcard/srv/grocy/public
import php
file_server
}
# Paperless / Paperspace
# paper.birb.it:80 { reverse_proxy * localhost:x }
tubesync.birb.it:80 {
reverse_proxy * localhost:4848
}
neko.birb.it:80 {
reverse_proxy * localhost:8989
}
rclone.birb.it:80 {
root * /www/rclone-webui-react/
file_server
}
3. The problem Iām having:
From my local server itself, OpenWrt, it looks fine (i abused my Grocy host for this test ^^')
root@FriendlyWrt:/sdcard/srv/grocy/public# curl grocy.birb.it/hdrs.php
Array
(
[TEMP] => /tmp
[TMPDIR] => /tmp
[TMP] => /tmp
[PATH] => /usr/local/bin:/usr/bin:/bin
[HOSTNAME] =>
[USER] => www
[HOME] => /home/www
[REQUEST_URI] => /hdrs.php
[SERVER_PROTOCOL] => HTTP/1.1
[GATEWAY_INTERFACE] => CGI/1.1
[HTTP_X_FORWARDED_HOST] => grocy.birb.it
[SERVER_PORT] => 80
[REQUEST_METHOD] => GET
[REMOTE_USER] =>
[HTTP_ACCEPT] => */*
[REMOTE_PORT] => 54042
[REMOTE_ADDR] => 192.168.2.1
[QUERY_STRING] =>
[CONTENT_LENGTH] => 0
[HTTP_X_FORWARDED_PROTO] => http
[HTTP_HOST] => grocy.birb.it
[REQUEST_SCHEME] => http
[REMOTE_IDENT] =>
[HTTP_USER_AGENT] => curl/7.86.0
[PATH_INFO] =>
[SCRIPT_FILENAME] => /sdcard/srv/grocy/public/hdrs.php
[DOCUMENT_ROOT] => /sdcard/srv/grocy/public
[HTTP_X_FORWARDED_FOR] => 192.168.2.1
[DOCUMENT_URI] => /hdrs.php
[SERVER_SOFTWARE] => Caddy/v2.6.2
[SERVER_NAME] => grocy.birb.it
[REMOTE_HOST] => 192.168.2.1
[SCRIPT_NAME] => /hdrs.php
[CONTENT_TYPE] =>
[AUTH_TYPE] =>
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /hdrs.php
[REQUEST_TIME_FLOAT] => 1670944509.83
[REQUEST_TIME] => 1670944509
[argv] => Array
(
)
[argc] => 0
)
Now, from my VPS via itās VPN link (192.168.222.0/24
):
root@birb:/srv# curl -H "Host: grocy.birb.it" 192.168.222.11/hdrs.php
Array
(
[TEMP] => /tmp
[TMPDIR] => /tmp
[TMP] => /tmp
[PATH] => /usr/local/bin:/usr/bin:/bin
[HOSTNAME] =>
[USER] => www
[HOME] => /home/www
[HTTP_X_FORWARDED_FOR] => 192.168.222.10
[SCRIPT_FILENAME] => /sdcard/srv/grocy/public/hdrs.php
[HTTP_HOST] => grocy.birb.it
[REQUEST_URI] => /hdrs.php
[DOCUMENT_URI] => /hdrs.php
[SERVER_SOFTWARE] => Caddy/v2.6.2
[QUERY_STRING] =>
[CONTENT_TYPE] =>
[HTTP_X_FORWARDED_PROTO] => http
[SERVER_PORT] => 80
[REMOTE_USER] =>
[HTTP_ACCEPT] => */*
[REQUEST_SCHEME] => http
[SCRIPT_NAME] => /hdrs.php
[SERVER_PROTOCOL] => HTTP/1.1
[REMOTE_PORT] => 42306
[PATH_INFO] =>
[CONTENT_LENGTH] => 0
[HTTP_USER_AGENT] => curl/7.74.0
[REQUEST_METHOD] => GET
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_NAME] => grocy.birb.it
[REMOTE_HOST] => 192.168.222.10
[REMOTE_ADDR] => 192.168.222.10
[REMOTE_IDENT] =>
[AUTH_TYPE] =>
[HTTP_X_FORWARDED_HOST] => grocy.birb.it
[DOCUMENT_ROOT] => /sdcard/srv/grocy/public
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /hdrs.php
[REQUEST_TIME_FLOAT] => 1670945586.72
[REQUEST_TIME] => 1670945586
[argv] => Array
(
)
[argc] => 0
)
And finally, I added a tiny reverse-proxy block for grocy.birb.it
. Accessing this from a totally different server reveals:
root@drachennetz:~# curl -Lv grocy.birb.it/hdrs.php
* Trying 185.185.127.216:80...
* TCP_NODELAY set
* Connected to grocy.birb.it (185.185.127.216) port 80 (#0)
> GET /hdrs.php HTTP/1.1
> Host: grocy.birb.it
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 308 Permanent Redirect
< Connection: close
< Location: https://grocy.birb.it/hdrs.php
< Server: Caddy
< Date: Tue, 13 Dec 2022 15:37:23 GMT
< Content-Length: 0
<
* Closing connection 0
* Clear auth, redirects to port from 80 to 443Issue another request to this URL: 'https://grocy.birb.it/hdrs.php'
* Trying 185.185.127.216:443...
* TCP_NODELAY set
* Connected to grocy.birb.it (185.185.127.216) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=grocy.birb.it
* start date: Dec 13 14:34:31 2022 GMT
* expire date: Mar 13 14:34:30 2023 GMT
* subjectAltName: host "grocy.birb.it" matched cert's "grocy.birb.it"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55db005c8210)
> GET /hdrs.php HTTP/2
> Host: grocy.birb.it
> user-agent: curl/7.68.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html; charset=UTF-8
< date: Tue, 13 Dec 2022 15:37:23 GMT
< server: Caddy
< server: Caddy
< x-powered-by: PHP/8.1.13
< content-length: 1299
<
Array
(
[TEMP] => /tmp
[TMPDIR] => /tmp
[TMP] => /tmp
[PATH] => /usr/local/bin:/usr/bin:/bin
[HOSTNAME] =>
[USER] => www
[HOME] => /home/www
[HTTP_X_FORWARDED_FOR] => 192.168.222.10
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_SCHEME] => http
[REMOTE_IDENT] =>
[GATEWAY_INTERFACE] => CGI/1.1
[REQUEST_URI] => /hdrs.php
[DOCUMENT_ROOT] => /sdcard/srv/grocy/public
[HTTP_USER_AGENT] => curl/7.68.0
[REMOTE_ADDR] => 192.168.222.10
[CONTENT_TYPE] =>
[HTTP_ACCEPT] => */*
[SCRIPT_NAME] => /hdrs.php
[HTTP_X_FORWARDED_HOST] => grocy.birb.it
[QUERY_STRING] =>
[CONTENT_LENGTH] => 0
[REMOTE_PORT] => 49910
[PATH_INFO] =>
[AUTH_TYPE] =>
[HTTP_ACCEPT_ENCODING] => gzip
[HTTP_HOST] => grocy.birb.it
[DOCUMENT_URI] => /hdrs.php
[REMOTE_USER] =>
[SERVER_PORT] => 80
[SCRIPT_FILENAME] => /sdcard/srv/grocy/public/hdrs.php
[SERVER_SOFTWARE] => Caddy/v2.6.2
[HTTP_X_FORWARDED_PROTO] => http
[SERVER_NAME] => grocy.birb.it
[REQUEST_METHOD] => GET
[REMOTE_HOST] => 192.168.222.10
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /hdrs.php
[REQUEST_TIME_FLOAT] => 1670945843.46
[REQUEST_TIME] => 1670945843
[argv] => Array
(
)
[argc] => 0
)
As you can see, the X-Forwarded-For
header is not set properly - its set to my VPSā, but if you ping drachennetz.com
, you can tell that this isnāt exactly correctā¦
This is the snippet I inserted for the last test:
grocy.birb.it {
reverse_proxy * 192.168.222.11:80
}
4. Error messages and/or full log output:
No error messages, only misaligned headers.
5. What I already tried:
I tried to add trusted_proxies 192.168.222.10
to my root config, but that was not correct, caddy validate
rejected that. Then I looked at the directive itself in the docs,m and there it is only mentioned as part of the reverse_proxy
block. Soā¦ Do I have to add that to /every/ single reverse proxy setup?..
Thank you!
PS.: My next step is to make VPS and OpenWRT share the same config directory with the latter not auto-renewing and leaving that to the VPS and simply pulling the key bundles from there to allow for HTTPS on the local network with the correct SNI. The router is configured to statically assign *.birb.it
to itself. The idea: Route to the router when at home, and go through a reverse proxy/VPN chain when away and only expose select services (Grocy would be one). Once that is working, TOTP and such to harden those exposed services properly. But, for now, I need to get the basics working - and having the correct IP in requests is kinda importantā¦ ^^ā
Thank you and kind regards,
Ingwie!
6. Links to relevant resources:
None