如何使用SSL HTTPS保护Amazon EC2 AWS中的Nginx前端和Puma后端

问题描述 投票:0回答:2

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

这是我第一次迁移到HTTPS并且我根本不熟练。读了很多,我取得了一些进展,但现在我被卡住了。

我想确认我是否采用了正确的方法,或者我的方法是否错误。

在这一刻:

  1. 我有一个Enjoy加密证书,安装并更新了我的Nginx服务器。现在,服务器正在侦听443,SSL正在前端工作。
  2. 我认为这足以保护网站,但我意识到我从前端发送到后端的请求中出现了阻塞:混合内容错误。
  3. 所以,我认为我还需要保护后端。 (请确认)
  4. 现在(这只是在开发中工作,而不是AWS实例)试图保护后端Puma服务器我采用了一种非常简单的方法:由于Rails API是私有的,我创建了一个自签名的SSL证书,只是用它来启动它Puma服务器是这样的: bundle exec puma -b'sssl://127.0.0.1:3000?key = puma.server.key&cert = puma.server.crt'-e development -S~ / puma -C config / puma / development.rb

如上所述,这正在开发中。我的Nginx服务器正在监听443并将请求发送到Puma侦听端口3000。

  1. 此时,我试图在我的EC2生产实例中做同样的事情。但在这里,我有一堵墙,我被困住了。我刚刚创建了另一个自签名证书,并以同样的方式启动了puma服务器。但是连接被拒绝了。我明白问题是EC2安全规则中的端口3000没有打开。我尝试在两个HTTPS中打开端口,EC2没有允许我,因为只适用于端口443和HTTP,但是因为服务器启动,因为SSL不能正常工作。

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

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

我理解你的方法。我建议,它阻碍了第二种方法。但是,我有一些问题:

  1. 我是否会解决使用此方法遇到的阻止:混合内容错误?为什么?我的意思是,Rails API请求是否会发生变化?注意:目前,在Angular中,我有资源发送请求,例如:// domain-name:8080 / action,Puma服务器正在侦听该端口中的请求。我目前没有任何代理通行证。
  2. 我想你包括连接到Puma套接字的de Nginx配置,我想我需要创建这个Puma套接字,我需要检查一下。如果你知道如何包含一个例子会有所帮助。如果我用这个套接字配置Puma,我是否需要在特定端口启动Puma?
  3. 我试图理解整个图片,但我仍然感到困惑:3.1 API(来自Angular Nginx)的请求应该如何? 3.2如果我应该在特定端口启动Puma?我不知道它是否需要套接字方法... 3.3并且代理传递配置应该如何匹配这些请求。

你能澄清一下可能更新你的例子吗?我们假设此时请求类似于//域名:8080 / action

UPDATE我正在尝试配置Nginx代理将请求传递给PUMA套接字(目前处于开发阶段)。我收到错误,请看一个新帖子以保持清洁:qazxsw poi

更新2它正在工作!我的网站安全无误!这是我的配置。

Nginx proxy pass to Rails API

我唯一的问题是:如果我评论所有proxy_set_header指令,如下所示:

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;
        }
    }

它也有效。我知道他们不是强制性的工作,应该包括在内,因为他们有一些好处吗?

与:相同:

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;
            }
ssl nginx amazon-ec2 https puma
2个回答
4
投票

你走错了路。

在大多数情况下,您不需要保护后端应用程序,这就是原因:

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

因此,任务归结为在nginx中配置https并通过与HTTP感知后端服务器的不安全连接执行ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; proxy_pass)。

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

  1. 您的后端服务器一无所知的Web主机名
  2. 是否生成https://nginx.ru/en/docs/http/ngx_http_proxy_module.html#proxy_passhttp网址
  3. 什么是真正的客户端的IP,因为你的后端应用程序会看到nginx的IP地址

以下是它通常如何解决的方法:

  1. https标头通过Host传递并由后端服务器接收
  2. proxy_set_header标头被传递并且通常受后端服务器的尊重
  3. X-Forwarded-Proto标头包含原始用户的IP

我搜索了与X-Forwarded-For相关的这些设置,这非常接近它最终的样子(从这里借来的puma),https://gist.github.com/rkjha/d898e225266f6bbe75d8部分对你的情况特别感兴趣:

@myapp_puma

现在关于你的角度应用。它需要知道它应该用于API请求的URL。它可以通过多种方式解决,但重点是NO URL应该在代码中进行硬编码,您可以使用环境变量代替。这是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; } 的方法之一 - 它使用在角应用程序之前包含的env.js文件,然后依赖于整个代码中定义的常量。在您的情况下,apiUrl应指向所需的https端点

described

另外:由于您的后端似乎正在处理没有API前缀的URL,您可以使用以下技巧与nginx:

(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));

在proxy_pass之后注意一个尾部斜杠 - 在这种情况下,将删除位置前缀。来自location /api/ { ... proxy_pass http://api.development/; ... }

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


1
投票

这听起来像整个考验是关于你在某处接受的here错误:

  • 它在浏览器中吗?无论好坏,浏览器永远不会真正知道前端服务器和后端服务器之间的连接是否超过blocked:mixed-contenthttp。换句话说,错误更可能是由于页面上的某些内容仍然通过https获取内容,无论是来自您自己的域还是来自第三方,而不是后端通过前端代理-qnd服务器在http上。例如,您可能希望在前端代码中将这些http更改为src="http://cdn.example.org/….js",以使所有JavaScript脚本都满意。
  • 它在后端吗?通常,为了“告诉”后端连接是安全的,前端代理必须添加适当的src="//cdn.example.org/….js"头。

否则,X-Forwarded-Proto确实在最新版本的nginx中支持经过验证的https,您可以使用http://nginx.org/r/proxy_pass指令的组合来配置安全策略,例如,proxy_ssl_…与您的自签名证书和/或CA的公共版本,以及proxy_ssl_trusted_certificate


附:实际上,我不同意关于后端和前端服务器之间加密性能影响的优点的其他答案。如果你有理由相信这种联系可能会被破坏(甚至谷歌发现他们的数据中心之间的专用光纤线已被政府利用),那么,当然,确实在后端和前端之间使用自签名的proxy_ssl_verify on;服务器。 在性能方面,https的主要成本来自于建立连接;但是在服务器场景中,那个连接可以重新用于服务多个客户端(例如,可能通过https控制);即使连接无法重用,后端和前端服务器之间的延迟通常也足够小,能够在没有性能影响的情况下维持一些额外的往返(特别是考虑到最终用户的延迟通常在订单上大于那个数量级)。 话虽如此,现在proxy_ssl_session_reuse被高度滥用 - 大多数公共网站都没有被强制使用强制性https address scheme的好处,因为它只会减少可以访问这些网站的人数(请参阅https仅仅是一份政策清单 - 基于问题,还有很多TLS不兼容的技术问题),加上面向客户的HTTP/2.0: The IETF Is Phoning It In确实会因为需要额外的往返来建立连接而降低性能,因此,如果你没有从https获得任何额外的好处,那就是通常只是一种责任。总而言之,如果没有它,你的偶尔猫图片的博客可能会更好。

© www.soinside.com 2019 - 2024. All rights reserved.