如何让Rails使用SSL连接到PostgreSQL?

pup*_*eno 18 postgresql ruby-on-rails-3 ubuntu-12.04

当我尝试使用Rails 3.2项目连接到远程PostgreSQL数据库时,我收到此错误:

FATAL:  no pg_hba.conf entry for host "10.0.0.3", user "projectx", database "projectx", SSL off
Run Code Online (Sandbox Code Playgroud)

我在Rails上的配置如下所示:

staging:
  adapter: postgresql
  database: projectx
  username: projectx
  password: 123456
  host: 10.0.0.3
  encoding: utf8
  template: template0
  min_messages: warning
Run Code Online (Sandbox Code Playgroud)

在PostgreSQL上看起来像这样:

hostssl    all             all             0.0.0.0/0            md5
hostssl    all             all             ::/0                 md5
Run Code Online (Sandbox Code Playgroud)

这两台机器都在Ubuntu 12.04上运行.

我发现帖子说它应该自动运行,这显然不会发生.我发现有人说libpq没有启用SSL并启用它解决了问题,但没有解释如何启用它.我可以看到,当我查看libpq的依赖关系时,它依赖于某些SSL包,所以我假设编译了SSL支持.

有些帖子建议添加:

sslmode: require
Run Code Online (Sandbox Code Playgroud)

或这个:

sslmode: enabled
Run Code Online (Sandbox Code Playgroud)

启用ssl模式,但它对我没有影响.我读到它被默默地忽略了.

我也尝试了数据库字符串方法,结果是:

staging:
  adapter: postgresql
  database: "host=10.0.0.3 dbname=projectx user=projectx password=123456 sslmode=require"
Run Code Online (Sandbox Code Playgroud)

然后我收到了错误:

could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Run Code Online (Sandbox Code Playgroud)

这似乎表明Rails试图连接到localhost,或者更确切地说,本地PostgreSQL(没有)而不是10.0.0.3.

有任何想法吗?

Dan*_*ité 14

正如您所写的那样,通常会设置Ubuntu 12.x软件包,以便激活SSL,开箱即用,此外是第一个尝试的方法rails,或者任何允许libpq处理这些内容的客户端,这意味着几乎所有客户端.

这种自动启用不一定适用于其他PostgreSQL包或自编译服务器,因此适用于这些其他上下文的答案或建议对您没有帮助.

由于您的设置应该直接工作,这个答案是一个要检查的事项列表,以找出问题所在.优选地,psql首先使用测试连接设置而不是rails,以便可以首先排除一般的postgresql问题.

客户端

客户端sslmode参数控制连接尝试的顺序.

为了自愿避免使用SSL,客户端需要将sslmode=disable某个地方放在连接字符串中,或​​者PGSSLMODE=disable放在环境中,或者与其他PGSSL*变量混淆.在不太可能的情况下,您的rails进程在其环境中具有此功能,这将解释您获得的错误,因为它pg_hba.conf不允许非SSL连接.

不尝试SSL的另一个原因显然libpq是在没有使用SSL支持进行编译时,但Ubuntu软件包的情况并非如此.

默认sslmode值为prefer,描述为:

喜欢(默认)

first try an SSL connection; if that fails, try a non-SSL connection
Run Code Online (Sandbox Code Playgroud)

SSL=off你的错误消息的末尾涉及失败的最后一个连接尝试.可能是SSL尝试失败,或者根本没有尝试过,我们无法单独从这个消息中知道.SSL=off服务器通常根据pg_hba.conf(hostssl在第一列中)设置的策略拒绝连接尝试.

这个问题在服务器方面更合理,因为有更多的东西可以出错.

服务器端

以下是检查服务器端的各种事项:

  • 应该有ssl=onpostgresql.conf(默认位置:/etc/postgresql/9.1/main/)

  • 当连接到localhost时psql,你应该收到这样的消息:

psql(9.1.13)
SSL连接(密码:DHE-RSA-AES256-SHA,位:256)输入
"help"以获取帮助.

  • ca-certificates软件包应该安装并且是最新的.

  • ssl-cert软件包应该安装并且是最新的.

  • 在postgres数据目录中(/var/lib/postgresql/9.1/main默认情况下),应该有软链接:
    server.crt -> /etc/ssl/certs/ssl-cert-snakeoil.pem或其他有效证书,
    server.key -> /etc/ssl/private/ssl-cert-snakeoil.key或其他有效密钥.

  • /etc/ssl/certs 和父目录应该是可读的,并且可以由postgres执行.

  • postgresUNIX用户应该是在ssl-certUNIX组(检查id -a postgres),否则就不能读取私钥.

  • 如果更改postgresql.conf,请确保在执行任何其他测试之前重新启动postgresql.

  • /var/log/postgresql/postgresql-9.1-main.log在启动时或连接尝试失败时,不应该有任何关于SSL的可疑消息.


ahm*_*eij 9

Rails使用PG gem来连接postgres,请参阅此处的实现:

https://github.com/rails/rails/blob/02a3c0e771b3e09173412f93d8699d4825a366d6/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L881

PG gem使用libpg(c库)和"PG :: Connection.new"文档:http: //deveiate.org/code/pg/PGconn.html

建议以下选项:

host
server hostname

hostaddr
server address (avoids hostname lookup, overrides host)

port
server port number

dbname
connecting database name

user
login user name

password
login password

connect_timeout
maximum time to wait for connection to succeed

options
backend options

tty
(ignored in newer versions of PostgreSQL)

sslmode
(disable|allow|prefer|require)

krbsrvname
kerberos service name

gsslib
GSS library to use for GSSAPI authentication

service
service name to use for additional parameters
Run Code Online (Sandbox Code Playgroud)

所以这表明连接字符串不起作用(因为它不能被适配器识别,这可能是一个mysql适配器选项)

此外,这表明该sslmode=required选项应该有效,因为这是libpg的基本功能.

所以:

database.yml的

staging:
  ...
  sslmode: "require"
  ...
Run Code Online (Sandbox Code Playgroud)

绝对应该这样做,你确定你使用分期模式吗?//也可以将sslmode添加到其他环境中.

此外,libpg默认使用SSL作为第一次尝试,也许您看到SSL关闭的错误,因为SSL模式首先失败,然后libpq重试没有ssl并最终引发错误.