簡體   English   中英

Postgres - python多個SSL連接

[英]Postgres - python multiple SSL connections

我有麻煩使用psycopg2和SSL建立兩個並發的Postgres數據庫連接(一個到主,一個到從)。 另外,兩個連接工作即:

import psycopg2
dsnMaster='dbname=... sslcert=path/to/master/cert'
psycopg2.connect(dsnMaster, connection_factory=None, async=False)

工作,等等

import psycopg2
dsnSlave='dbname=... sslcert=path/to/slave/cert'
psycopg2.connect(dsnSlave, connection_factory=None, async=False

但加入兩者

import psycopg2
dsnMaster='dbname=... sslcert=path/to/master/cert'
psycopg2.connect(dsnMaster, connection_factory=None, async=False)
dsnSlave='dbname=... sslcert=path/to/slave/cert'
psycopg2.connect(dsnSlave, connection_factory=None, async=False)

對於第二個連接始終失敗,出現SSL error: block type is not 01 似乎psycopg使用以前連接的證書。

我已經嘗試過.close()第一個連接(如圖所示,但沒有動態使用psycopg2在python中使用 ssl 更改數據庫(postgresql) ),還嘗試了各種psycopg.extensions isolation_level選項,但沒有成功。

提前致謝!

我相信我已將問題追溯到libq ... PostgreSQL C庫。

我也注意到我不能為2個不同的連接使用不同的ssl客戶端證書。 第一個連接始終成功,而第二個連接始終因SSL error: certificate verify failed而失敗SSL error: certificate verify failed

在服務器日志中,我could not accept SSL connection: tlsv1 alert unknown ca

這告訴我第二個連接可能嘗試使用第一個連接中的ssl證書,而不是使用它被告知使用的ssl證書。

考慮這段代碼

import psycopg2
conn1 = psycopg2.connect('host=server1... sslcert=path/to/cert1')
conn2 = psycopg2.connect('host=server2... sslcert=path/to/cert2')

連接2似乎使用cert1而不是cert2

我認為psycopg2存在問題...也許它正在緩存客戶端ssl證書....

我繼續構建了一個psycopg2的調試版本並安裝它..我再次嘗試了我的代碼並獲得了大量的調試信息。 這是我得到的調試信息。 (我只發布相關信息)

[98940] psyco_connect: dsn = 'dbname=testdb user=testdb host=server1 sslrootcert=root1.crt sslkey=cert1.key sslcert=cert1.crt sslmode=verify-full', async = 0
[98940] connection_setup: init connection object at 0x103093048, async 0, refcnt = 1
[98940] con_connect: connecting in SYNC mode
[98940] conn_connect: new postgresql connection at 0x10047ff90
[98940] conn_connect: server standard_conforming_strings parameter: on
[98940] conn_connect: server requires E'' quotes: NO
[98940] conn_connect: using protocol 3
[98940] conn_connect: client encoding: UTF8
[98940] clear_encoding_name: UTF8 -> UTF8
[98940] conn_connect: DateStyle ISO, MDY
[98940] connection_setup: good connection object at 0x103093048, refcnt = 1
# ... Got a good 1st connection here
# ... (Tons more lines of output before the 2nd connection)
[98940] psyco_connect: dsn = 'dbname=testdb user=testdb host=server2 sslrootcert=root2.crt sslkey=cert2.key sslcert=cert2.crt sslmode=verify-full', async = 0
[98940] connection_setup: init connection object at 0x103093170, async 0, refcnt = 1
[98940] con_connect: connecting in SYNC mode
[98940] conn_connect: new postgresql connection at 0x100682d30
[98940] conn_connect: PQconnectdb(dbname=testdb user=testdb host=server2 sslrootcert=root2.crt sslkey=cert2.key sslcert=cert2.crt sslmode=verify-full) returned BAD
[98940] connection_init: FAILED
[98940] conn_close: PQfinish called
[98940] connection_dealloc: deleted connection object at 0x103093170, refcnt = 0

如果我切換2個連接,則結果相同......第一個連接成功,但第二個連接失敗。 因此,第二個連接的dsn是正確的,因為如果先執行連接,連接會成功。

檢查psycopg2的來源,它只是從libq C庫調用PQconnectdb ...並且它使用正確的參數調用它。 您可以在http://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-PQCONNECTDB上查看PQconnectdb上的文檔

這告訴我psycopg2正確地使用正確的參數調用PQconnectdb ,而PQconnectdb只是沒有在第二個連接上使用正確的證書。

更重要的是,我也對其他程序進行了一些測試。 我測試了Navicat for PostgreSQL(Mac版) - 同樣的問題。 第一次連接成功,第二次連接無法驗證證書。 當我重新啟動Navicat時,它再次發生...無論我嘗試什么順序,第一次連接成功,第二次連接失敗。

PgAdmin也是如此(最新版本目前為1.20)。 第一次連接成功,第二次連接失敗。

我懷疑只要使用libq進行連接,任何連接到PostgreSQL的軟件或模塊都會遇到同樣的問題。 事實上,我甚至測試過PHP,並得到了相同的結果

root@test:~# php -a
Interactive mode enabled

php > // Test with server 1 first
php > $conn = pg_connect('host=server1 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt');
php > $conn2 = pg_connect('host=server2 user=testdb dbname=testdb sslcert=cert2.crt sslmode=verify-full sslkey=cert2.key sslrootcert=root2.crt');
PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: SSL error: certificate verify failed in php shell code on line 1
php > quit
root@test:~# php -a
Interactive mode enabled

php > // Test with server 2 first
php > $conn2 = pg_connect('host=server2 user=testdb dbname=testdb sslcert=cert2.crt sslmode=verify-full sslkey=cert2.key sslrootcert=root2.crt');
php > $conn = pg_connect('host=server1 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt');
PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: SSL error: certificate verify failed in php shell code on line 1
php > quit
root@test:~# php -a
Interactive mode enabled

php > // Test using the same certificate
php > $conn = pg_connect('host=server1 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt');
php > $conn2 = pg_connect('host=server2 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt');
php > // No problems. Both connect just fine now

我的建議是提交PostgreSQL的錯誤報告。 不確定這是否是提交此類錯誤報告的正確位置http://www.postgresql.org/support/submitbug/

在此之前,我能夠提出一個適合我的解決方案......現在的解決方案是簡單地為兩個服務器使用相同的證書。 如果您可以這樣做,它適用於兩個連接,您可以有2個單獨的連接到2個單獨的服務器...(只要兩個連接都可以使用相同的客戶端證書連接)

對我來說,我只是為兩台服務器使用相同的服務器ssl證書,私鑰和根證書...我只是使用通配符作為通用名稱並自己簽署證書(但如果你願意,你可以使用商業通配符證書然后,我生成了一個客戶端證書,並將該單個證書用於這兩個連接。

這可能不是您正在尋找的答案,但這似乎是使用客戶端證書身份驗證通過SSL與2個不同服務器建立2個連接的唯一方法。 無論您使用何種編程語言或軟件,都是如此。

所以,你的代碼現在變成了:

import psycopg2
dsnMaster='dbname=... sslcert=path/to/master/cert'
psycopg2.connect(dsnMaster, connection_factory=None, async=False)

# Here, the dsnSlave simply uses the same cert as the master
# Other connection details like the host and dbname can be different
dsnSlave='dbname=... sslcert=path/to/master/cert'
psycopg2.connect(dsnSlave, connection_factory=None, async=False)

這是我在python中的實際代碼

root@test:~# python3
Python 3.4.0 (default, Jun 19 2015, 14:20:21) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg2
>>> dsn1 = 'host=server1 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt'
>>> conn1 = psycopg2.connect(dsn1)
>>> dsn2 = 'host=server2 user=testdb dbname=testdb sslcert=cert1.crt sslmode=verify-full sslkey=cert1.key sslrootcert=root1.crt'
>>> conn2 = psycopg2.connect(dsn2)
>>> # YAY, no issues and both connections work

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM