Caddyv2 offload SSL

1. Caddy version (caddy version):

v2.2.0

2. How I run Caddy:

caddy-api on ubuntu vm

a. System environment:

ubuntu 20.04

b. Command:

systemctl start caddy-api

c. Service/unit/compose file:

# caddy-api.service
#
# For using Caddy with its API.
#
# This unit is "durable" in that it will automatically resume
# the last active configuration if the service is restarted.
#
# See https://caddyserver.com/docs/install for instructions.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target

[Service]
User=caddy
Group=caddy
Environment="CONSUL_HTTP_ADDR=https://consul01p.net.work:8500"
ExecStart=/usr/bin/caddy run --environ --resume
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddyfile or JSON config:

N/A

3. The problem I’m having:

Hi there,

I’m trying to send traffic back to the 80 port (http) after receiving the requests on port 443 on my caddy server.
The application behind (web server) can’t run with 443 so I must redirect the traffic to 80.

This is what my configuration look like :

{
    "handle": [{
            "handler": "reverse_proxy",
            "transport": {
                "protocol": "http"
            },
            "upstreams": [
                {
                    "dial": "app1.net.work:80"
                }
            ]
        }
    ],
    "match": [
        {
            "host": [
                "app.net.work"
            ],
			"path": [
                        "/app1",
                        "/APP1"
            ]
        }
    ]
}

4. Error messages and/or full log output:

This is what I can found on my error log (caddy)

{"level":"debug","ts":1610460556.342307,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"app1.net.work:80","request":{"remote_addr":"ip1.ip1.ip1.ip1:42906","proto":"HTTP/1.1","method":"GET","host":"app.net.work","uri":"/app1","headers":{"User-Agent":["curl/7.29.0"],"X-Forwarded-For":["ip1.ip1.ip1.ip1"],"Accept":["*/*"],"X-Forwarded-Proto":["https"]},"tls":{"resumed":false,"version":771,"cipher_suite":49200,"proto":"","proto_mutual":true,"server_name":"app.net.work"}},"duration":0.006666728,"error":"tls: first record does not look like a TLS handshake"}
{"level":"error","ts":1610460556.3427713,"logger":"http.log.error.app","msg":"tls: first record does not look like a TLS handshake","request":{"remote_addr":"ip1.ip1.ip1.ip1:42906","proto":"HTTP/1.1","method":"GET","host":"app.net.work","uri":"/app1","headers":{"User-Agent":["curl/7.29.0"],"Accept":["*/*"]},"tls":{"resumed":false,"version":771,"cipher_suite":49200,"proto":"","proto_mutual":true,"server_name":"app.net.work"}},"duration":0.00718922,"status":502,"err_id":"rc8vpzpr0","err_trace":"reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:440)"}

5. What I already tried:

I tried to change port to 443 : app1.net.work:443 but like I said server can’t reply on this port so I’m ending up with error 502 too.
I don’t want to set to false “automatic_https” as I need it for the other servers proxied by caddy.

6. Links to relevant resources:

N/A

Also it is supposed to redirect to app1.net.work/app1 if it matches path /app1 but I did not find how to do it properly yet since I’m being stuck on the SSL offload first.

Thx for your help,

Regards,

FYI, path matching is exact in Caddy v2, so this would only match exactly /app1 and /APP1, but not /app1/foo. Add a * at the end of each to make this work, like /app1*.

The term you’re looking for is “proxy”. The word “redirect” has a different meaning in HTTP servers, i.e. telling the client to make a new request at a different URL. In JSON config a redirect is typically done with the static_response handler, setting the Location header to the new URL.

This is what confuses me. This error comes from the Go stdlib:

https://golang.org/src/crypto/tls/conn.go?h=first+record+does+not+look+like+a+TLS+handshake

It seems like Caddy is trying to do a TLS connection to your upstream.

What’s your full config?

Hi Françis,

Noted for the path, thanks.

As you can see, client request app.net.work and request are redirected to app1.net.work which is not the same URL.
So i can’t use upstreams ? I need to use static_response?

Here is my full configuration, I removed part from other proxied application because they are no relevant to my problem.

