caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
58.41k stars 4.04k forks source link

caddy as CDN , 400 Bad Request #3543

Closed zuohuadong closed 4 years ago

zuohuadong commented 4 years ago

my computer:10.0.0.55 host : 10.0.0.113 ce.basicdn.cn

400 Bad Request


CDN server: 10.0.0.113 host: XXIP ce.basicdn.com

config:

{
  "logging": {
    "logs": {
      "zuo4": {
        "writer": {
          "output": "file",
          "filename": "zuo3",
          "roll": false,
          "roll_size_mb": 0,
          "roll_gzip": false,
          "roll_local_time": false,
          "roll_keep": 0,
          "roll_keep_days": 0
        },
        "encoder": {
          "format": "json",
          "message_key": "Zuo3S",
          "level_key": "",
          "time_key": "",
          "name_key": "",
          "caller_key": "",
          "stacktrace_key": "",
          "line_ending": "",
          "time_format": "",
          "duration_format": "",
          "level_format": ""
        },
        "level": "DEBUG",
        "sampling": {
          "interval": 0,
          "first": 0,
          "thereafter": 0
        }
      }
    }
  },
  "apps": {
    "tls": {
      "certificates": {
        "load_files": [
          {
            "certificate": "/home/workspace/cdn/1_ce.basicdn.cn_bundle.crt",
            "key": "/home/workspace/cdn/2_ce.basicdn.cn.key"
          }
        ]
      }
    },
    "http": {
      "servers": {
        "test1": {
          "listen": [":80",":443"],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "ce.basicdn.cn"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [
                    {
                      "dial": "ce.basicdn.cn:443"
                    }
                  ],
                  "headers": {
                    "request": {
                      "set": {
                        "Host": [
                          "ce.basicdn.cn"
                        ],
                        "X-Forwarded-For": [
                          "{http.request.remote.host}"
                        ],
                        "X-Forwarded-Port": [
                          "{http.request.port}"
                        ],
                        "X-Forwarded-Proto": [
                          "{http.request.scheme}"
                        ]
                      }
                    }
                  }
                }
              ]
            }
          ]
        }

      }
    }
  }
}

log:

