如何在Sidekiq上为Redis 6启用TLS



问题

在我的Ruby On Rails应用程序上,我不断收到以下Heroku Redis Premium 0插件的错误:

OpenSSL::SSL::SSLError:SSL_connect返回=1错误号=0状态=错误:证书验证失败(证书链中的自签名证书)

Heroku Redis文档提到,为了连接到Redis 6数据库,我需要在Redis客户端的配置中启用TLS。为了实现这一点,我阅读了redis-rb上的SSL/TLS支持文档。我的理解是;我需要为Redis.new#ssl_params分配ca_filecertkey问题是如何为Redis或通过Heroku上的Sidekiq设置这些?

更新

更新3:Heroku的支持提供了解决问题的答案。

更新2:已创建Heroku支持票证和等待响应。

更新1:被问及Sidekiq的Github问题,并被建议去写Heroku支持。当我得到答案时,我会更新这个问题。


相关信息

我已经验证了当附加组件是以下任何一种时,该应用程序确实有效:

  • Redis 6的业余爱好开发
  • Redis 5的溢价0

版本:

  • Ruby–3.0.0p0
  • Ruby on Rails–6.1.1
  • Redis–6.0
  • redis rb–4.2.5
  • Sidekiq–6.2.1
  • Heroku Stack–20

帮助我缩小问题范围的一些链接:

  • https://bibwild.wordpress.com/2020/11/24/are-you-talking-to-heroku-redis-in-cleartext-or-ssl/
  • https://mislav.net/2013/07/ruby-openssl/

解决方案

OpenSSL::SSL::VERIFY_NONE用于Redis客户端。

Sidekiq

# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
end
Sidekiq.configure_client do |config|
config.redis = { ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
end

Redis

Redis.new(url: 'url', driver: :ruby, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE })

原因

Redis 6需要TLS才能连接。然而,Heroku支持解释说,他们管理从路由器级别到应用程序级别的涉及自签名证书的请求。事实证明,Heroku在路由器级别终止SSL,并通过HTTP将请求从那里转发到应用程序,而一切都在Heroku的防火墙和安全措施之后。


来源

  • https://ogirginc.github.io/en/heroku-redis-ssl-error
  • https://devcenter.heroku.com/articles/securing-heroku-redis#connecting-直接到stunnel

如果使用ActionCable,您可能还需要将verify_mode添加到`cable.yml-config:

production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: my_app_production
ssl_params:
verify_mode: <%= OpenSSL::SSL::VERIFY_NONE %>

来源:https://github.com/chatwoot/chatwoot/issues/2420

如果您使用Rails 5,则无法通过cable.yml文件为ActionCable配置Redis的ssl_params。相反,您可以在初始化器中手动设置redis_connector属性,如下所示:

# frozen_string_literal: true
require "action_cable/subscription_adapter/redis"
ActionCable::SubscriptionAdapter::Redis.redis_connector = ->(_config) do
Redis.new(...your options here...)
end

关于使用OpenSSL::SSL::VERIFY_NONE的含义以及如果你在Heroku:上,为什么它可能是可以的更多上下文

使用OpenSSL::SSL::VERIFY_NONE告诉客户端可以使用自签名证书,不会尝试验证证书是否由已知的证书颁发机构签名。

风险在于中间人有可能发起攻击。如果尝试与Heroku Redis对话的客户端没有验证其遇到的SSL证书是否属于Heroku(AKA,这些证书由已验证请求证书的实体实际上是Heroku的证书颁发机构签名),然后,位于您的客户端和Heroku Redis之间的攻击者可以创建自己的自签名SSL证书并冒充Heroku。这意味着他们可能会拦截你试图发送给Heroku Redis的任何流量。

在实践中,对于一个Heroku dyno与Heroku Redis交谈来说,这可能不是一个现实的场景。

这是Heroku支持的一句话:

MITM攻击在托管主机提供商上是不切实际的。会的一个坏演员很难在dyno和Redis实例之间切换托管在AWS上。这是因为在同一个AZ中的EC2实例在任何时候都不应在AWS基础设施之外进行路由。这在这种情况下,MITM攻击只能由坏人执行自网络流量从未离开所述设施。

以下是AWS文档中的一些片段,似乎证实了这一点:

https://aws.amazon.com/vpc/faqs/

Q。当两个实例通信时,流量会通过互联网吗使用公共IP地址,或者当实例与公共AWS服务端点?

没有。当使用公共地址空间时AWS中托管的实例和服务使用AWS的专用网络。源于AWS网络且目的地位于AWS网络保留在AWS全球网络上,来往流量除外AWS中国地区。

此外,AWS全球网络中流动的所有数据互连我们的数据中心,区域自动加密在它离开我们的安全设施之前在物理层。还存在额外的加密层;例如,所有VPC跨区域对等流量,以及客户或服务对服务传输层安全性(TLS)连接。

和https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-vpc.html

Amazon虚拟私有云(Amazon VPC)使您能够定义AWS中您自己的逻辑隔离区域中的虚拟网络云,称为虚拟私有云(VPC)。

当您创建AWS帐户时,我们会在中为您创建一个默认的VPC每个区域

最新更新