如何让 SSL 与 Rails、AWS Elastic Beanstalk 和 Cloudflare 一起使用

Posted

技术标签:

【中文标题】如何让 SSL 与 Rails、AWS Elastic Beanstalk 和 Cloudflare 一起使用【英文标题】:How to get SSL working with Rails, AWS Elastic Beanstalk and Cloudflare 【发布时间】:2018-08-28 10:59:13 【问题描述】:

我有一个托管在 Elastic Beanstalk 上的站点,该站点使用 Ruby on Rails 构建。我设置 Cloudflare 来配置 DNS 并提供 CDN。 Cloudflare 还提供 SSL。

我无法让 SSL 与我的应用程序一起使用。

通过将 Cloudflare 的 SSL 设置为“灵活”,我可以加载我的主页,但是当我尝试登录时,我收到了这些错误(为简洁起见进行了编辑):

INFO -- :  Started POST "/users/sign_in" for xxx.xxx.146.132 at 2018-03-19 16:45:24 +0000
INFO -- :  Processing by Users::SessionsController#create as html
INFO -- :    Parameters: "utf8"=>"✓", "authenticity_token"=>"f92CTIe5qlp7C624DZzZM2oWdFMcq6PhyfOJI16saV32yugMmJlenL/F3gTeBBsAjaAw92P1vncWBzI+JnK8wA==", "user"=>"email"=>"test@test.com", "password"=>"[FILTERED]", "commit"=>"Log in"
WARN -- :  HTTP Origin header (https://[MY_URL].com) didn't match request.base_url (http://[MY_URL].com)
INFO -- :  Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)  
FATAL -- :  ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

如果我将 Cloudflare 的 SSL 设置为“完整”,我会在 Cloudflare 生成的页面上收到 502 错误(见图)。

我遇到了这个网站 (http://til.obiefernandez.com/posts/875a2a69af-cloudflare-flexible-ssl-mode-breaks-rails-5-csrf),它似乎有完全相同的问题,但设置为“完整”并没有帮助我。

我尝试在 /config/environments/production.rb 中设置 config.force_ssl = true。该设置不允许对该站点进行任何访问。只显示来自 Cloudflare 的相同 502 错误页面,而我的生产或 nginx 日志中没有任何内容。

我尝试过使用自定义 nginx 配置,但没有得到任何结果。这是我最新的 nginx 配置尝试:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events 
    worker_connections 1024;


http 
    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;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

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

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

    index   index.html index.htm;

    server 
        listen       80 ;
        listen       [::]:80 ;
        server_name  localhost;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;


        location / 
          proxy_pass        http://localhost;
          proxy_set_header  Host $host;
          proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header  X-Forwarded-Proto $scheme;
          proxy_set_header  X-Forwarded-Ssl on; # Optional
          proxy_set_header  X-Forwarded-Port $server_port;
          proxy_set_header  X-Forwarded-Host $host;
        
        error_page 404 /404.html;
            location = /40x.html 
        

        # redirect server error pages to the static page /50x.html
        #
        error_page 500 502 503 504 /50x.html;
            location = /50x.html 
        
    

有人可以帮忙吗?我确定我在这里遗漏了一些明显的东西。

【问题讨论】:

任何 cmets 都会有所帮助。我真的坚持这个。 看起来您遇到了 CORS 问题。由于您已谴责 [my-url].com 的错误日志,因此很难确定。我的猜测是,您有一些使用与 cloudflare URL 不同的 url 的 javascript。 IE。即使通过 cloudflare.com 访问该站点,您也有一些使用 elasticbeanstalk url 的 javascript 您收到了ActionController::InvalidAuthenticityToken,所以首先要调查的是:令牌在每个页面加载时都会改变还是保持不变?我的猜测是 Cloudflare 正在缓存您的登录页面,因此每次都发送相同的令牌,这显然是无效的。请检查并告诉我! 另外,在您当前的设置中设置config.force_ssl = true 是错误的。让我们解决最初的问题,然后继续在 AWS 和 Cloudflare 之间建立安全连接 您使用的是哪种 Elastic Beanstalk 环境?负载均衡的?在这种情况下,负载均衡器将终止 SSL 并通过“正常”http 与您的虚拟机对话。 【参考方案1】:

502 错误:此错误表示 Cloudfare 服务器无法读取您的 rails 服务器发送的响应,基本上当您选择 Full SSL 时,Cloudflare 预计响应是 SSL 但在这里rails 应用程序发送 Cloudflare 无法读取的 NON-SSL (HTTP) 响应。

我阅读了您分享的文章,看起来 Rails 出于安全原因不允许使用灵活的 SSL。

灵活的 SSLflexible SSL 中,您不需要使用 SSL 证书 (HTTPS) 保护您的 Rails 应用程序,但您的访问者仍会看到该站点启用了 HTTPS。

Flexible SSL:访问者与 Cloudflare 之间的安全连接, 但 Cloudflare 和您的 Web 服务器之间没有安全连接。你 不需要在您的网络服务器上拥有 SSL 证书,但您的 访问者仍然认为该网站启用了 HTTPS。

完整的 SSL 如article 中所述,如果启用Full SSL,则需要配置rails config.force_ssl = true 以使用自签名SSL 证书,或者您可以免费从letsencrypt 获得证书,一旦您这样做了,您需要将您的 Nginx 更改为在 HTTPS 端口 443 上运行。这应该可以修复 502 错误。

这是Using HTTPs with Ruby on Rails的教程

Full SSL:访问者与 Cloudflare 之间的安全连接,以及 Cloudflare 和您的设备之间的安全连接(但未经过身份验证) 网络服务器。您需要将服务器配置为回答 HTTPS 连接,至少带有自签名证书。

Image Source

【讨论】:

以上是关于如何让 SSL 与 Rails、AWS Elastic Beanstalk 和 Cloudflare 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在aws中为cname设置ssl证书?

在 Rails 应用程序中向 PostgreSQL 提供 SSL 证书

在 AWS Elastic Beanstalk / Rails 上配置 HTTPS

Paperclip + Rails 与负载平衡机器

AWS Certificate Manager - SSL 说正在使用,但 HTTPS 不起作用

如何使用 SSL 将 AWS EC2 Flask 应用程序部署到 HTTPS 端口 443?