{
    "level": "info",
    "Zuo3S": "skipping automatic certificate management because one or more matching certificates are already loaded",
    "domain": "ce.basicdn.cn",
    "server_name": "test1"
}
{
    "level": "info",
    "Zuo3S": "enabling automatic HTTP->HTTPS redirects",
    "server_name": "test1"
}
{
    "level": "warn",
    "Zuo3S": "user server is listening on same interface as automatic HTTP->HTTPS redirects; user-configured routes might override these redirects",
    "server_name": "test1",
    "interface": "tcp/:80"
}
{
    "level": "debug",
    "Zuo3S": "starting server loop",
    "address": "[::]:80",
    "http3": false,
    "tls": false
}
{
    "level": "debug",
    "Zuo3S": "starting server loop",
    "address": "[::]:443",
    "http3": false,
    "tls": true
}
{
    "level": "info",
    "Zuo3S": "cleaned up storage units"
}
{
    "level": "debug",
    "Zuo3S": "upstream roundtrip",
    "upstream": "ce.basicdn.cn:443",
    "request": {
        "method": "GET",
        "uri": "/",
        "proto": "HTTP/2.0",
        "remote_addr": "10.0.0.55:59309",
        "host": "ce.basicdn.cn",
        "headers": {
            "Upgrade-Insecure-Requests": [
                "1"
            ],
            "User-Agent": [
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
            ],
            "Sec-Fetch-User": [
                "?1"
            ],
            "Sec-Fetch-Dest": [
                "document"
            ],
            "Cache-Control": [
                "max-age=0"
            ],
            "X-Forwarded-Port": [
                ""
            ],
            "Accept": [
                "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Sec-Fetch-Site": [
                "none"
            ],
            "Accept-Language": [
                "zh-CN,zh;q=0.9"
            ],
            "X-Forwarded-For": [
                "10.0.0.55"
            ],
            "X-Forwarded-Proto": [
                "https"
            ],
            "Sec-Fetch-Mode": [
                "navigate"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "ciphersuite": 4865,
            "proto": "h2",
            "proto_mutual": true,
            "server_name": "ce.basicdn.cn"
        }
    },
    "duration": 0.052056774,
    "headers": {
        "Server": [
            "marco/2.11"
        ],
        "Date": [
            "Fri, 03 Jul 2020 03:25:08 GMT"
        ],
        "Content-Type": [
            "text/html"
        ],
        "Content-Length": [
            "671"
        ]
    },
    "status": 400
}
{
    "level": "debug",
    "Zuo3S": "upstream roundtrip",
    "upstream": "ce.basicdn.cn:443",
    "request": {
        "method": "GET",
        "uri": "/favicon.ico",
        "proto": "HTTP/2.0",
        "remote_addr": "10.0.0.55:59309",
        "host": "ce.basicdn.cn",
        "headers": {
            "Sec-Fetch-Site": [
                "same-origin"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Cache-Control": [
                "no-cache"
            ],
            "Accept": [
                "image/webp,image/apng,image/*,*/*;q=0.8"
            ],
            "X-Forwarded-Port": [
                ""
            ],
            "Pragma": [
                "no-cache"
            ],
            "Sec-Fetch-Mode": [
                "no-cors"
            ],
            "Accept-Language": [
                "zh-CN,zh;q=0.9"
            ],
            "X-Forwarded-For": [
                "10.0.0.55"
            ],
            "Sec-Fetch-Dest": [
                "image"
            ],
            "Referer": [
                "https://ce.basicdn.cn/"
            ],
            "X-Forwarded-Proto": [
                "https"
            ],
            "User-Agent": [
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "ciphersuite": 4865,
            "proto": "h2",
            "proto_mutual": true,
            "server_name": "ce.basicdn.cn"
        }
    },
    "duration": 0.052087432,
    "headers": {
        "Server": [
            "marco/2.11"
        ],
        "Date": [
            "Fri, 03 Jul 2020 03:25:08 GMT"
        ],
        "Content-Type": [
            "text/html"
        ],
        "Content-Length": [
            "671"
        ]
    },
    "status": 400
}

server: XXIP ce.basicdn.com

==================================================================================

But I change “CDN server” : match.host : “localhost” Then 200......

I think it' is BUG .

mholt commented 4 years ago

I don't really understand what you mean by "CDN server" and "host" -- can you be more specific about how we can reproduce the behavior you're expecting and what you're actually getting? Please provide more information, or I can provide a template if that will help.

It's not immediately clear to me what is going on, so I'll need your help to understand it better.

Ideally, we need to be able to reproduce the bug in the most minimal way possible. This allows us to write regression tests to verify the fix is working. If we can't reproduce it, then you'll have to test our changes for us until it's fixed -- and then we can't add test cases, either.

I've attached a template below that will help make this easier and faster! This will require some effort on your part -- please understand that we will be dedicating time to fix the bug you are reporting if you can just help us understand it and reproduce it easily.

This template will ask for some information you've already provided; that's OK, just fill it out the best you can. :+1: I've also included some helpful tips below the template. Feel free to let me know if you have any questions!

Thank you again for your report, we look forward to resolving it!

Template

## 1. Environment

### 1a. Operating system and version

```
paste here
```

### 1b. Caddy version (run `caddy version` or paste commit SHA)

```
paste here
```

### 1c. Go version (if building Caddy from source; run `go version`)

```
paste here
```

## 2. Description

### 2a. What happens (briefly explain what is wrong)

### 2b. Why it's a bug (if it's not obvious)

### 2c. Log output

```
paste terminal output or logs here
```

### 2d. Workaround(s)

### 2e. Relevant links

## 3. Tutorial (minimal steps to reproduce the bug)

Helpful tips

  1. Environment: Please fill out your OS and Caddy versions, even if you don't think they are relevant. (They are always relevant.) If you built Caddy from source, provide the commit SHA and specify your exact Go version.

  2. Description: Describe at a high level what the bug is. What happens? Why is it a bug? Not all bugs are obvious, so convince readers that it's actually a bug.

    • 2c) Log output: Paste terminal output and/or complete logs in a code block. DO NOT REDACT INFORMATION except for credentials.
    • 2d) Workaround: What are you doing to work around the problem in the meantime? This can help others who encounter the same problem, until we implement a fix.
    • 2e) Relevant links: Please link to any related issues, pull requests, docs, and/or discussion. This can add crucial context to your report.
  3. Tutorial: What are the minimum required specific steps someone needs to take in order to experience the same bug? Your goal here is to make sure that anyone else can have the same experience with the bug as you do. You are writing a tutorial, so make sure to carry it out yourself before posting it. Please:

    • Start with an empty config. Add only the lines/parameters that are absolutely required to reproduce the bug.
    • Do not run Caddy inside containers.
    • Run Caddy manually in your terminal; do not use systemd or other init systems.
    • If making HTTP requests, avoid web browsers. Use a simpler HTTP client instead, like curl.
    • Do not redact any information from your config (except credentials). Domain names are public knowledge and often necessary for quick resolution of an issue!
    • Note that ignoring this advice may result in delays, or even in your issue being closed. 😞 Only actionable issues are kept open, and if there is not enough information or clarity to reproduce the bug, then the report is not actionable.

