如何使用 SSL HTTPS 保护 Amazon EC2 AWS 中的 Nginx 前端和 Puma 后端 [英] How to secure with SSL HTTPS a Nginx front-end and Puma back-end in Amazon EC2 AWS

查看:74
本文介绍了如何使用 SSL HTTPS 保护 Amazon EC2 AWS 中的 Nginx 前端和 Puma 后端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将我的网站从 http 迁移到 https.架构是: 一个运行在 Nginx 服务器上的 angularJS webapp 前端(侦听端口 80),它将请求发送到运行在 Puma 服务器上的 Rails API 应用程序(侦听端口 8080).两台服务器共同生活在一个 Amazon EC2 实例中.

I´m trying to migrate my website from http to https. The architecture is: An angularJS webapp front-end running on Nginx server (listening on port 80) that sends requests to a Rails API app running on a Puma server (listening on port 8080). Both servers are living together in an Amazon EC2 instance.

这是我第一次迁移到 HTTPS,我一点也不熟练.阅读了很多,我取得了一些进步,但现在我卡住了.

It´s my first migration to HTTPS and I´m not skilled at all. Reading a lot, I made some progress but now I´m stuck.

我想确认我的方法是正确的还是错误的.

I would like to confirm if I´m in the right approach or however I´m in the wrong way.

目前:

  1. 我获得了 Let's encrypt 证书,安装并更新了我的 Nginx 服务器.现在,服务器正在侦听 443 和 SSL,在前端工作.
  2. 我认为这足以保护站点,但我意识到我在从前端发送到后端的请求中遇到了一个被阻止的:混合内容错误.
  3. 因此,我认为我还需要保护后端.(请确认)
  4. 现在(这仅在开发中有效,不适用于 AWS 实例)尝试保护后端 Puma 服务器的安全我找到了一个非常简单的方法:由于 Rails API 是私有的,我创建了一个自签名 SSL 证书并只是使用它来启动 Puma 服务器,如下所示:

  1. I got a Let´s encrypt certificate, installed and updated my Nginx server. Now, the server is listening in 443 and SSL in working in the front-end.
  2. I thought that was enough to secure a site, but I realized I got a blocked:mixed-content error in the requests sent from the front to the back-end.
  3. So, I assume I need to secure the backend also. (Please confirm)
  4. Now (This is only working in development, not AWS instance) Trying to secure the backend Puma server I came to a quite easy approach: As the Rails API is private, I created a self-signed SSL certificate and just uses it to start the Puma server like this:

bundle exec puma -b 'ssl://127.0.0.1:3000?key=puma.server.key&cert=puma.server.crt' -e development -S ~/puma -C config/puma/development.rb

bundle exec puma -b 'ssl://127.0.0.1:3000?key=puma.server.key&cert=puma.server.crt' -e development -S ~/puma -C config/puma/development.rb

如前所述,这正在开发中.我的 Nginx 服务器正在侦听 443,并向侦听端口 3000 的 Puma 发送请求.

As said, this is working in development. My Nginx server is listening in 443 and sends requests to Puma listening in port 3000.

  1. 此时,我尝试在我的 EC2 生产实例中执行相同的操作.但在这里,我有一面墙,我被卡住了.我刚刚创建了另一个自签名证书并以相同的方式启动了 puma 服务器.但连接被拒绝.我理解的问题是EC2安全规则中的3000端口没有打开.我试图在两个 HTTPS 中打开端口,EC2 不允许我,因为仅适用于端口 443 和 HTTP,但服务器启动时 SSL 也不起作用.

所以,在这一点上,我想知道我是否采用了正确的方法,但我只是遗漏了一些东西,否则,对于 EC2 实例来说,这是一种错误的方法,我需要做一些真正不同的事情.注意:我已经阅读了一些关于如何配置 Nginx 服务器来代理 https 的内容,但目前还不太了解.我应该走这条路吗?

So, at this point, I´m wondering if I´m in the right approach but I´m just missing something, or otherwise, this is a wrong approach for an EC2 instance and I need to do something really different. Note: I have read something about how to configure an Nginx server to proxy https, but at the moment, didn´t understand much. Should I go this way?

@ffeast 回答后的评论和问题:

我理解你的方法.我建议它采用第二种方法.但是,我有一些问题:

