【问题标题】:Prevent Nginx from changing host防止 Nginx 更改主机
【发布时间】:2021-01-17 21:15:22
【问题描述】:

我正在构建一个现在在 localhost 上运行的应用程序。我在 https://localhost/ 上启动并运行了整个 dockerized 应用程序。 HTTP 请求被重定向到 HTTPS

我在 docker-compose.yml 中的 nginx 配置正在处理所有应有的请求。

我希望我的应用程序可以从任何地方访问,因此我尝试使用 Ngrok 将请求路由到我的本地主机。实际上我有一个正在开发的移动应用程序,所以需要一个本地服务器用于 api。

现在,当我在浏览器中输入 ngrok 的 url,如 abc123.ngrok.io 时,nginx 会将其转换为 https://localhost/。这适用于我的主机系统的浏览器,因为我的网络应用程序只在那里工作,但是当我在我的移动模拟器中打开它时。它不起作用。

我是 nginx 的新手。任何建议都将受到欢迎。 这是我的 nginx 配置。

nginx.conf

upstream web {
    ip_hash;
    server web:443;
}

# Redirect all HTTP requests to HTTPS
server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

# for https requests
server {

    # Pass request to the web container
    location / {
        proxy_pass https://web/;
    }

    location /static/ {
        root /var/www/mysite/;
    }
    
    listen 443 ssl;
    server_name localhost;

    # SSL properties
    # (http://nginx.org/en/docs/http/configuring_https_servers.html)    
    ssl_certificate /etc/nginx/conf.d/certs/localhost.crt;
    ssl_certificate_key /etc/nginx/conf.d/certs/localhost.key;
    root /usr/share/nginx/html;    
    add_header Strict-Transport-Security "max-age=31536000" always;
}

这个配置是我从教程中得到的。

【问题讨论】:

    标签: django nginx networking server ngrok


    【解决方案1】:

    首先,您将每个 HTTP 请求的重定向设置为 HTTPS:

    # Redirect all HTTP requests to HTTPS
    server {
        listen 80;
        server_name localhost;
        return 301 https://$server_name$request_uri;
    }
    

    您在此处使用$server_name 变量,因此对您的应用程序的每个/some/path?request_string HTTP 请求都将被重定向到https://localhost/some/path?request_string。至少将return 指令更改为

    return 301 https://$host$request_uri;
    

    查看this 问题以获取有关$host$server_name 变量之间差异的信息。

    如果这些是您的 nginx 配置中唯一的服务器块,您可以安全地删除 server_name localhost; 指令,这些块仍然是 80 和 443 TCP 端口上所有传入请求的默认块。

    第二个,如果您使用localhost 的自签名证书,请准备好浏览器抱怨证书不匹配(为localhost 颁发,出现在abc123.ngrok.io)。如果它没有破坏您的移动应用程序,那没关系,但如果是,您可以在启动 ngrok 连接后从 Lets Encrypt 免费获取您的abc123.ngrok.io 域的证书,查看this 页面以获取可用的 ACME 客户端和选项。或者,如果您的调试过程不严格要求 HTTPS,您可以完全禁用 HTTPS,只需使用这个 server 块:

    server {
        listen 80;
    
        # Pass request to the web container
        location / {
            proxy_pass https://web/;
        }
    
        location /static/ {
            root /var/www/mysite/;
        }
    }
    

    当然这不应该在生产中使用,只用于调试。

    最后一个。我认为在 docker 本身内部加密 nginx 和 web 容器之间的流量没有任何意义,特别是如果您已经使用 nginx 设置了 HTTP-to-HTTPS 重定向。它在安全性方面没有给你任何东西,而只是一些额外的开销。 nginx 和web 容器之间的通信使用端口 80 上的纯 HTTP 协议:

    upstream web {
        ip_hash;
        server web:80;
    }
    
    server {
        ...
        location / {
            proxy_pass http://web;
        }
    }
    

    【讨论】:

    • 感谢您提供全面的答案,这绝对有帮助。现在无法检查。如果它确实有效,将投票赞成。
    • 按照您的建议进行了更改。虽然我需要 HTTPS,所以只替换了 $server_name。仍然会自动将 ngrok url 更改为 localhost。
    • 此外,即使在仅对 http 使用单个服务器块之后。它仍然将我重定向到本地主机。我知道它不那么相关,但仍然如此。
    • @TaranjeetSingh 你确定这不是浏览器缓存的重定向吗?运行curl -i abc123.ngrok.io 并检查其输出。或者更好地将该输出添加到您的问题中。
    • 哦,是的。但怎么可能?我早些时候在隐身模式下尝试过。无论如何,我的坏。谢谢,我明白了。
    猜你喜欢
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 2012-12-30
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多