Example of a tutorial:

Create a config file: ``` { ... } ``` Open terminal and run Caddy: ``` $ caddy ... ``` Make an HTTP request: ``` $ curl ... ``` Notice that the result is ___ but it should be ___.
zuohuadong commented 4 years ago

1. Environment

1a. Operating system and version

ubuntu 18.04 

1b. Caddy version (run caddy version or paste commit SHA)

 v2.1.1 h1:X9k1+ehZPYYrSqBvf/ocUgdLSRIuiNiMo7CvyGUQKeA=

2. Description

2a. What happens (briefly explain what is wrong)

my computer (10.0.0.55) -----------> server1 (10.0.0.113 caddy 2.1.1 [proxy]) ---------> server2 (10.0.1.212 web)
/etc/host: 10.0.0.113 ce.basicdn.cn /etc/host:10.0.1.212 ce.basicdn.cn none

In "10.0.0.55" : curl -L "https://ce.basicdn.cn" ————> 400 Bad Request

In "10.0.0.113" : curl -L "https://ce.basicdn.cn" ——> 200 OK !

2b. Why it's a bug (if it's not obvious)

400 Bad Request.

2c. Log output

server 1 log:

{
    "level": "info",
    "Zuo3S": "skipping automatic certificate management because one or more matching certificates are already loaded",
    "domain": "ce.basicdn.cn",
    "server_name": "test1"
}
{
    "level": "info",
    "Zuo3S": "enabling automatic HTTP->HTTPS redirects",
    "server_name": "test1"
}
{
    "level": "warn",
    "Zuo3S": "user server is listening on same interface as automatic HTTP->HTTPS redirects; user-configured routes might override these redirects",
    "server_name": "test1",
    "interface": "tcp/:80"
}
{
    "level": "debug",
    "Zuo3S": "starting server loop",
    "address": "[::]:80",
    "http3": false,
    "tls": false
}
{
    "level": "debug",
    "Zuo3S": "starting server loop",
    "address": "[::]:443",
    "http3": false,
    "tls": true
}
{
    "level": "info",
    "Zuo3S": "cleaned up storage units"
}
{
    "level": "debug",
    "Zuo3S": "upstream roundtrip",
    "upstream": "ce.basicdn.cn:443",
    "request": {
        "method": "GET",
        "uri": "/",
        "proto": "HTTP/2.0",
        "remote_addr": "10.0.0.55:59309",
        "host": "ce.basicdn.cn",
        "headers": {
            "Upgrade-Insecure-Requests": [
                "1"
            ],
            "User-Agent": [
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
            ],
            "Sec-Fetch-User": [
                "?1"
            ],
            "Sec-Fetch-Dest": [
                "document"
            ],
            "Cache-Control": [
                "max-age=0"
            ],
            "X-Forwarded-Port": [
                ""
            ],
            "Accept": [
                "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Sec-Fetch-Site": [
                "none"
            ],
            "Accept-Language": [
                "zh-CN,zh;q=0.9"
            ],
            "X-Forwarded-For": [
                "10.0.0.55"
            ],
            "X-Forwarded-Proto": [
                "https"
            ],
            "Sec-Fetch-Mode": [
                "navigate"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "ciphersuite": 4865,
            "proto": "h2",
            "proto_mutual": true,
            "server_name": "ce.basicdn.cn"
        }
    },
    "duration": 0.052056774,
    "headers": {
        "Server": [
            "marco/2.11"
        ],
        "Date": [
            "Fri, 03 Jul 2020 03:25:08 GMT"
        ],
        "Content-Type": [
            "text/html"
        ],
        "Content-Length": [
            "671"
        ]
    },
    "status": 400
}
{
    "level": "debug",
    "Zuo3S": "upstream roundtrip",
    "upstream": "ce.basicdn.cn:443",
    "request": {
        "method": "GET",
        "uri": "/favicon.ico",
        "proto": "HTTP/2.0",
        "remote_addr": "10.0.0.55:59309",
        "host": "ce.basicdn.cn",
        "headers": {
            "Sec-Fetch-Site": [
                "same-origin"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Cache-Control": [
                "no-cache"
            ],
            "Accept": [
                "image/webp,image/apng,image/*,*/*;q=0.8"
            ],
            "X-Forwarded-Port": [
                ""
            ],
            "Pragma": [
                "no-cache"
            ],
            "Sec-Fetch-Mode": [
                "no-cors"
            ],
            "Accept-Language": [
                "zh-CN,zh;q=0.9"
            ],
            "X-Forwarded-For": [
                "10.0.0.55"
            ],
            "Sec-Fetch-Dest": [
                "image"
            ],
            "Referer": [
                "https://ce.basicdn.cn/"
            ],
            "X-Forwarded-Proto": [
                "https"
            ],
            "User-Agent": [
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "ciphersuite": 4865,
            "proto": "h2",
            "proto_mutual": true,
            "server_name": "ce.basicdn.cn"
        }
    },
    "duration": 0.052087432,
    "headers": {
        "Server": [
            "marco/2.11"
        ],
        "Date": [
            "Fri, 03 Jul 2020 03:25:08 GMT"
        ],
        "Content-Type": [
            "text/html"
        ],
        "Content-Length": [
            "671"
        ]
    },
    "status": 400
}

3. Tutorial (minimal steps to reproduce the bug)

need: 1 computer (eg:A) 2 server (eg: B C) 1 domian & cert (eg: ce.basicdn.cn)

C: (“ce.basicdn.cn” web server IP: 10.0.1.212)

caddy file-server --root ./  --listen 443 --domain "ce.basicdn.cn"

B : (IP: 10.0.0.113)

change /etc/host: add 10.0.1.212 ce.basicdn.cn

then, caddy.json is:

{
  "apps": {
    "tls": {
      "certificates": {
        "load_files": [
          {
            "certificate": "/home/workspace/cdn/Nginx/1_ce.basicdn.cn_bundle.crt",
            "key": "/home/workspace/cdn/Nginx/2_ce.basicdn.cn.key"
          }
        ]
      }
    },
    "http": {
      "servers": {
        "test1": {
          "listen": [":80",":443"],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "ce.basicdn.cn"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [
                    {
                      "dial": "ce.basicdn.cn:443"
                    }
                  ],
                  "headers": {
                    "request": {
                      "set": {
                        "Host": [
                          "ce.basicdn.cn"
                        ],
                        "X-Forwarded-For": [
                          "{http.request.remote.host}"
                        ],
                        "X-Forwarded-Port": [
                          "{http.request.port}"
                        ],
                        "X-Forwarded-Proto": [
                          "{http.request.scheme}"
                        ]
                      }
                    }
                  }
                }
              ]
            }
          ]
        }

      }
    }
  }
}

