502 Bad Gateway when using Caddy as a reverse proxy

1. The problem I’m having:

I’m trying to configure Caddy to act as a reverse proxy in front of GitHub Enterprise Server which uses port 8443 for its management console. This port is blocked on my company’s network. When I access the URL for the reverse proxy I receive a 502 Bad Gateway error.

Note that if I run Caddy locally using caddy start and access it using http://localhost the reverse proxy appears to be working correctly and I am taken to the GitHub Enterprise Server management console. However, the URL in the web browser changes to the upstream URL and port; not sure if that is supposed to happen?

2. Error messages and/or full log output:

curl -vL https://manage.github.example.com/

*   Trying [REDACTED IP ADDRESS]:443...
* Connected to manage.github.example.com (REDACTED) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=manage.github.example.com
*  start date: Mar 29 10:21:42 2023 GMT
*  expire date: Jun 27 11:07:50 2023 GMT
*  subjectAltName: host "manage.github.example.com" matched cert's "manage.github.example.com"
*  issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1D4
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: GET]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: manage.github.example.com]
* h2h3 [user-agent: curl/7.86.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x7fb21f011400)
> GET / HTTP/2
> Host: manage.github.example.com
> user-agent: curl/7.86.0
> accept: */*
> 
< HTTP/2 502 
< content-type: text/html; charset=UTF-8
< referrer-policy: no-referrer
< content-length: 332
< date: Wed, 29 Mar 2023 15:50:41 GMT
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< 

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>502 Server Error</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Server Error</h1>
<h2>The server encountered a temporary error and could not complete your request.<p>Please try again in 30 seconds.</h2>
<h2></h2>
</body></html>
* Connection #0 to host manage.github.example.com left intact

Log entry:

{
  "level": "debug",
  "ts": 1680105520.7144086,
  "logger": "http.handlers.reverse_proxy",
  "msg": "upstream roundtrip",
  "upstream": "github.example.com:8443",
  "duration": 3.001128821,
  "request": {
    "remote_ip": "10.119.3.35",
    "remote_port": "44493",
    "proto": "HTTP/1.1",
    "method": "GET",
    "host": "github.example.com:8443",
    "uri": "/",
    "headers": {
      "X-Forwarded-For": [
        "10.119.3.35"
      ],
      "User-Agent": [
        "GoogleHC/1.0"
      ],
      "X-Forwarded-Proto": [
        "http"
      ],
      "X-Forwarded-Host": [
        "10.119.3.35"
      ]
    }
  },
  "error": "dial tcp [GOOGLE LOAD BALANCER IP ADDRESS]:8443: i/o timeout"
}
{
  "level": "error",
  "ts": 1680105520.714512,
  "logger": "http.log.error",
  "msg": "dial tcp [GOOGLE LOAD BALANCER IP ADDRESS]:8443: i/o timeout",
  "request": {
    "remote_ip": "10.119.3.35",
    "remote_port": "44493",
    "proto": "HTTP/1.1",
    "method": "GET",
    "host": "10.119.3.35",
    "uri": "/",
    "headers": {
      "User-Agent": [
        "GoogleHC/1.0"
      ],
      "Connection": [
        "Keep-alive"
      ]
    }
  },
  "duration": 3.001374337,
  "status": 502,
  "err_id": "3nxz5g64v",
  "err_trace": "reverseproxy.statusError (reverseproxy.go:1272)"
}

3. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

I am running Caddy as a Docker image on Google Kubernetes Engine. Caddy is running as a Kubernetes Deployment with a Kubernetes Ingress and NodePort Service bound to port 80 in front.

a. System environment:

Google Kubernetes Engine with automatic TLS turned off within Caddy as I’m using a Google-managed TLS certificate with the Google external HTTPS load balancers. I have verified that Caddy is running correctly by initially deploying a minimal “Hello World” Caddy configuration.

b. Command:

N/A

c. Service/unit/compose file:

Dockerfile:

FROM caddy

COPY proxy/Caddyfile /etc/caddy/Caddyfile

d. My complete Caddy config:

{
	auto_https off
    debug
}

:80 {
	handle /health {
		respond 200
	}

	reverse_proxy https://github.example.com:8443 {
		header_up Host {upstream_hostport}
	}
}

That’s not really a Caddy problem, it’s a networking problem between Caddy and the upstream causing the connection to fail. I can’t really help with that, you’ll need to investigate your networking conditions to figure out why it won’t connect.

The upstream is probably serving redirects (using the Location header) to certain pages with an absolute URL (including scheme/hostname). You’d have to configure the upstream app to be aware of the real hostname you’ll be connecting with.

Probably best if you reach out to your company’s network admins to stop blocking the traffic you need.

Thank you for the pointers.

Unfortunately it’s not possible for me to change the configuration of the upstream app because it’s a virtual appliance and doing so would violate the support Ts & Cs. Trying to get the corporate network reconfigured is a battle I’d rather not contemplate…

Not to worry. Thanks again.

John

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