【问题标题】:Cloudflare SSL Does Not Work With Elixir/Phoenix BackendCloudflare SSL 不适用于 Elixir/Phoenix 后端
【发布时间】:2019-07-05 04:51:04
【问题描述】:

我正在使用 Cloudflare 的灵活 SSL 来保护我的网站,它在运行我的 vue.js 前端时运行良好。本质上,它所做的是与 50 个随机客户共享 SSL 证书,并且通过他们的边缘网络管道我的 DNS 来做到这一点。基本上,它完成了我需要的事情并且很好,但现在我试图将它绑定到 phoenix/elixir 后端,它正在崩溃。

问题是你不能从 ssl 页面内发出 http 请求,因为你会得到这个错误:

Blocked loading mixed active content

这是有道理的 - 如果加载时使用 ssl,则需要一直使用 ssl。所以现在我需要给 Elixir 添加 SSL。

这个网站 (https://elixirforum.com/t/run-phoenix-https-behind-cloudflare-without-key-keyfile/12660/2) 似乎有解决方案!他们的回答是:

configs = Keyword.put(config, :http, [:inet6, port: "80"])
 |> Keyword.put(:url, [scheme: "https", host: hostname, port: "443"])

所以我做了这样的配置:

config :albatross, AlbatrossWeb.Endpoint,
  http: [:inet6, port: "4000"],
  url: [scheme: "https", host: "my.website", port: "443"],
  secret_key_base: "SUPERSECRET",
  render_errors: [view: AlbatrossWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: Albatross.PubSub,
           adapter: Phoenix.PubSub.PG2]

这只允许我访问 http:etc!所以我也试过这个:

config :albatross, AlbatrossWeb.Endpoint,
  http: [:inet6, port: "4000"],
  https: [ :inet6, port: "4443"],
  url: [scheme: "https", host: "my.website", port: "443"],
  secret_key_base: "SUPERSECRET",
  render_errors: [view: AlbatrossWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: Albatross.PubSub,
           adapter: Phoenix.PubSub.PG2]

这当然行不通,因为没有 PEM 文件。因为我只使用 elixir 作为 API(而不是 DNS),所以我不能使用这样的解决方案(http://51percent.tech/blog/uncategorized/serving-phoenix-apps-ssl-and-lets-encrypt/),因为letsencrypt 不允许仅对 IP 地址进行身份验证(https://www.digitalocean.com/community/questions/ssl-for-ip-address)。

所以在这一点上我很困惑。有人有建议吗?


编辑:


有人提到你可以转到 crypto>Origin Certificates>Create Certificate 继续使用 cloudflare 并生成 TLS 证书。我这样做了,下载了文件,将它们保存在我的项目中并运行:

config :albatross, AlbatrossWeb.Endpoint,
  http: [:inet6, port: "4000"],
  https: [ port: "4443", 
           keyfile: "priv/ssl/cloudflare/private.key", 
           certfile: "priv/ssl/cloudflare/public.pem"],
  url: [scheme: "https", host: "website.me", port: "443"],
  secret_key_base: "SUPERSECRET",
  render_errors: [view: AlbatrossWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: Albatross.PubSub,
           adapter: Phoenix.PubSub.PG2]

那么查询后端的所有可能方式的结果是什么?

我正在运行 docker-compose,所以 https://backendservice:4443 是我从前端查询的内容。这给了我 -

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://backendservice:4443/getComments?postnum=6. (Reason: CORS request did not succeed).[Learn More]
value of error :  Error: "Network Error"
    exports https://mywebsi.te/js/chunk-vendors.4345f11a.js:49:15423
    onerror https://mywebsi.te/js/chunk-vendors.4345f11a.js:65:538540
actions.js:61:12 

所以这显然行不通。

可以http://my.ip.address:4000,但我不能https://my.ip.address:4443

据我所知,cloudflare TLS 证书不起作用。

或者,更有可能的是,我在编写 elixir 配置时做了一些愚蠢的事情。


进一步澄清:


是的,上面有一个 CORS 标头错误。 然而请注意,它为 https 请求而不是 http 请求触发。为什么会发生这种情况非常令人困惑。我的应用程序入口点中有一个用于 elixir 的 cors 插件,该插件当前允许 * 传入请求。就是这样 - 它应该非常简单:

plug CORSPlug, origin: "*"

可以在此处找到更多信息 (https://github.com/mschae/cors_plug)。

【问题讨论】:

  • 我可能是错的,但在这样的设置中,cloudflare 不会终止 SSL 并仅向您发送 HTTP 请求吗?这意味着您无需在 Phoenix 中设置任何内容。您可能只需要确保您的前端发送的是 HTTPS 请求而不是 HTTP 请求?
  • 不,这不正确。如果我没有做任何特别的事情,我的后端将解析为MY.IP.ADDRESS/route。如果我 https 请求那里什么都没有,如果我 http 请求我得到 Blocked loading mixed active content 错误。

标签: ssl networking elixir phoenix-framework cloudflare


【解决方案1】:

我似乎已经能够使我的网站使用以下配置:

config :my_app, MyAppWeb.Endpoint,
  force_ssl: [hsts: true],
  url: [host: "my.website", port: 443],
  http: [:inet6, port: 4000],
  https: [
    :inet6,
    port: 8443,
    cipher_suite: :strong,
    keyfile: "private.key.pem",
    certfile: "public.cert.pem",
    cacertfile: "intermediate.cert.pem"
  ],
  cache_static_manifest: "priv/static/cache_manifest.json"

其中private.key.pempublic.cert.pem 是从 Cloudflare 下载的原始证书。

(请注意,您可以从 Cloudflare 下载的原始证书仅对加密您的网站和 Cloudflare 之间的连接有用。)

我还必须通过iptables 添加路由规则。

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 4000
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443

此配置之前也适用于使用 letsencrypt 证书的设置。

我不确定是否需要 cacertfile: "intermediate.cert.pem" 部分。我是从Cloudflare documentation的“第4步”获得的。

【讨论】:

    【解决方案2】:

    我从未使用过 Cloudflare,但我知道如果在请求标头中设置了 x-forwarded-proto,phoenix 可以假装它正在提供 https 内容。你的配置没问题(没有 https 部分,你不需要它)。

    尝试在端点配置中添加force_ssl 选项。这将指示 Plug.SSL 强制 SSL 并将任何 http 请求重定向到 https。

    config :albatross, AlbatrossWeb.Endpoint,
       http: [:inet6, port: "4000"],
       url: [scheme: "https", host: "my.website", port: "443"],
       force_ssl: [rewrite_on: [:x_forwarded_proto], host: nil],
       secret_key_base: "SUPERSECRET",
       render_errors: [view: AlbatrossWeb.ErrorView, accepts: ~w(html json)],
       pubsub: [name: Albatross.PubSub,
               adapter: Phoenix.PubSub.PG2]
    

    【讨论】:

      【解决方案3】:

      根据我使用 Cloudflare 和 Web 后端的经验(并且没有看到导致问题的 确切 请求),这通常是由使用 http:// 或通过使用硬编码的http:// 发出 AJAX 请求。如果您使用http:// 请求的后端没有自动重定向到https://,您将收到您所看到的错误。

      如果您使用 Cloudflare 的“一键式 SSL”,这就是向您的服务器发出请求的方式:

      [ Client Browser ] <-- HTTPS --> [ Cloudflare ] <-- HTTP --> [ Your Server ]
      

      由于 Cloudflare 和您的服务器之间的通信已经结束http://,您根本不需要更改任何 Phoenix 配置,但是有 2 个潜在的错误来源:

      1. Cloudflare 未自动重定向到 https://(或 Cloudflare 未提供您的内容)
      2. 您有一些硬编码到 http:// 的 CSS/JS 依赖项或 Ajax 请求,响应请求的服务器不会自动重定向到 https://

      故障排除点 1:根据Cloudflare's docs for their "One-Click SSL",他们应该自动将http:// 请求重定向到https://(尽管这可能是您需要更改的设置)。如果请求通过 http:// 到达您的域,Cloudflare 应自动重定向到 https://。您可以通过在浏览器中从后端请求一个页面来检查是否发生这种情况,并在 URL 的前面包含http:// 明确。如果您没有被重定向到 https://,这可能意味着 a) Cloudflare 实际上不在您的浏览器和后端之间,或者 b) Cloudflare 没有自动重定向到 https://。无论哪种情况,您都会对解决问题的下一步有一些提示。

      疑难解答点 2: 您可以通过使用浏览器的开发人员工具中的“网络”选项卡来检查这一点,或者通过手动浏览您的网站代码来查找 CSS/JS 依赖项或 Ajax 请求用http:// 硬编码。在开发人员工具中,您可以准确检查导致问题的请求(该行应该是红色的并且有关于混合内容的错误)。从那里您可以检查此请求在您的代码中来自何处。在您的代码中搜索硬编码的 http:// 请求时,大多数情况下您可以直接将其替换为 https://,但您应该仔细检查浏览器中的 URL 以确保该 URL 实际上可用https://。如果 CSS/JS 依赖项或 Ajax 端点实际上在 https:// 上不可用,那么您将需要删除/替换它。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2019-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多