©
This document uses PHP Chinese website manual Release
PostgreSQL本机支持使用SSL连接对客户端/服务器通讯进行加密, 以增强安全性。参阅Section 17.8获取有关服务器端SSL功能的细节。
libpq读取全系统 OpenSSL配置文件,默认情况下,文件命名 为openssl.cnf并且存放在openssl version -d 目录报告中,此默认可以通过设置环境变量OPENSSL_CONF覆盖配置名称文件名称。
缺省,PostgreSQL不会执行任何服务器证书验证。 这就意味着可以在客户端没有察觉的情况下骗过服务认证(如,通过修改一个DNS记录或接管服务IP)。 为了避免这种情况,必须使用SSL证书认证。
如果sslmode参数设置为verify-ca,libpq将通过检查受信任的证书颁发机构的证书链(CA)来通过 服务是可信任的。如果sslmode设置为verify-full,libpq会通过验证服务主机名匹配认证来认为服务是可信任的。 如果服务验证不能被通过,那么SSL连接会失败。在大多数对安全要求较高的环境中,建议使用verify-full。
在verify-full模式下,认证的cn(Common Name)属性与主机名进行匹配。 如果cn以*开始,会被看做是一个通配符,并且会匹配除了.之外的所有字符。 这就意味着认证不会匹配子域名。如果是使用IP而不是主机名进行连接,会进行IP匹配检查(不会做DNS检查)。
为了允许服务器认证通过,一个或多个信任的CA认证必须放在用户的home目录下的~/.postgresql/root.crt文件中。 Windows下的文件名是%APPDATA%\postgresql\root.crt。
如果存在~/.postgresql/root.crl文件(Windows下是%APPDATA%\postgresql\root.crl文件),同样也会检查CRL。
root认证文件和CRL的位置可以通过设置sslrootcert和sslcrl连接参数,或PGSSLROOTCERT和PGSSLCRL环境变量进行修改。
如果服务器要求一个信任的客户端认证,libpq将发送存储在~/.postgresql/postgresql.crt文件中的 证书。该认证必须通过一个或多个服务器信任的CA认证。 同时也必须出示一个匹配的私钥文件~/.postgresql/postgresql.key。 私钥文件不允许任何对世界或组的访问;通过chmod 0600 ~/.postgresql/postgresql.key命令可以实现。 在Windows上,这个文件是%APPDATA%\postgresql\postgresql.crt和%APPDATA%\postgresql\postgresql.key, 同时没有特定的权限检查,因为目录被认为是安全的。证书和key文件的位置可以通过sslcert和sslkey连接参数, 或PGSSLCERT和PGSSLKEY环境变量进行覆盖重写。
在一些情况下,客户端认证可能会被一个"intermediate"的证书认证来标记, 而不是一个能直接被服务信任的。为了使用一个这种认证,向postgresql.crt文件 追加标记认证权,并且直到"root"都可以被服务器信任。root认证应该被包含在任何一种情况(postgresql.crt包含一个或多个认证)下。
需要注意的是,root.crt列出了最高级别的CA,被认为对标记服务认证中是可信任的。 原则上,不需要列出标记客户端认证的CA,尽管在大多数情况下,CA仍会被认为对服务器认证是可信任的。
sslmode参数的不同值提供了不同的保护级别。SSL可以提供为三种攻击提供保护:
Table 31-2. SSL的攻击
类型 | 描述 |
---|---|
Eavesdropping(窃听) | 如果一个第三方可以在客户端与服务器端之间检查网络通信, 那么它就能读取两边的连接信息(包括用户名和密码)以及传递的数据。对此, SSL通过加密进行防护。 |
MITM | 如果客户端和服务器端进行传递数据的时候,第三方可以对其进行修改,那么他就能伪装成服务器, 然后查看或修改数据(即使是加密的)。第三方接着可以向原始服务器发出连接信息和数据, 最终造成无法防护这种攻击。这种攻击常用的载体有DNS中毒或IP绑架,即客户端被定向到预期之外的不同的服务器。 同样还有几种其他的方法也能做到这种攻击。SSL通过服务器到客户端的证书验证来阻止这种攻击。 |
模拟 | 如果第三方可以伪装成一个认证了的客户端,那么它就能轻松访问到它本来不能访问的数据。 典型的,如不安全的密钥管理,就会造成这种情况。SSL通过客户端认证来阻止这种情况, 即确保只有知道有效认证的人员才能访问连接服务器。 |
对于一个被称为安全的连接来说,进行连接之前,必须在客户端和服务器端都进行SSL配置。 如果只在服务器端进行配置,在它知道服务器端需要高级认证之前不会发送敏感信息(如密码等)。 在libpq中,可以通过将sslmode参数设置为verify-full或verify-ca来确保安全连接, 并且为系统提供一个root认证以进行安全认证。类似于使用https和URL进行加密网页浏览。
一旦服务器已经认证,客户端就可以发送敏感信息。 这就意味着知道这一刻,客户端都不需要知道,是否认证需要证书,只在服务器配置,对其安全地指定。
所有以加密和密钥交换方式得SSL选项都会产生开销, 因此在性能和安全之间需要进行一个权衡。下表说明不同sslmode为值的安全风险, 以及关于安全和开销所做出的声明:
Table 31-3. SSL模式说明
sslmode | 窃听保护 | MITM保护 | 声明 |
---|---|---|---|
disabled | 否 | 否 | 我不关心安全,我不想来支付加密的开销 |
允许 | 可能 | 否 | 我不关心安全性,但我会支付的加密开销 ,如果服务器的治持的话 |
喜欢 | 或许 | 否 | 我不关心加密,但我想支付加密开销 ,如果服务器支持它。 |
要求 | 是 | 否 | 我想我的数据是加密的,我接受的开销。我相信 该网络将确保我始终连接到服务器,按我想象的。 |
验证CA | 是 | 取决于对CA规定 | 我希望我的数据加密,我接受的开销。我想成为 确保连接到一个服务器,我坚信。 |
全验证 | 是 | 是 | 我希望我的数据加密,我接受开销。我想确定连接到一个服务器我相信,它是我 指定。 |
verify-ca和verify-full之间的不同是根据rootCA的规定。 如果使用的是一个公用CA,verify-ca允许那些带有CA注册的客户端对服务器进行连接访问。 在这种情况下,应该使用verify-full。如果使用的是一个本地CA, 甚至是一个自签名证书,使用verify-ca通常会提供充分的保护。
sslmode缺省值是prefer。如在表中说明的那样,从安全角度来看这样做是没有意义的, 并且如果可能的话,它只承诺性能的开销。它仅提供了缺省向后兼容性,在安全部署中不建议使用。
Table 31-4. libpq/客户端SSL文件的使用
文件 | 内容 | 影响 |
---|---|---|
~/.postgresql/postgresql.crt | 客户端证书 | 服务器要求 |
~/.postgresql/postgresql.key | 客户端的私钥 | 证明由所有者发送的客户端证书,并不表示 证书拥有者是值得信赖 |
~/.postgresql/root.crt | 受信任的证书颁发机构 | 检查服务器证书是由受信任的证书机关签署。 |
~/.postgresql/root.crl | 证书颁发机构吊销证书 | 服务器证书必须不在这个名单 |
如果应用程序初始化libssl和/或libcrypto库以及libpq编译为支持SSL,
应该调用PQinitOpenSSL
来告诉libpq说libssl和/或libcrypto已经被应用程序初始化了,
因此libpq将不会在初始化这些库。
参阅http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html
PQinitOpenSSL
允许应用程序选择安全库初始化。
void PQinitOpenSSL(int do_ssl,int do_crypto);
当do_ssl为非0时,在第一次打开一个数据库连接之前,libpq将初始化OpenSSL库。
当do_crypto为非0时,libcrypto库将被初始化。
缺省(如果PQinitOpenSSL
没有被调用),两个库都会被初始化。
如果没有编译SSL支持,会提供该函数,但不会做任何事情。
如果应用程序使用并初始化OpenSSL,或其底层libcrypto库,那么 在第一次打开一个数据库连接之前,必须调用这个函数(带有适当0值的参数)。 同样要确保在打开一个数据库连接之前做过初始化。
PQinitSSL
允许应用程序选择安全库初始化。
void PQinitSSL(int do_ssl);
此功能相当于PQinitOpenSSL(do_ssl,do_ssl) 它的应用是足够的同时初始化或都不初始化OpenSSL和libcrypto。
从8.0之后的版本就提供了PQinitSSL
函数,然而PQinitOpenSSL
函数是在8.4中才添加的,
因此对老版本的libpq的使用,PQinitSSL
是对应用程序的不错的选择。