Caddy as Reverse Proxy on OpnSense - 502 Bad Gateway

1. The problem I’m having:

Can’t successfully complete SSL challenges.

I’m running Caddy as reverse proxy on OpnSense. I plan to accept 2 domains (blackcat.vip and punkfairie.net) to my network, which will be routed to 2 different sub-nets. I am only working on blackcat.vip for now while troubleshooting this problem.

Blackcat.vip 80/443 is currently accepted by OpnSense and routed to its server through port forwarding. I have successfully negotiated with Let’s Encrypt through this current setup (via the upstream host - not OpnSense) and am operating a secure site here.

I expect that I should be able to disengage port 80 forwarding so that it connects directly to OpnSense and is available for Caddy to bind to. And this does appear to work – but the SSL challenge won’t complete.

LetsDebug says all is well when only port 80 is unforwarded…but still no cert for Caddy. And when I unforward 443 as well, LetsDebug starts to have issues:


UnexpectedHttpResponse
Warning
Sending an ACME HTTP validation request to blackcat.vip results in unexpected HTTP response 502 Bad Gateway. This indicates that the webserver is misconfigured or misbehaving.
502 Bad Gateway



Trace:
@0ms: Making a request to http://blackcat.vip/.well-known/acme-challenge/letsdebug-test (using initial IP 67.168.20.17)
@0ms: Dialing 67.168.20.17
@394ms: Server response: HTTP 308 Permanent Redirect
@394ms: Received redirect to https://blackcat.vip/.well-known/acme-challenge/letsdebug-test
@394ms: Dialing 67.168.20.17
@970ms: Server response: HTTP 502 Bad Gateway 

Culring the server on OpnSense:

curl -vL 127.0.0.1:80
*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 () port 80
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/8.10.0
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 308 Permanent Redirect
< Connection: close
< Location: https://127.0.0.1/
< Server: Caddy
< Date: Sat, 05 Oct 2024 15:49:36 GMT
< Content-Length: 0
< 
* shutting down connection #0
* Clear auth, redirects to port from 80 to 443
* Issue another request to this URL: 'https://127.0.0.1/'
*   Trying 127.0.0.1:443...
* Connected to 127.0.0.1 () port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, internal error (592):
* OpenSSL/3.0.15: error:0A000438:SSL routines::tlsv1 alert internal error
* closing connection #1
curl: (35) OpenSSL/3.0.15: error:0A000438:SSL routines::tlsv1 alert internal error

I’m not sure what’s causing the 308 Permanent Redirect error - and other approaches give a 502 Error instead (such as in the logs below).

