Reverse_proxy between valid external domain and a made up internal domain

@Mohammed90 Thank you for your patience with me.
Indeed, making the following change to Caddyfile

    reverse_proxy @cel_backend_node rp-tailscale.esco.ghaar:8443 {
      transport http {
        #tls_insecure_skip_verify
        tls_trust_pool file {
          pem_file /opt/caddy/certificates/ldap_acme_actualroot_ca.crt
         }
       }
    }

where ldap_acme_actualroot_ca.crt is my ACME’s root cert, along w/ changing the Node.js (upstream) code to

  var certFile,
    certKey = null
  if (envNodeEnv === 'development') {
    certFile = envHttpsCertFile || 'certs/devnode.crt'
    certKey = envHttpsKeyFile || 'certs/devnode.key'
  } else {
    // assume its 'production' environment.
    certFile = envHttpsCertFile || 'certs/prodnode.crt'
    certKey = envHttpsKeyFile || 'certs/prodnode.key'
  }
  try {
    var privateKey = fs.readFileSync(path.resolve(__dirname, certKey), 'utf8')
    var certificate = fs.readFileSync(path.resolve(__dirname, certFile), 'utf8')
  } catch (error) {
    logger.error('Certificates can not be read')
    logger.error(`Secure HTTP server can not be started.\n ${error}\n EXITING`)
    gracefulShutdown()
  }

where devnode.crt points to fullchain.pem (complete chain as issued by step-ca) of rp-tailscale.esco.ghaar (VM1 host node running Node.js + react) and devnode.key points to privkey.pem

works!

Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526546.4749594,"logger":"tls.handshake","msg":"choosing certificate","identifier":"liveliteandwell.com","num_choices":1}
Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526546.4749887,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"liveliteandwell.com","subjects":["liveliteandwell.com"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"8e02fc2b7fd7fdf007881e7004fe00a66666501929f409bdc8344a0ab77e6baf"}
Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526546.4750075,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"192.168.0.28","remote_port":"52741","subjects":["liveliteandwell.com"],"managed":true,"expiration":1726361429,"hash":"8e02fc2b7fd7fdf007881e7004fe00a66666501929f409bdc8344a0ab77e6baf"}
Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526546.5051308,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"rp-tailscale.esco.ghaar:8443","total_upstreams":1}
Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526546.807779,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"rp-tailscale.esco.ghaar:8443","duration":0.30253505,"request":{"remote_ip":"192.168.0.28","remote_port":"52741","client_ip":"192.168.0.28","proto":"HTTP/2.0","method":"POST","host":"liveliteandwell.com","uri":"/api/login","headers":{"X-Forwarded-Host":["liveliteandwell.com"],"User-Agent":["curl/8.4.0"],"Accept":["*/*"],"Content-Type":["application/json"],"Content-Length":["53"],"X-Forwarded-For":["192.168.0.28"],"X-Forwarded-Proto":["https"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"liveliteandwell.com"}},"headers":{"Origin-Agent-Cluster":["?1"],"X-Frame-Options":["SAMEORIGIN"],"X-Download-Options":["noopen"],"Keep-Alive":["timeout=5"],"Cross-Origin-Resource-Policy":["same-origin"],"Referrer-Policy":["no-referrer"],"X-Dns-Prefetch-Control":["off"],"Date":["Thu, 27 Jun 2024 22:15:46 GMT"],"Connection":["keep-alive"],"Content-Security-Policy":["default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests"],"X-Content-Type-Options":["nosniff"],"X-Permitted-Cross-Domain-Policies":["none"],"Content-Length":["34"],"Cross-Origin-Opener-Policy":["same-origin"],"Strict-Transport-Security":["max-age=15552000; includeSubDomains"],"X-Xss-Protection":["0"]},"status":422}
Jun 27 15:15:46 rp-tailscale caddy[339064]: {"level":"info","ts":1719526546.8080058,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"192.168.0.28","remote_port":"52741","client_ip":"192.168.0.28","proto":"HTTP/2.0","method":"POST","host":"liveliteandwell.com","uri":"/api/login","headers":{"Content-Type":["application/json"],"Content-Length":["53"],"User-Agent":["curl/8.4.0"],"Accept":["*/*"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"liveliteandwell.com"}},"bytes_read":53,"user_id":"","duration":0.303025555,"size":34,"status":422,"resp_headers":{"Server":["Caddy"],"X-Frame-Options":["SAMEORIGIN"],"Referrer-Policy":["no-referrer"],"X-Content-Type-Options":["nosniff"],"Cross-Origin-Opener-Policy":["same-origin"],"Cross-Origin-Resource-Policy":["same-origin"],"X-Dns-Prefetch-Control":["off"],"Content-Security-Policy":["default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests"],"X-Permitted-Cross-Domain-Policies":["none"],"Content-Length":["34"],"Origin-Agent-Cluster":["?1"],"X-Download-Options":["noopen"],"Strict-Transport-Security":["max-age=15552000; includeSubDomains"],"X-Xss-Protection":["0"],"Alt-Svc":["h3=\":443\"; ma=2592000"],"Date":["Thu, 27 Jun 2024 22:15:46 GMT"]}}
Jun 27 15:16:19 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526579.6771302,"logger":"events","msg":"event","name":"tls_get_certificate","id":"c680a2c2-ccd3-477a-97f0-8c62cee6d94f","origin":"tls","data":{"client_hello":{"CipherSuites":[4866,4867,4865,49200,49196,49192,49188,49172,49162,159,107,57,52393,52392,52394,65413,196,136,129,157,61,53,192,132,49199,49195,49191,49187,49171,49161,158,103,51,190,69,156,60,47,186,65,49169,49159,5,4,49170,49160,22,10,255],"ServerName":"liveliteandwell.com","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2054,1537,1539,2053,1281,1283,2052,1025,1027,513,515],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771,770,769],"RemoteAddr":{"IP":"192.168.0.28","Port":52750,"Zone":""},"LocalAddr":{"IP":"192.168.100.17","Port":443,"Zone":""}}}}
Jun 27 15:16:19 rp-tailscale caddy[339064]: {"level":"debug","ts":1719526579.677233,"logger":"tls.handshake","msg":"choosing certificate","identifier":"liveliteandwell.com","num_choices":1}

The reason I went down the rabbit hole of specifying ca, ca_root (or acme_server) under tls under a separate call out for rp-tailscale.ecso.ghaar in Caddyfile is the desire to obtain caddy metrics. To do so, I need an entry like

rp-tailscale.esco.ghaar:8443 {
 metrics /metrics
}

But doing so will tell Caddy to contact LE’s ACME to obtain certs.

1 Like

Just noticed, you don’t need to do this. Caddy does it for you.

Do you want Caddy metrics for the machine that runs rp-tailscale.ecso.ghaar or liveliteandwell.com?

If it’s for the rp-tailscale.ecso.ghaar machine, then this is not how metrics of another machine is exposed. You need to run an agent on the other machine. If it’s for the liveliteandwell.com machine, then you’ll have to pick a different name. Caddy tried to get a certificate from Let’s Encrypt because the domain name you used looks like a legitimate domain. You can tell Caddy to issue a certificate from its own self-signed root, but then your metrics agent (Prometheus?) needs to either trust the certificate or ignore the certificate trust error (not recommended). You can also expose metrics under Caddy admin endpoint (default localhost:2019) by enabling it in global options.

The exposed metrics are for the subject Caddy instance. Read this article to learn more about it.

Since the core question of this topic is answered, it’s best if you open a new topic for other questions to ensure consistency and make it easier for future readers to track.

2 Likes

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