I understand your approach. It goes in the way of the second approach, I suggested. However, I have some questions:

  1. 我能解决用这种方法遇到的被阻止的:混合内容错误吗?为什么?我的意思是,Rails API 请求应该改变吗?注意:目前,在 Angular 中,我有资源发送如下请求://domain-name:8080/action 并且 Puma 服务器正在侦听该端口中的请求.我目前没有任何代理通行证.

  1. Will I solve the blocked:mixed-content error that I get with this approach? Why? I mean, should the Rails API requests change? Note: At the moment, in Angular I have resources that sends requests like: //domain-name:8080/action and the Puma server is listening the requests in that port. I don´t have any proxy-pass at the moment.

我想你包含了连接到 Puma 套接字的 de Nginx 配置,我想我需要创建这个 Puma 套接字,我需要检查如何.如果你知道包含一个例子会有什么帮助.如果我用这个socket配置Puma,我需要在特定端口启动Puma吗?

I think you included de Nginx configuration connecting to the Puma socket, I guess I need to create this Puma socket, I will need to check how. If you know how would be helpful to include an example. If I configure Puma with this socket, do I need to startup Puma in an specific port?

我试图理解整个画面,但我仍然对以下内容感到困惑:3.1 对 API 的请求(来自 Angular Nginx)应该是什么样子的?3.2 我是否应该在特定端口启动 Puma?我不知道套接字方法是否需要...3.3 代理传递配置应该如何匹配这些请求.

I try to understand the whole picture, but I´m stil confused with: 3.1 How the requests to the API (from Angular Nginx) should look like? 3.2 If I should startup Puma in an specific port? I don´t know if it´s required with the socket approach... 3.3 And how should the proxy-pass configuration looks like to match those requests.

您能否澄清一下可能会更新您的示例?假设此时请求类似于//domain-name:8080/action

Could you please clarify maybe updating your example? Let´s suppose at the moment the requests are like //domain-name:8080/action

更新我正在尝试将 Ningx 配置为代理将请求传递给 PUMA 套接字(目前正在开发中).我遇到错误,请查看新帖子以保持干净:Nginx 代理传递到Rails API

UPDATE I´m trying to config Ningx to proxy pass the requests to PUMA socket (in development at the moment). I´m getting errors, please see a new post to keep this clean: Nginx proxy pass to Rails API

更新 2它起作用了!我的网站是安全的,没有错误!这是我的配置.

UPDATE 2 It´s working! My website is secure with no errors! This is my configuration.

upstream api.development {
    # Path to Puma SOCK file, as defined previously
    server unix:/tmp/puma.sock fail_timeout=0;
}

server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      /keys/ssl/development.server.crt;
        ssl_certificate_key  /keys/ssl/development.server.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

        location / {
            root   /path-to-app;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html =404;
        }

        # Proxy pass requests to Yanpy API
        location /api {
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $host;
           #proxy_set_header X-Forwarded-Proto https;
           proxy_redirect off;
           rewrite ^/api(.*) /$1 break;
           proxy_pass http://api.development;
        }
    }

我唯一的问题是:如果我像这样评论所有 proxy_set_header 指令:

My only questions is: If I comment all proxy_set_header directives like this:

location /api {
               #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
               #proxy_set_header Host $host;
               #proxy_set_header X-Forwarded-Proto https;
               #proxy_redirect off;
               rewrite ^/api(.*) /$1 break;
               proxy_pass http://api.development;
            }

它也有效.我知道他们不是必须工作的,应该包括在内,因为他们有一些好处?

It works too. I understand they are not mandatory to work and should be included because they have some benefit?

同:

ssl_session_timeout  5m;
 ssl_protocols  SSLv2 SSLv3 TLSv1;
 ssl_ciphers  HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers   on;

推荐答案

你走错路了.

在大多数情况下,您不需要保护后端应用的安全,原因如下:

In most cases you don’t need to secure your backend app, here's why:

  1. 流量将通过本地连接或内部网络传输,因此通过安全连接路由没有意义
  2. 你会妨碍 nginx <-> 后端通信性能(可以忽略不计,但仍然如此)
  3. 额外的内部证书会出现各种问题
  4. 更重要的是 - 并非所有后端服务器都支持 https 处理 - 因为这根本不是他们的工作
  5. 从开发的角度来看,您的后端 Web 应用不应该关心它是通过 http 还是 httpS 运行 - 这些环境问题应该从您的应用逻辑中完全剖析

