如何让SSL在Rails、AWS Elastic Beanstalk与Cloudflare环境中正常工作?
Hey there, let's break down why your login POST request is failing with Cloudflare's Flexible SSL mode, and how to fix it.
The Root Cause
Cloudflare's Flexible SSL mode creates a tricky protocol mismatch:
- Users connect to Cloudflare over HTTPS
- But Cloudflare connects to your Elastic Beanstalk/Rails app over plain HTTP
Rails has no way to detect the original HTTPS request unless you explicitly configure it, which leads to two critical issues:
- Rails generates CSRF tokens tied to HTTP instead of HTTPS. When the user submits the login form (served over HTTPS), the token validation fails because the protocol doesn't match.
- If your app uses
securecookies (standard for authentication), these cookies won't be sent back to Rails over the unencrypted HTTP connection from Cloudflare, breaking the login flow entirely.
Fix Options
Option 1: Switch Cloudflare SSL to Full/Full (Strict) (Recommended)
This is the most secure and clean long-term solution. Here's how to implement it:
- Get an SSL certificate for your Elastic Beanstalk environment (AWS Certificate Manager offers free certificates that integrate seamlessly with Elastic Beanstalk)
- Configure Elastic Beanstalk to use this certificate for HTTPS connections
- In Cloudflare's SSL/TLS settings, switch the mode to Full or Full (Strict)
This setup ensures end-to-end encryption (HTTPS from user → Cloudflare → your app), eliminating the protocol mismatch that's causing the login failure.
Option 2: Configure Rails to Trust Cloudflare's Forwarded Headers
If you can't switch to Full SSL right now, you need to make Rails recognize the original HTTPS request via Cloudflare's X-Forwarded-Proto header.
Update your production environment config (
config/environments/production.rb):# Tell Rails to use Cloudflare's forwarded header to identify the original request protocol config.action_dispatch.default_headers.merge!('X-Forwarded-Proto' => 'https') # Trust Cloudflare as a valid reverse proxy (Rails 5.2+; for better security, use Cloudflare's official IP ranges instead of 0.0.0.0/0) config.action_dispatch.trusted_proxies = IPAddr.new('0.0.0.0/0')Note: For tighter security, replace
0.0.0.0/0with Cloudflare's published IP ranges to only trust requests coming directly from Cloudflare.Enable
force_sslin production to ensure Rails uses HTTPS for all routes and marks authentication cookies as secure:config.force_ssl = trueDouble-check your CSRF protection is properly configured in
ApplicationController:class ApplicationController < ActionController::Base protect_from_forgery with: :exception end
After making these changes, redeploy your Rails app to Elastic Beanstalk. This will make Rails aware of the HTTPS request, fix CSRF validation, and ensure authentication cookies are handled correctly.
内容的提问来源于stack exchange,提问作者Gold Masta