Open terminal and run Caddy: caddy run --config Caddy.json


A: (ip:10.0.0.55)

change /etc/host: add 10.0.1.113 ce.basicdn.cn

bash: curl “https://ce.basicdn.cn”

zuohuadong commented 4 years ago

@mholt
I have added information

francislavoie commented 4 years ago

The status 400 response doesn't come from Caddy, it comes from your upstream server. You'll need to debug your upstream to figure out why it's returning a 400. All we can do is guess here. We don't know what your upstream is doing or what it expects.

zuohuadong commented 4 years ago

The status 400 response doesn't come from Caddy, it comes from your upstream server. You'll need to debug your upstream to figure out why it's returning a 400. All we can do is guess here. We don't know what your upstream is doing or what it expects.

in B (server): bash: curl “https://ce.basicdn.cn” is 200 OK .

in A (computer) bash: curl “https://ce.basicdn.cn” is 400 .

so, C is OK .

francislavoie commented 4 years ago

Yes, we get that. But that's not Caddy's fault. It might be due to a misconfiguration of Caddy causing the expectation of your upstream to not be met, but it's not because of anything inherent in Caddy.

We don't have enough information about what your upstream server is or does, so there's not much we can do. You'll need to figure out what triggers the 400 response from your upstream server. Status code 400 on its own doesn't tell us anything at all about what's wrong. There must be an error message in the response body that describes the reason for the error, but you didn't share that with us. And even if you did, I figure we wouldn't be able to narrow things down much because we don't know what your upstream server does.

zuohuadong commented 4 years ago

Yes, we get that. But that's not Caddy's fault. It might be due to a misconfiguration of Caddy causing the expectation of your upstream to not be met, but it's not because of anything inherent in Caddy.

We don't have enough information about what your upstream server is or does, so there's not much we can do. You'll need to figure out what triggers the 400 response from your upstream server. Status code 400 on its own doesn't tell us anything at all about what's wrong. There must be an error message in the response body that describes the reason for the error, but you didn't share that with us. And even if you did, I figure we wouldn't be able to narrow things down much because we don't know what your upstream server does.

In B (server), only change : match.host : “localhost”

Then In A : curl “http://10.0.0.113” is 200 OK .

So I think this is still caddy's BUG.

francislavoie commented 4 years ago

No, like I said, Caddy is not returning the 400 error. It's not a bug in Caddy.

I'm going to close this now because there's not enough evidence or information for us to do anything at this point.

zuohuadong commented 4 years ago

No, like I said, Caddy is not returning the 400 error. It's not a bug in Caddy.

I'm going to close this now because there's not enough evidence or information for us to do anything at this point.

In other words, only caddy will have 400 errors. Using nginx is normal.

image

francislavoie commented 4 years ago

Are you intentionally trying to use unencrypted HTTP traffic on port 443?

Again, it's unclear what your upstream server is expecting. You'll need to debug your upstream server to determine what's different about proxying via nginx compared to via Caddy.

zuohuadong commented 4 years ago

Are you intentionally trying to use unencrypted HTTP traffic on port 443?

You can view my configuration file.

image

Then curl “https://ce.basicdn.cn

Again, it's unclear what your upstream server is expecting. You'll need to debug your upstream server to determine what's different about proxying via nginx compared to via Caddy.

You can use any https page for testing, provided you have a certificate.

C web server is just a test station.

You can also build your own test station. Use nginx, caddy or Apache.

@francislavoie

francislavoie commented 4 years ago

I think you misunderstand what I'm saying.

You only told Caddy you want to proxy to ce.basicdn.cn:443. Caddy is proxying over HTTP, not HTTPS. When using JSON config, you need to be specific about enabling TLS for the proxy.

Please take a look at https://caddyserver.com/docs/json/apps/http/servers/errors/routes/handle/reverse_proxy/transport/http/ for the proxy transport configuration.

zuohuadong commented 4 years ago

I think you misunderstand what I'm saying.

You only told Caddy you want to proxy to ce.basicdn.cn:443. Caddy is proxying over HTTP, not HTTPS. When using JSON config, you need to be specific about enabling TLS for the proxy.

Please take a look at https://caddyserver.com/docs/json/apps/http/servers/errors/routes/handle/reverse_proxy/transport/http/ for the proxy transport configuration.

client_certificate_automate: "ce.basicdn.cn" is 400

I want to make caddy into a node similar to cloudflare, you can add your own website as a proxy. The original station can have 80 and 443 at the same time. And there is no need to upload your own certificate.

@francislavoie

mholt commented 4 years ago

@zuohuadong I too am not convinced this is a bug in Caddy, this seems more to be a question about how to use it. Please use our forum to get help with using Caddy: https://caddy.community - and someone will probably be willing to help answer your questions there!

Note, however, that building your own CDN is a big task and asking for someone to show you how to do it is asking a lot of somebody for free.