2. Error messages and/or full log output:

 "warn","ts":"2024-10-05T03:03:57Z","logger":"tls.issuance.acme","msg":"looking up info for HTTP challenge","host":"blackcat.vip","remote_addr":"66.133.109.36:44023","user_agent":"Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)","error":"no information found to solve challenge for identifier: blackcat.vip"}
 "error","ts":"2024-10-05T03:03:57Z","logger":"http.log.error","msg":"remote error: tls: internal error","request":{"remote_ip":"66.133.109.36","remote_port":"44023","client_ip":"66.133.109.36","proto":"HTTP/1.1","method":"GET","host":"blackcat.vip","uri":"/.well-known/acme-challenge/IfwWZTfPG6DwKLg_Kw-X8zULgddqbRVW7j6dv1wU-B0","headers":{"Referer":["http://blackcat.vip/.well-known/acme-challenge/IfwWZTfPG6DwKLg_Kw-X8zULgddqbRVW7j6dv1wU-B0"],"Accept-Encoding":["gzip"],"Connection":["close"],"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"","server_name":"blackcat.vip"}},"duration":0.001733746,"status":502,"err_id":"zu7eikp94","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}

3. Caddy version:

os-caddy 1.7.1 via OpnSense package manager

4. How I installed and ran Caddy:

a. System environment:

OPNsense 24.7.5-amd64
FreeBSD 14.1-RELEASE-p5
OpenSSL 3.0.15

b. Command:

Activate through GUI (runs on startup)

c. Service/unit/compose file:

n/a

d. My complete Caddy config:

Caddy File:

# DO NOT EDIT THIS FILE -- OPNsense auto-generated file


# caddy_user=root

# Global Options
{
	log {
		output net unixgram//var/run/caddy/log.sock {
		}
		format json {
			time_format rfc3339
		}
		level DEBUG
	}

	servers {
		protocols h1 h2 h3
	}

	email admin@blackcat.vip
	grace_period 10s
	import /usr/local/etc/caddy/caddy.d/*.global
}

# Reverse Proxy Configuration


# Reverse Proxy Domain: "e2738f8e-be32-4376-a70a-f68502629d64"
punkfairie.net {
}
# Reverse Proxy Domain: "a817b16d-3999-48dc-8d84-b678065fdad9"
blackcat.vip {
	handle {
		reverse_proxy 10.9.9.9:443 {
			transport http {
				tls
				tls_insecure_skip_verify
				tls_trust_pool file /var/db/caddy/data/caddy/certificates/temp/66ca340652a7f.pem
				tls_server_name 10.9.9.9
			}
		}
	}

	handle {
		reverse_proxy 10.9.9.9:80 {
		}
	}
}

import /usr/local/etc/caddy/caddy.d/*.conf

JSON Configuration

{
  "apps": {
    "http": {
      "grace_period": 10000000000,
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "protocols": [
            "h1",
            "h2",
            "h3"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "punkfairie.net"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "group": "group3",
                      "handle": [
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "handler": "reverse_proxy",
                                  "transport": {
                                    "protocol": "http",
                                    "tls": {
                                      "ca": {
                                        "pem_files": [
                                          "/var/db/caddy/data/caddy/certificates/temp/66ca340652a7f.pem"
                                        ],
                                        "provider": "file"
                                      },
                                      "insecure_skip_verify": true,
                                      "server_name": "10.9.9.9"
                                    }
                                  },
                                  "upstreams": [
                                    {
                                      "dial": "10.9.9.9:443"
                                    }
                                  ]
                                }
                              ]
                            }
                          ]
                        },
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "handler": "reverse_proxy",
                                  "upstreams": [
                                    {
                                      "dial": "10.9.9.9:80"
                                    }
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "blackcat.vip"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "issuers": [
              {
                "email": "admin@blackcat.vip",
                "module": "acme"
              },
              {
                "ca": "https://acme.zerossl.com/v2/DV90",
                "email": "admin@blackcat.vip",
                "module": "acme"
              }
            ],
            "subjects": [
              "punkfairie.net",
              "blackcat.vip"
            ]
          }
        ]
      }
    }
  },
  "logging": {
    "logs": {
      "default": {
        "encoder": {
          "format": "json",
          "time_format": "rfc3339"
        },
        "level": "DEBUG",
        "writer": {
          "address": "unixgram//var/run/caddy/log.sock",
          "output": "net"
        }
      }
    }
  }
}

5. Links to relevant resources:

Have you followed these docs when setting it up? What you did resulted in a kinda strange configuration.

https://docs.opnsense.org/manual/how-tos/caddy.html#caddy-reverse-proxy

1 Like

Hello - yes, I did. I’ve refollowed the directions now to make sure all is in order as described. What are you seeing in the conf that looks weird?

I dont understand why you created two reverse proxy entries on 443 and 80, only the first one will match, so remove the port 80 one.

Also when using tls insecure skip verify you dont need tls trust pool or tls server name.

Apart from that double check the Firewall rules of the OPNsense and that old port forward rules have been properly disabled.

You probably attached the handler meant for punkfairie to blackcat on accident.

1 Like

Hi - I rebuilt everything to docs and removed the pf.net entries. No good, unfortunately. Lets Debug still says 502 Bad Gateway.
I know that the port forwarding is off because as soon as I click Apply my Mastodon server stops working.
I’ve removed the internal cert chain.

Updated Caddyfile

# DO NOT EDIT THIS FILE -- OPNsense auto-generated file


# caddy_user=root

# Global Options
{
	log {
		output net unixgram//var/run/caddy/log.sock {
		}
		format json {
			time_format rfc3339
		}
		level DEBUG
	}

	servers {
		protocols h1 h2 h3
	}

	email admin@blackcat.vip
	grace_period 10s
	import /usr/local/etc/caddy/caddy.d/*.global
}

# Reverse Proxy Configuration


# Reverse Proxy Domain: "a817b16d-3999-48dc-8d84-b678065fdad9"
blackcat.vip {
	handle {
		reverse_proxy 10.9.9.9 {
			transport http {
				tls
				tls_insecure_skip_verify
			}
		}
	}
}

import /usr/local/etc/caddy/caddy.d/*.conf

Updated JSON conf

{
  "apps": {
    "http": {
      "grace_period": 10000000000,
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "protocols": [
            "h1",
            "h2",
            "h3"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "handler": "reverse_proxy",
                                  "transport": {
                                    "protocol": "http",
                                    "tls": {
                                      "insecure_skip_verify": true
                                    }
                                  },
                                  "upstreams": [
                                    {
                                      "dial": "10.9.9.9:80"
                                    }
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "blackcat.vip"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "issuers": [
              {
                "email": "admin@blackcat.vip",
                "module": "acme"
              },
              {
                "ca": "https://acme.zerossl.com/v2/DV90",
                "email": "admin@blackcat.vip",
                "module": "acme"
              }
            ],
            "subjects": [
              "blackcat.vip"
            ]
          }
        ]
      }
    }
  },
  "logging": {
    "logs": {
      "default": {
        "encoder": {
          "format": "json",
          "time_format": "rfc3339"
        },
        "level": "DEBUG",
        "writer": {
          "address": "unixgram//var/run/caddy/log.sock",
          "output": "net"
        }
      }
    }
  }
}

Curl from OpnSense

curl -vL http://127.0.0.1:80
*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 () port 80
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/8.10.0
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 308 Permanent Redirect
< Connection: close
< Location: https://127.0.0.1/
< Server: Caddy
< Date: Sat, 05 Oct 2024 18:21:32 GMT
< Content-Length: 0
< 
* shutting down connection #0
* Clear auth, redirects to port from 80 to 443
* Issue another request to this URL: 'https://127.0.0.1/'
*   Trying 127.0.0.1:443...
* Connected to 127.0.0.1 () port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, internal error (592):
* OpenSSL/3.0.15: error:0A000438:SSL routines::tlsv1 alert internal error
* closing connection #1
curl: (35) OpenSSL/3.0.15: error:0A000438:SSL routines::tlsv1 alert internal error

Log entries

"error","ts":"2024-10-05T18:17:57Z","logger":"http.log.error","msg":"tls: first record does not look like a TLS handshake","request":{"remote_ip":"65.21.146.168","remote_port":"48190","client_ip":"65.21.146.168","proto":"HTTP/1.1","method":"GET","host":"blackcat.vip","uri":"/.well-known/acme-challenge/letsdebug-test","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Debug emulating Let's Encrypt validation server; +https://letsdebug.net)"],"Accept":["*/*"],"Referer":["http://blackcat.vip/.well-known/acme-challenge/letsdebug-test"],"Accept-Encoding":["gzip"],"Connection":["close"]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"","server_name":"blackcat.vip"}},"duration":0.001320915,"status":502,"err_id":"zrfh0rfig","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}
"debug","ts":"2024-10-05T18:17:57Z","logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"10.9.9.9:80","duration":0.001153372,"request":{"remote_ip":"65.21.146.168","remote_port":"48190","client_ip":"65.21.146.168","proto":"HTTP/1.1","method":"GET","host":"blackcat.vip","uri":"/.well-known/acme-challenge/letsdebug-test","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Debug emulating Let's Encrypt validation server; +https://letsdebug.net)"],"Accept":["*/*"],"Referer":["http://blackcat.vip/.well-known/acme-challenge/letsdebug-test"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["blackcat.vip"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["65.21.146.168"]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"","server_name":"blackcat.vip"}},"error":"tls: first record does not look like a TLS handshake"}

Resolved by disabling the Let’s Encrypt auto-renew in the host software after noticing the redirects were looping. Both domains up and running - thanks

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