Brummbaer
(Otto Bär)
August 20, 2023, 9:17am
1
1. The problem I’m having:
I’m trying to regex match a request that is sent to the reverse proxy directive but I can’t seem to find out how to handle non matching requests. I tried using a handle doing something like “not @whitelisted ” but that seems to get ignored.
3. Caddy version: 2.6.4
4. How I installed and ran Caddy:
Archlinux package running with systemd unit file
a. System environment:
Archlinux either with systemd unit file or just from the command line
b. Command:
caddy run ./Caddyfile
d. My complete Caddy config:
disco.pandaden.net {
bind "39.52.43.18"
@whitelisted {
path_regexp \?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)
}
reverse_proxy @whitelisted 10.0.15.1:8443 {
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Client-Port {http.request.remote.port}
header_up X-Tls-Client-Cert-Der-Base64 {http.request.tls.client.certificate_der_base64}
}
tls {
client_auth {
mode request
}
}
}
I recommend using handle
blocks.
Apply your matcher to the first handle block, and put your proxy inside it.
Make a second handle block with no matcher, and all other requests will fall through to it.
Remove this. Caddy sets this header correctly already. See reverse_proxy (Caddyfile directive) — Caddy Documentation
This is unlikely to be useful because the connecting port is usually a random port assigned by the system networking stack.
You can shorten this by using the placeholder shortcut {tls_client_certificate_der_base64}
Brummbaer
(Otto Bär)
August 21, 2023, 9:25am
3
Thank you for your help. I modified the file and it looks like it’s working now.
The only problem I have now is with the path_regex
path_regexp /\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)
The regex seems to be correct according to this validator regex101: build, test, and debug regex
but it seems like in caddy this is not evaluated.
Here is my updated Caddyfile
disco.pandaden.net {
bind "39.52.43.18"
@whitelisted {
path_regexp /\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)
}
handle @whitelisted {
reverse_proxy 10.0.15.1:8443 {
header_up X-Tls-Client-Cert-Der-Base64 {tls_client_certificate_der_base64}
}
}
tls {
client_auth {
mode request
}
}
handle {
respond "no match"
}
}
~
The tls
directive cannot be within a handle
block.
Your config is really messy, please mind whitespace. Run caddy fmt --overwrite
to clean it up.
Brummbaer
(Otto Bär)
August 22, 2023, 7:06am
5
Reformatted
disco.pandaden.net {
bind "39.52.43.18"
@whitelisted {
path_regexp /\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)
}
handle @whitelisted {
reverse_proxy 10.0.15.1:8443 {
header_up X-Tls-Client-Cert-Der-Base64 {tls_client_certificate_der_base64}
}
}
tls {
client_auth {
mode request
}
}
handle {
respond "no match"
}
Oh right – path_regexp
cannot match the query, because the query is not the path. See What is a URL? - Learn web development | MDN
I think you might need to use an expression matcher in this case to regexp match on the {uri}
placeholder
@whitelisted `{uri}.match('/\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)')`
That said, this is awkward because it won’t match if device
is somewhere else in the query, i.e. as a second query param.
Brummbaer
(Otto Bär)
August 22, 2023, 11:04am
7
Thank you, I thought path would match everything right of the url, but it makes sense that it would only match paths.
It’s ok for device as this shouldn’t be anywhere else, since this is defined in the syncthing relay protocol.
I’m just a bit lost on how to integrate the {uri].match into the caddyfile - as far as I can see it’s used to replace something ?
It’s an expression matcher. See Request matchers (Caddyfile) — Caddy Documentation . You can remove your existing @whitelisted
matcher (i.e. path_regexp) and use what I gave you instead.
Brummbaer
(Otto Bär)
August 29, 2023, 9:15am
9
Thank you for the hint.
But I’m still a bit lost on how to integrate the expression matcher.
As I understood it it should go like this :
disco.pandaden.net {
bind "39.52.43.18"
@whitelisted `{uri}.match('/\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)')`
handle @whitelisted {
reverse_proxy 10.0.15.1:8443 {
header_up X-Tls-Client-Cert-Der-Base64 {tls_client_certificate_der_base64}
}
}
tls {
client_auth {
mode request
}
}
handle {
respond "no match"
}
But that gives an error :
Error: loading initial config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading matcher modules: module name 'expression': provision http.matchers.expression: compiling CEL program: ERROR: <input>:1:52: undeclared reference to 'match' (in container '')
| caddyPlaceholder(request, "http.request.uri").match('/\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)')
| ...................................................^
Ah sorry, it’s matches
instead of match
in CEL.
@whitelisted `{uri}.matches('/\?device=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)')`
See https://github.com/google/cel-spec/blob/master/doc/langdef.md
2 Likes
Brummbaer
(Otto Bär)
August 30, 2023, 7:30am
11
Thank you, its working as expected now :).
1 Like