因此任务归结为在 nginx 中配置 https 并执行 proxy_pass (https://nginx.ru/en/docs/http/ngx_http_proxy_module.html#proxy_pass) 通过与 HTTP 感知后端服务器的不安全连接.

So the task boils down to configuring https in nginx and doing proxy_pass (https://nginx.ru/en/docs/http/ngx_http_proxy_module.html#proxy_pass) over an insecure connection to your HTTP-aware backend server.

问题是如何处理以下问题:

The question is how to deal with the following:

  1. 您的后端服务器一无所知的网络主机名
  2. 是否生成httphttps urls
  3. 真实客户端的 ip 是多少,因为您的后端应用程序会看到 nginx 的 ip 地址

通常的解决方法如下:

  1. Host 标头通过 proxy_set_header 并由后端服务器提取
  2. X-Forwarded-Proto 标头被传递并且通常被后端服务器尊重
  3. X-Forwarded-For header 包含原用户的ip
  1. Host header is passed via proxy_set_header and picked up by the backend server
  2. X-Forwarded-Proto header is passed and usually respected by backend servers
  3. X-Forwarded-For header contains the original user’s ip

我在谷歌上搜索了与 puma 相关的这些设置,这非常接近它最终的样子(从这里借用 https://gist.github.com/rkjha/d898e225266f6bbe75d8),@myapp_puma 部分对您的情况特别感兴趣:

I googled such setups related to puma, this is very close to how it might eventually look like (borrowed from here https://gist.github.com/rkjha/d898e225266f6bbe75d8),@myapp_puma section is of particular interest in your case:

upstream myapp_puma {
  server 127.0.0.1:8080 fail_timeout=0;
}
server {
 listen  443 default ssl;    
 server_name example.com;
 root /home/username/example.com/current/public;
 ssl on;
 ssl_certificate /home/username/.comodo_certs/example.com.crt;
 ssl_certificate_key /home/username/.comodo_certs/example.com.key;
 ssl_session_timeout  5m;
 ssl_protocols  SSLv2 SSLv3 TLSv1;
 ssl_ciphers  HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers   on;

 try_files $uri/index.html $uri @myapp_puma;

 location @myapp_puma {
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-Proto https;
   proxy_redirect off;
   proxy_pass http://myapp_puma;
 }

 error_page 500 502 503 504 /500.html;
 client_max_body_size 4G;
 keepalive_timeout 10;
}

现在关于您的 Angular 应用程序.它需要知道它应该为 API 请求使用什么 url.它可以通过多种方式解决,但要点是代码中不应硬编码 URL,您可以使用即环境变量.这是描述的方法之一- 它使用包含在 angular 应用程序之前的 env.js 文件,然后依赖于整个代码中定义的常量.在您的情况下 apiUrl 应指向所需的 https 端点

Now about your angular app. It needs to know what url it should use for the API requests. It can be solved in numerous ways, but the main point is that NO URLS should be hard-coded in the code, you can use i.e environment variables instead. Here's one of the approaches described - it uses an env.js file included before your angular app and then relies on the constants defined throughout the code. In your case apiUrl should point at the desired https endpoint

(function (window) {
  window.__env = window.__env || {};

  // API url
  window.__env.apiUrl = 'http://dev.your-api.com';

  // Base url
  window.__env.baseUrl = '/';

  // Whether or not to enable debug mode
  // Setting this to false will disable console output
  window.__env.enableDebug = true;
}(this));

补充:因为您的后端似乎正在处理没有 API 前缀的 URL,您可以在 nginx 中使用以下技巧:

Addition: as your backend appears to be working on URLs without API prefix, you can use the following trick with nginx:

location /api/ {        
  ...
  proxy_pass http://api.development/;
  ...
}

注意 proxy_pass 后面的斜杠 - 在这种情况下,位置前缀将被删除.从这里:

notice a trailing slash after proxy_pass - in this case the location prefix will be removed. From here:

如果使用 URI 指定了 proxy_pass 指令,那么当请求传递给服务器,这是规范化请求 URI 的一部分匹配的位置被指令中指定的 URI 替换

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive

这篇关于如何使用 SSL HTTPS 保护 Amazon EC2 AWS 中的 Nginx 前端和 Puma 后端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