"admin": {
        "listen": "0.0.0.0:2019"
    },
    "apps": {
        "http": {
            "servers": {
                "netsrv": {
                    "listen": [
                        ":443",
                        ":35001",
                        ":35002"
                    ],
                    "logs": {
                        "logger_names": {
                            "app.net.work": "app"
                        }
                    },
                    "routes": [
                        {
                            {
                            "handle": [
                                {
                                    "handler": "reverse_proxy",
                                    "transport": {
                                        "protocol": "http",
                                        "tls": {}
                                    },
                                    "upstreams": [
                                        {
                                            "dial": "app1.net.work:80"
                                        }
                                    ]
                                }
                            ],
                            "match": [
                                {
                                    "host": [
                                        "app.net.work"
                                    ],
                                    "path": [
                                        "/app1",
                                        "/APP1"
                                    ]
                                }
                            ]
                        }
                    ],
                    "tls_connection_policies": [
                        {
                            "certificate_selection": {
                                "any_tag": [
                                    "netcert"
                                ]
                            }
                        }
                    ]
                }
            }
        },
        "tls": {
            "certificates": {
                "load_files": [
                    {
                        "certificate": "/etc/ssl/certs/net/pem-net.pem",
                        "key": "/etc/ssl/certs/net/key-net.key",
                        "tags": [
                            "netcert"
                        ]
                    }
                ]
            }
        }
    },
    "logging": {
        "logs": {
            "app": {
                "encoder": {
                    "format": "json"
                },
                "include": [
                    "http.log.access.app"
                ],
                "level": "DEBUG",
                "writer": {
                    "filename": "/var/log/caddy/app.log",
                    "output": "file"
                }
            },
            "default": {
                "encoder": {
                    "format": "json"
                },
                "exclude": [
                    "http.log.access.app"
                ],
                "level": "DEBUG",
                "writer": {
                    "filename": "/var/log/caddy/caddy-Go.log",
                    "output": "file"
                }
            }
        },
        "sink": {
            "writer": {
                "filename": "/var/log/caddy-tmp.log",
                "output": "file"
            }
        }
    }
}
```

Regards,

The "tls": {} here tells Caddy to try to connect over HTTPS. Remove that to connect over HTTP. (you didn’t include that part in your original post)

Indeed I thought I tried with and without I must have fix something and not retesting without it… apologize…

TO proxy any request from app.net.work/app1 to app1.net.work/application (example) am I going in the right direction with rewrite?

{
    "handle": [{
            "handler": "reverse_proxy",
            "transport": {
                "protocol": "http"
            },
            "upstreams": [
                {
                    "dial": "app1.net.work:80"
                }
            ]
        }
    ],
    "match": [
        {
            "host": [
                "app.net.work"
            ],
			"path": [
                        "/APP1*",
                        "/app1*"
            ]
        }
    ],
    "handle":[
        {
           "handler":"rewrite",
           "uri":"/application/"
        }
     ]
}

thx

The rewrite would need to be before the proxy handler (execution order matters).

That rewrite would not preserve the existing path, it would just make every request have exactly the path /application/. You’ll need to use a placeholder for the path here, i.e. /application{http.request.path}

But you also want to strip the existing /app1 prefix, so you’ll need a 2nd rewrite, before the first one, using strip_path_prefix:

If I were to write it with the Caddyfile (which I find easier to read and understand), it would look like this:

handle_path /app1* {
	rewrite * /application{uri}
	reverse_proxy app1.net.work:80
}

handle {
	# Fallback for otherwise unhandled requests
}

You can use the caddy adapt command to see what the JSON version of that would look like.

2 Likes

For those who can find this usefull here is the configuration (json) :

{
    "handle": [{
        "handler": "subroute",
        "routes": [{
            "match": [{
                "host": [
                    "app.netw.ork"
                ]
            }]
        },{
            "handle": [{
                "handler": "subroute",
                "routes": [{
                    "match": [{
                        "host": [
                            "app.netw.ork"
                        ],
                        "path": [
                                    "/APP1*",
                                    "/app1*"
                        ]
                    }],
                    "handle": [{
                        "handler": "subroute",
                        "routes": [{
                            "handle": [{
                                "handler": "rewrite",
                                "uri": "/APP1"
                            }],
                            "match": [{
                                "path": [
                                    "/app1"
                                ]
                            }]
                        },{
                            "handle": [{
                                "handler": "subroute",
                                "routes": [{
                                    "handle": [{
                                        "handler": "rewrite",
                                        "strip_path_prefix": "/APP1"
                                    }]
                                },{
                                    "handle": [{
                                        "handler": "rewrite",
                                        "uri": "/application/{http.request.uri}"
                                    }]
                                    
                                },{
                                    "handle": [{
                                        "handler": "reverse_proxy",
                                        "transport": {
                                            "protocol": "http"
                                        },
                                        "upstreams": [{
                                            "dial": "application1.netw.ork:80"
                                        }]
                                    }]
                                }]
                            }]
                        }]
                    }]
                }]
            }]
        }]
    }]
}

Thank you Françis for your help, appreciate.

Regards,