AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 108710
Accepted
csd
csd
Asked: 2015-08-01 11:24:11 +0800 CST2015-08-01 11:24:11 +0800 CST 2015-08-01 11:24:11 +0800 CST

如何检查 PostgreSQL 服务器的 SSL 证书?

  • 772

假设有一个 PostgreSQL 服务器正在运行并且它启用了 SSL。使用“标准”Linux 和 PostgreSQL 工具,我如何检查其 SSL 证书?

我希望输出类似于您从运行中获得的输出openssl x509 -text ...。我希望有一个或两个命令行的答案,所以我不必求助于运行数据包嗅探器。

我无权访问 PostgreSQL 服务器,因此无法直接查看其配置文件。

我没有超级用户登录,所以我无法获取设置的值,ssl_cert_file然后pg_read_file就可以了。

使用openssl s_client -connect ...不起作用,因为 PostgreSQL 似乎不想立即进行 SSL 握手。

通过快速查看psql文档,我找不到使其在启动时显示该信息的命令行参数。(尽管它确实向我显示了某些密码信息。)

postgresql postgresql-9.4
  • 5 5 个回答
  • 16647 Views

5 个回答

  • Voted
  1. Best Answer
    Adam Batkin
    2019-07-18T17:41:59+08:002019-07-18T17:41:59+08:00

    看起来 OpenSSL 的s_client工具-starttls在 1.1.1 中添加了 Postgres 支持,因此您现在可以使用 OpenSSL 命令行工具的全部功能而无需额外的帮助脚本:

    openssl s_client -starttls postgres -connect my.postgres.host:5432 # etc...
    

    参考:

    • Git 提交
    • s_client 手册页
    • 18
  2. csd
    2015-08-04T12:10:19+08:002015-08-04T12:10:19+08:00

    按照克雷格·林格评论中的想法:

    一种选择是openssl s_client使用 PostgreSQL 协议修补握手。您也可以通过将自定义 SSLSocketFactory 传递给 PgJDBC 来使用 Java 来实现。我不确定是否有任何简单的选项。

    ...我写了一个简单的 SSL 套接字工厂。我复制了 PgJDBC 自己的NonValidatingFactory类的代码,只是添加了代码来打印证书。

    这是它的样子,当一切都说完了:

    import java.security.GeneralSecurityException;
    import java.security.cert.X509Certificate;
    import java.sql.Connection;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.postgresql.ds.PGSimpleDataSource;
    import org.postgresql.ssl.WrappedFactory;
    
    public class ShowPostgreSQLCert {
        public static void main(String[] args) throws Throwable {
            PGSimpleDataSource ds = new PGSimpleDataSource();
            ds.setServerName( ... );
            ds.setSsl(true);
            ds.setUser( ... );
            ds.setDatabaseName( ... );
            ds.setPassword( ... );
            ds.setSslfactory(DumperFactory.class.getName());
            try (Connection c = ds.getConnection()) { }
        }
    
        public static class DumperFactory extends WrappedFactory {
            public DumperFactory(String arg) throws GeneralSecurityException {
                SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(null, new TrustManager[] { new DumperTM() }, null);
                _factory = ctx.getSocketFactory();
            }
        }
    
        public static class DumperTM implements X509TrustManager {
            public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                for (int i=0; i<certs.length; ++i) {
                    System.out.println("Cert " + (i+1) + ":");
                    System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                    System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
                }
            }
        }
    }
    
    • 11
  3. mivk
    2016-11-13T09:46:42+08:002016-11-13T09:46:42+08:00

    如果你不想安装 java 和编译,并且你已经有了 python,你可以试试这个 python 脚本:https ://github.com/thusoy/postgres-mitm/blob/master/postgres_get_server_cert.py

    我用它来检查证书日期:

    postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -dates
    

    或将完整证书作为文本:

    postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -text
    
    • 11
  4. vidarsk
    2016-04-27T01:49:27+08:002016-04-27T01:49:27+08:00

    csd的回答真的救了我。对于我们这些不了解或忘记 java 的人来说,这里有一个更详细的演练。

    1. 确保你的服务器可以编译java。尝试命令“which javac”,如果它输出类似“... no javac in ...”,那么您需要安装 JDK(JRE 不起作用,它有“java”但没有“javac”)。

    2. 如果您还没有 postgresql-jdbc,请安装它。对于 RHEL6,命令是“yum install postgresql-jdbc”。找出 jar 文件的安装位置。会有几个,每个版本一个。我使用了“/usr/share/java/postgresql-jdbc3.jar”。

    3. 复制 csd 的代码并插入数据库信息(另一个答案),或者在这个答案的末尾使用我稍微修改过的版本。将其保存在一个名为“ShowPostgreSQLCert.java”的文件中。大写/小写很重要,将其称为其他任何内容,它都不会编译。

    4. 在包含 ShowPostgreSQLCert.java 文件的目录中,运行以下命令(根据需要修改 postgresql-jdbc3.jar 的位置):“javac -cp /usr/share/java/postgresql-jdbc3.jar ShowPostgreSQLCert.java”。您现在应该在同一目录中有 3 个 .class 文件。

    5. 最后,运行以下命令:“java -cp .:/usr/share/java/postgresql-jdbc3.jar ShowPostgreSQLCert”。这 ”。” 在“-cp”之后意味着它应该在当前目录中查找 .class 文件。您可以在此处插入类文件的完整路径,只需记住在路径和 .jar 文件的位置之间保留“:”。

    6. 如果您需要在不同的机器上运行命令,您需要安装相同的 jar 文件(postgresql-jdbc3.jar),或者您可以从编译 .class 文件的服务器上复制它。然后只需复制 .class 文件并在修改路径后运行 5. 中的命令。

    我稍微修改了代码,以便您可以在命令行上传递数据库信息,而不是将其编译到 .class 文件中。只需不带任何参数运行它,它就会显示一条消息,显示它期望的参数。csd的代码+修改为:

    import java.security.GeneralSecurityException;
    import java.security.cert.X509Certificate;
    import java.sql.Connection;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.postgresql.ds.PGSimpleDataSource;
    import org.postgresql.ssl.WrappedFactory;
    
    public class ShowPostgreSQLCert {
        public static void main(String[] args) throws Throwable {
            PGSimpleDataSource ds = new PGSimpleDataSource();
            if( args.length != 4 ) {
                System.out.println("Not enough arguments. Usage: ShowPostgreSQLCert ServerName User DatabaseName Password");
                System.exit(1);
            }
            ds.setServerName( args[0] );
            ds.setSsl(true);
            ds.setUser( args[1] );
            ds.setDatabaseName( args[2] );
            ds.setPassword( args[3] );
            ds.setSslfactory(DumperFactory.class.getName());
            try (Connection c = ds.getConnection()) { }
        }
    
        public static class DumperFactory extends WrappedFactory {
            public DumperFactory(String arg) throws GeneralSecurityException {
                SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(null, new TrustManager[] { new DumperTM() }, null);
                _factory = ctx.getSocketFactory();
            }
        }
    
        public static class DumperTM implements X509TrustManager {
            public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                for (int i=0; i<certs.length; ++i) {
                    System.out.println("Cert " + (i+1) + ":");
                    System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                    System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
                }
            }
        }
    }
    
    • 3
  5. Cameron Kerr
    2016-10-21T17:33:37+08:002016-10-21T17:33:37+08:00

    我从https://stackoverflow.com/questions/3313020/write-x509-certificate-into-pem-formatted-string-in-java添加了一些代码以将证书输出为 PEM,并消除了指定数据库的需要,用户名或密码(获取证书不需要它们)。

    使用它,我能够验证是否需要重新启动 PostgreSQL 才能切换到新证书。

    不是Java开发人员,我构建和运行的步骤可能不是那么好,但它们可以工作,只要你能找到一个postgresql jdbc

    # locate postgresql | grep jar
    /path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar   <-- this one will do
    ...
    

    编译:

    javac -cp /path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar ./ShowPostgreSQLCert.java
    

    跑步:

    java -cp /path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar:. ShowPostgreSQLCert 127.0.0.1
    

    样本输出:

    Cert 1:
        Subject: CN=...
        Issuer: CN=...
        Not Before: Fri Oct 21 11:14:06 NZDT 2016
        Not After: Sun Oct 21 11:24:00 NZDT 2018
    -----BEGIN CERTIFICATE-----
    MIIHEjCCBfqgAwIBAgIUUbiRZjruNAEo2j1QPqBh6GzcNrwwDQYJKoZIhvcNAQEL
    ...
    IcIXcVQxPzVrpIDT5G6jArVt+ERLEWs2V09iMwY7//CQb0ivpVg=
    -----END CERTIFICATE-----
    
    Cert 2:
    ...
    

    资源:

    import java.security.GeneralSecurityException;
    import java.security.cert.X509Certificate;
    import java.sql.Connection;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.postgresql.ds.PGSimpleDataSource;
    import org.postgresql.ssl.WrappedFactory;
    
    import javax.xml.bind.DatatypeConverter;
    import java.security.cert.X509Certificate;
    import java.io.StringWriter;
    
    public class ShowPostgreSQLCert {
        public static void main(String[] args) throws Throwable {
            PGSimpleDataSource ds = new PGSimpleDataSource();
            if( args.length != 1 ) {
                System.out.println("Not enough arguments.");
                System.out.println("Usage: ShowPostgreSQLCert ServerName");
                System.exit(1);
            }
            ds.setServerName( args[0] );
            ds.setSsl(true);
            ds.setUser( "" );
            ds.setDatabaseName( "" );
            ds.setPassword( "" );
            ds.setSslfactory(DumperFactory.class.getName());
            try (Connection c = ds.getConnection()) { }
            catch (org.postgresql.util.PSQLException e) {
                // Don't actually want to login
            }
        }
    
        public static class DumperFactory extends WrappedFactory {
            public DumperFactory(String arg) throws GeneralSecurityException {
                SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(null, new TrustManager[] { new DumperTM() }, null);
                _factory = ctx.getSocketFactory();
            }
        }
    
        public static String certToString(X509Certificate cert) {
            StringWriter sw = new StringWriter();
            try {
                sw.write("-----BEGIN CERTIFICATE-----\n");
                sw.write(DatatypeConverter.printBase64Binary(cert.getEncoded()).replaceAll("(.{64})", "$1\n"));
                sw.write("\n-----END CERTIFICATE-----\n");
            } catch (java.security.cert.CertificateEncodingException e) {
                e.printStackTrace();
            }
            return sw.toString();
        }
    
        public static class DumperTM implements X509TrustManager {
            public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                for (int i=0; i<certs.length; ++i) {
    
                    System.out.println("Cert " + (i+1) + ":");
                    System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                    System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
                    System.out.println("    Not Before: " + certs[i].getNotBefore().toString());
                    System.out.println("    Not After: " + certs[i].getNotAfter().toString());
    
                    System.out.println(certToString(certs[i]));
                }
            }
        }
    }
    
    • 1

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve