Nginx + Let's Encrypt + Https 重定向

Nginx + Let's Encrypt + Https 重定向

在过去的几个小时里,我试图了解 nginx 位置文档发生了什么,以及 serverfault 上其他人提出的问题(像这个)从我收集到的所有信息来看,我的解决方案应该工作,但事实并非如此。

因此,正如标题所述,我想配置 nginx,以便它可以为 acme.sh 创建的挑战文件提供服务,但重定向其他一切到在同一台服务器上配置的我的特定 https 域(这个域运行良好)。

我的服务器块:

server {
    listen      80 default_server;
    listen [::]:80 default_server;
    server_name _;
    root /usr/share/nginx/html;

    location ^~ /.well-known/acme-challenge/ {
        try_files $uri /;
    }
    location / {
        return 301 https://example.com$request_uri;
    }
}

为了测试目的,我在这个目录中自己创建了一个文件:/usr/share/nginx/html/.well-known/acme-challange/somefile。测试 curl 命令:curl http://example.com/.well-known/acme-challange/somefile

问题是:无论哪个请求,一切都是总是重定向。但是,当我删除/位置块时,curl 命令将返回我的测试文件的内容。显然,在这种情况下不会进行重定向。

根据 nginx 文档,我的理解是,使用我放置的修饰符,一旦 acme 前缀匹配(显然它匹配,因为当它是唯一的位置块时它会起作用),它就不应该尝试匹配其他任何东西。我也尝试过简单地删除指令try_files,但没有什么区别。除了return 301 ...我还尝试执行rewrite,它也有完全相同的行为:无论使用哪个 URI,总会有一个重定向。

由于某种原因,/位置块一旦出现就总是被使用,即使有更多匹配的具体位置,即使所述位置具有修饰符^~

我刚刚尝试的另一种变体:

server {
    listen      80 default_server;
    listen [::]:80 default_server;
    server_name _;
    root /usr/share/nginx/html;
    location /.well-known/acme-challenge/ {
        try_files $uri =404;
    }
    return 301 https://example.com$request_uri;
}

非常相似的行为:如果存在返回 -> 重定向。如果我将其注释掉:我的测试文件将通过 curl 调用提供给我。有一点很奇怪,我无法将指令移动到root位置块内。如果我这样做,nginx 会开始在 中查找文件/etc/nginx/html,这显然是默认的根目录,当我执行 http 请求时,它会在日志中抛出一个错误(“没有这样的文件或目录”)。

顺便说一句,我没有从这个服务器块中删除任何内容,我只是将域名更改为 example.com。它也是唯一一个监听端口 80 的服务器块,文件中不包含其他配置。当然,每次更改后,我还会重新启动 nginx 服务。如果这很重要,我的 nginx 版本是1.18.0

按照评论的要求输出nginx -T(此处由于字符限制,域名已更改并且 mime.types 文件被剪切):

2021/04/23 02:21:00 [warn] 88558#88558: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
user html;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include mime.types;
    default_type application/octet-stream;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES256+EECDH:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256";
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ecdh_curve secp384r1:prime256v1;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    # for certificate verification
    server {
        listen      80 default_server;
        listen [::]:80 default_server;
        server_name _;
        root /usr/share/nginx/html;
        location /.well-known/acme-challenge/ {
            try_files $uri =404;
        }
        #return 301 https://example.com$request_uri;
    }

    server {
        listen       443 ssl http2;
        listen  [::]:443 ssl http2;
        server_name  example.com;
        ssl_certificate ssl/example.com.crt;
        ssl_certificate_key ssl/example.com.key;

        #access_log  logs/host.access.log  main;

        root   /usr/share/nginx/html;
        index index.html index.php;
        location / {
            fastcgi_param SCRIPT_FILENAME $document_root/src/index.php;
            include fastcgi_params;
            # override SCRIPT_NAME which was set in fastcgi_params
            fastcgi_param SCRIPT_NAME /src/index.php;
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        }
        location /public/ {
            allow all;
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #    root   /usr/share/nginx/html;
        #}
    }
}


# configuration file /etc/nginx/mime.types:
types {
 #REMOVED BECAUSE OF CHARACTER LIMIT
}

# configuration file /etc/nginx/fastcgi_params:

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

答案1

我使用以下 vhost 配置来实现这个功能:

server {
    listen 80;

    server_name example.com;

    location /.well-known/ {
        root /whatever/i/specified/in/certbot/-d/argument;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

(SSL vhost 配置在这里并不重要)

与您的不同之处在于,我有root内部location。此设置在众多反向代理和原始服务器上运行良好。

相关内容