如何将现有的 nginx 配置更改为多台具有工作加密证书的本地计算机的反向代理

How to alter existing nginx config into a reverse proxy for multiple local machines with working lets-encrypt certificate

首先让我说一下,我的大部分“经验”来自于盲目地从各种博客和网站复制粘贴配置行,并希望一切顺利。

目前我有这样的设置:

动态 ddns 主机名指向我的 public IP 将传入流量从端口 80 和 443 重定向到具有 nextcloud 的 LXC 容器 + 来自 letsencrypt 的相同 ddns 主机名的证书。到目前为止一切顺利。

这是相关的 nginx 配置:

server {
server_name stats;
listen 9753 default_server;
listen [::]:9753 default_server;

location /nginx-status {
         stub_status on;
         access_log   off;
         allow 127.0.0.1;
         allow ::1;
         deny all;
         }

location ^~ /.well-known/acme-challenge {
         proxy_pass http://127.0.0.1:81;
         proxy_set_header Host $host;
         }

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

server {
server_name nextcloud;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
client_max_body_size 10240M;
root /var/www/nextcloud/;

location = /robots.txt {
         allow all;
         log_not_found off;
         access_log off;
         }

location = /.well-known/carddav {
         return 301 $scheme://$host/remote.php/dav;
         }

location = /.well-known/caldav {
         return 301 $scheme://$host/remote.php/dav;
         }

location / {
           rewrite ^ /index.php;
           }

location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
         deny all;
         }

location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
         deny all;
         }

location ^~ /apps/rainloop/app/data {
         deny all;
         }

location ~ \.(?:flv|mp4|mov|m4a)$ {
         mp4;
         mp4_buffer_size 100M;
         mp4_max_buffer_size 1024M;
         fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
         set $path_info $fastcgi_path_info;
         try_files $fastcgi_script_name =404;
         include fastcgi_params;
         include php_optimization.conf;
         }

location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
         fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
         set $path_info $fastcgi_path_info;
         try_files $fastcgi_script_name =404;
         include fastcgi_params;
         include php_optimization.conf;
         }

location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
         try_files $uri/ =404;
         index index.php;
         }

location ~ .(?:css|js|woff2?|svg|gif|map|png|html|ttf|ico|jpg|jpeg)$ {
         try_files $uri /index.php$request_uri;
         access_log off;
         expires 30d;
         }
}

我改变这个的最初设想是像以前一样使用 nextcloud.ddns.net 访问我的 nextcloud,但也能够通过 nextcloud.ddns.net/whatever 反向代理到不同的本地机器, nextcloud.ddns.net/something 等等 为什么?因为我完全不理解底层技术,所以我设想这将继续使用 nextcloud.ddns.net 已经有效的 ssl 证书,而我不必为每个目的地获取新证书。它是这样工作的吗?我仍然不知道,但这并没有阻止我尝试。我尝试在不同的地方包含一个新的 location /whatever 指令,但我所取得的只是 a) 它根本不起作用,b) 将我重定向到原始的 nextcloud,c) 仅在连接到本地 lan 时工作。

看到我没有到达任何地方,我走了另一条路并注册了另一个 ddns 主机名,指向相同的 public IP 并将此块包含在 nginx.conf 的顶部:

server {
listen 443 ssl;
server_name other_hostname.ddns.net;
location / {
         proxy_pass http://different_local_machine.lan/;
         }
}

这有效,但显然抱怨证书颁发给 nextcloud.ddns.net 而不是 other_hostname.ddns.net

然后回答我的问题:

  1. 是否完全可以像我最初想的那样使用 1 个具有不同 / 后缀的 ddns 主机名进行设置,或者这根本不是它的工作方式?

  2. 在具有多个 ddns 主机名的工作场景中,我将如何获取多个 lets-encrypt 证书?我担心如果我按照与获得 nextcloud 证书时相同的说明进行操作,我最终会搞砸它,因为它仍然是唯一面向互联网的 nginx。

  3. 如果忽略警告,我有多“安全”?我的意思是我知道该证书适用于不同的主机名,但我实际上知道它仍然是一个有效的证书。

再次为我的技术缺陷道歉,我花了几天时间才发现我想要实现的是反向代理,并没有从那里改进太多,但我认为我想要实现的应该在互联网陌生人的帮助下成为可能,而无需完成一个学期的计算机科学

感谢您的帮助!

这是一个可用于处理此问题的示例...您可能需要根据自己的需要调整设置...

我在与两个容器联网的 nginx docker 中使用它

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

在/etc/nginx/conf.d/ 目录中驻留了每个容器的配置文件..

--在site1.conf--

upstream production{

    server container_name1:80;

}

server {
    server_name  site1.com;

    location / {

    proxy_redirect off;
    proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        add_header Access-Control-Allow-Origin *;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://production/;

    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/site1.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/site1.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = site1.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name  site1.com;
    listen 80;
    return 404; # managed by Certbot


}

--在site2.conf--

upstream production_admin{

    server container_name2:80;

}

server {
    server_name  admin.site1.com;

    location / {

    proxy_redirect off;
    proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        add_header Access-Control-Allow-Origin *;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://production_admin/;

    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/site1.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/site1.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = admin.site1.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name  admin.site1.com;
    listen 80;
    return 404; # managed by Certbot


}

Upstream 将设置在 proxypass 中使用的名称,并仅在服务器的端口 80 之外提供服务。这应该可以帮助您入门

如果有人像我一样绝望并且遇到完全相同的问题,我设法在另一个论坛上找到了解决方案。 1 条该死的线,仅此而已。 proxy_set_header Referer $http_referer; 它有什么作用?我怎么知道?它让我的东西按我想要的方式工作,这就是我所关心的。

因此完整的工作位置块如下所示:

location ~ /something {
         proxy_pass http://somehost.lan:someport;
         proxy_set_header Referer $http_referer;
         proxy_set_header X-Real-IP  $remote_addr;
         proxy_set_header X-Forwarded-For $remote_addr;
         proxy_set_header Host $host;
}

导致我“发现”的讨论:https://unix.stackexchange.com/questions/290141/nginx-reverse-proxy-redirection底部post,第一条评论。