首先,这个问题与语言无关。我正在尝试编写一个简单的应用程序,使用SSL连接到PostgreSQL。
- 我使用脚本创建了证书:
# Create CA private key
openssl genrsa -des3 -out root.key 4096
#Remove a passphrase
openssl rsa -in root.key -out root.key
# Create a root Certificate Authority (CA)
openssl \
req -new -x509 \
-days 365 \
-subj "/CN=localhost" \
-key root.key \
-out root.crt
# Create server key
openssl genrsa -des3 -out server.key 4096
#Remove a passphrase
openssl rsa -in server.key -out server.key
# Create a root certificate signing request
openssl \
req -new \
-key server.key \
-subj "/CN=localhost" \
-text \
-out server.csr
# Create server certificate
openssl \
x509 -req \
-in server.csr \
-text \
-days 365 \
-CA root.crt \
-CAkey root.key \
-CAcreateserial \
-out server.crt
我使用以下命令创建了一个数据库:
init.sql
该文件包含数据库的初始化脚本。CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE TESTING_DATA (
ID SERIAL PRIMARY KEY,
UUID UUID UNIQUE NOT NULL DEFAULT uuid_generate_v4(),
NAME TEXT NOT NULL,
INFO NUMERIC(3, 2)
);
INSERT INTO TESTING_DATA (NAME, INFO)
VALUES
('Notebook', 1),
('Office supplies', 2),
('Pencil', 2),
('Office supplies', 1),
('Eraser', 1),
('Coffee', 1),
('Cookies', 2),
('Puzzles', 5)
;
postgresql.conf
ssl = on
ssl_ca_file = '/etc/postgres/security/root.crt'
ssl_cert_file = '/etc/postgres/security/server.crt'
ssl_key_file = '/etc/postgres/security/server.key'
password_encryption = scram-sha-256
pg_hba.conf
local all all md5
host all all 127.0.0.1/32 md5
hostssl all all 0.0.0.0/0 cert clientcert=1
Dockerfile
FROM postgres:12-alpine
ENV POSTGRES_USER=pguser
ENV POSTGRES_PASSWORD=pgpassword
ENV POSTGRES_DB=securitylearning
COPY pg_hba.conf postgresql.conf /etc/postgresql/config/
COPY --chown=postgres:postgres root.crt server.crt server.key /etc/postgres/security/
COPY init.sql /docker-entrypoint-initdb.d/
EXPOSE 5432
CMD ["postgres", "-c", "config_file=/etc/postgresql/config/postgresql.conf", "-c", "hba_file=/etc/postgresql/config/pg_hba.conf"]
我启动了一个容器,并确保从容器本身可以连接到数据库并从表中选择一些内容。
- 我创建了一个简单的程序: server.go
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
func main() {
connection := fmt.Sprint(
" host=localhost",
" port=5432",
" user=pguser",
" dbname=securitylearning",
" sslmode=verify-full",
" sslrootcert=root.crt",
" sslkey=client.key",
" sslcert=client.crt",
)
db, err := sql.Open("postgres", connection)
defer db.Close()
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
row := db.QueryRow("SELECT * FROM TESTING_DATA")
fmt.Println(row)
}
我尝试过:
- 将
root.crt
、server.crt
、server.key
文件放在编译二进制文件旁边,并在go文件的连接字符串中添加sslrootcert
、sslcert
、sslkey
,分别进行设置 - 将相同的文件,但名称为
root.crt
、postgresql.crt
、postgresql.key
,放在~/.postgresql/
目录中,因为pq默认使用它们。
目前,这种方法不起作用。我随机得到其中一种错误:
read: connection reset by peer
或者
EOF
你能帮忙吗?我错过了什么?或者你能给我指点一些资源吗?谢谢。
更新1 感谢评论中的建议,我创建了客户端密钥和证书,使用以下命令:
# Create client key
openssl genrsa -out client.key 4096
#Remove a passphrase
openssl rsa -in client.key -out client.key
# Create client certificate signing request
openssl \
req -new \
-key client.key \
-subj "/CN=172.17.0.2" \
-out client.csr
# Create client certificate
openssl \
x509 -req \
-in client.csr \
-CA root.crt \
-CAkey root.key \
-CAcreateserial \
-days 365 \
-text \
-out client.crt
我在中国使用172.17.0.2,因为这是从Docker容器的角度看到的主机IP。
我尝试了以下两种方法:
- 在程序中使用连接字符串中的以下键
" sslrootcert=root.crt",
" sslkey=client.key",
" sslcert=client.crt",
- 将
root.crt
、client.key
和client.srt
复制到~/.postgresql/
目录下,尝试使用 psql 进行连接。
psql "host=localhost port=5432 user=pguser dbname=securitylearning sslmode=verify-full sslrootcert=root.crt sslkey=client.key sslcert=client.crt"
或者不需要密码。
两种方式都无法连接。在psql的情况下,我收到以下错误信息:
psql: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.
psql
命令? - Patrick Mevzekpsql "host=localhost port=5432 user=postgres dbname=securitylearning sslmode=verify-full sslrootcert=root.crt"
命令,但是出现了 psql: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request. 的错误提示。主机上的 psql 版本为 12.3(失败),容器中的版本为 12.2(成功)。日志中没有任何相关信息。 - Alexander Shelyugov