1. The problem I’m having:
I’m configuring two domains: one public (port 443) and one on port 12000 protected by the network firewall. Will the private domain answer only to connections on port 12000 or faking SNI/Host header would allow an attacker to reach that reverse proxy?
I’ve been trying to reach it and the private certificate is presented but then it always answers 404 as expected.
I want to depend on this security behaviour to have the same Caddy for everything on the machine.
If it is not secure enough, how could I differentiate Tailscale traffic specifically?
2. Error messages and/or full log output:
It connects through port 443, it receives the certificate for the private domain, but then it reaches a 404 as expected.
curl -kv --connect-to test.otter-cat.ts.net:12000:34.76.170.44:443 'https://test.otter-cat.ts.net:12000/health'
* Connecting to hostname: 34.76.170.44
* Connecting to port: 443
* Trying 34.76.170.44:443...
* Connected to (nil) (34.76.170.44) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* 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=test.otter-cat.ts.net
* start date: Jul 4 05:15:13 2024 GMT
* expire date: Oct 2 05:15:12 2024 GMT
* issuer: C=US; O=Let's Encrypt; CN=E5
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x56202e06aeb0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /health HTTP/2
> Host: test.otter-cat.ts.net:12000
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 404
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Mon, 29 Jul 2024 06:15:59 GMT
<
* Connection #0 to host (nil) left intact
3. Caddy version:
v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=
4. How I installed and ran Caddy:
Docker Compose.
a. System environment:
Linux, Docker, Tailscale.
b. Command:
Standard Docker command.
c. Service/unit/compose file:
Dockerfile:
FROM caddy:2.7.6
COPY caddy/origin /etc/ssl/origin
COPY caddy/Caddyfile /etc/caddy/Caddyfile
docker-compose.yml:
services:
caddy:
container_name: caddy
build: ./caddy
restart: unless-stopped
ports: ['80:80', '443:443', '12000:12000']
volumes:
- /srv/data/caddy:/data
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
d. My complete Caddy config:
(proxy) {
log {
format json
}
skip_log /health
reverse_proxy {
to {args[0]}:{args[1]}
lb_retries 40
lb_try_duration 25s
lb_try_interval 250ms
transport http {
dial_timeout 5s
read_timeout 30s
write_timeout 30s
response_header_timeout 30s
}
}
}
test.onetbooking.com {
import proxy engine 8080
tls /etc/ssl/origin/cert.pem /etc/ssl/origin/key.pem
}
https://test.otter-cat.ts.net:12000 {
import proxy flows 8080
}
:80 {
respond 404
}
:443 {
respond 404
}