数据库 101:面向初学者的 SSL/TLS

2025-05-26

数据库 101:面向初学者的 SSL/TLS

再次,我将分享我在ScyllaDB担任开发倡导者期间积累的一些日常工作经验,这次我将教大家如何安全加密连接!这个话题可能会让新手感到焦虑,但我将尽量简化。

如果您刚刚开始接触数据库或特定数据库,您可能需要先阅读我的第一篇文章《数据库 101:初学者的数据一致性》

本文记录了我对数据库范式的探索,我的视野远远超出了之前只使用 SQL 和 MySQL 的经验。我会继续在这个数据库 101系列中记录我的学习成果。

目录

1. 序言

使用 NoSQL 数据库很有挑战性,因为我必须学习一些作为普通 Web 开发者永远不会接触或学习的东西。我的意思是,你主要会构建一个 CRUD 应用程序,尽量不弄乱数据库索引(对吧,伙计们???),然后画几个按钮。

但是如果你一直在关注我的数据库 101 之旅,你可能知道我来到 Scylla 时对数据库一无所知,除了 MySQL 是什么以及如何使用 Laravel 构建东西,现在我对它感兴趣:

  • 使用 ScyllaDB 构建高度可扩展的应用程序
  • 仍在学习 Rust — 1 年零 6 个月(我感觉我对它了解不多)
  • 开始学习 ShellScript、Go、Python、JavaScript 以及任何具有 ScyllaDB 驱动程序的程序
  • 学习使用 Grafana/Prometheus 进行可观察性的基础知识
  • 以及我的新朋友传输层安全性(又名TLS

如果您正在搭建自己的服务器,您可能已经使用过certbot来安装证书,以确保 HTTPS 的顺利运行。我过去六七年一直在用这个。说实话,知道如何使用工具才是我们开发人员该做的。

这甚至看起来像一个预兆,但我正在开发一个浏览器扩展,其后端是用 Rust 编写的,而我没有设法certbot在那里使用,所以我不得不使用奇怪的命令创建我的证书并向我的项目openssl添加一个奇怪的板条箱并相信它会起作用:

let mut certs_file = BufReader::new(File::open(cert_path).unwrap());
let mut key_file = BufReader::new(File::open(key_path).unwrap());

// load TLS certs and key to create a self-signed temporary cert for testing:
// `openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost'`
let tls_certs = rustls_pemfile::certs(&mut certs_file)
    .collect::<Result<Vec<_>, _>>()
    .unwrap();
let tls_key = rustls_pemfile::pkcs8_private_keys(&mut key_file)
    .next()
    .unwrap()
    .unwrap();
Enter fullscreen mode Exit fullscreen mode

经过几个小时的尝试/抓取,我终于成功部署了带证书的 API,但我什么也没学到。几天后,老板让我扩展ScyllaDB 安全页面,并学习基于证书的连接是如何工作的,因为我从未使用过它。

我花了 10 个小时才让它工作起来,但主要问题不是文档,而是我缺乏这方面的知识,现在这不再是问题了,我会把我学到的一切教给你!

2.什么是 SSL 和 TLS?

TLDR:这是无聊的部分,如果您愿意,可以跳过。

SSL(安全套接字层)由 Netscape 于 1995 年推出,主要用于在浏览器中为互联网通信提供隐私、身份验证和数据完整性。TLS(传输层安全性)取代了 SSL,如今已成为互联网上电子邮件、消息传递和 VoIP 等应用程序使用的标准安全协议。

如果没有 SSL/TLS,客户端和服务器之间传输的数据将处于未加密状态,容易被拦截和滥用,从而容易成为网络钓鱼和其他攻击的目标。SSL/TLS 确保在数据传输之前进行安全的“握手”,这意味着该会话的所有数据均已加密。

然而,即使 SSL/TLS 提供了加密,它也不能保证服务器本身完全可信或安全。SSL 自 1996 年起因其漏洞而被弃用,但由于其历史意义,开发人员仍然经常将其与 TLS 一起称为“SSL/TLS”。

了解了 SSL/TLS 之后,我们现在深入了解有助于管理安全连接的工具。

3. OpenSSL 新手入门

目前有许多可用的数据加密工具包,但我们将讨论一个非常具体的工具包:openssl-library.org

该库于 1998 年首次发布,附加到有关数据加密的每一个教程中,并且被开放/封闭源环境中的许多其他工具(例如 Let's Encrypt 和 Certbot)使用,以及我们将在这里使用的库。

OpenSSL 手册

此工具的目的是创建钥匙串和凭证,以授权某人做任何你想做的事情。

想象一下,你在一栋商业建筑中工作,你必须向保安出示你的徽章才能进入:

  • 您的公司创建一个“主密钥”并为其生成证书。
  • 您还为保安人员生成密钥和证书,并将它们连同所有员工的证书列表一起交给他。
  • 警卫有一个信任库钥匙串,上面有各种标签。
  • 当你到达入口时,他会检查你的标签是否具有与他的相同的根证书,以决定你是否可以通过。

加密目的图

就命令而言,我们做了类似这样的事情:

# Creating the root/master key and certificate
# -----
openssl genpkey -algorithm RSA -out root_key.pem -pkeyopt rsa_keygen_bits:2048 # Generate the root key
openssl req -x509 -new -key root_key.pem -days 3650 -out root_cert.pem -subj "/CN=administrator" # Generate the root certificate
# -----

# Creating the Employee Key and Certificate
# -----
openssl genpkey -algorithm RSA -out employee_key.pem -pkeyopt rsa_keygen_bits:2048 # Generate the employee base key
openssl req -new -key employee_key.pem -out employee.csr -subj "/CN=employee" # Generate the employee CSR
openssl x509 -req -in employee.csr -CA root_cert.pem -CAkey root_key.pem -CAcreateserial -out employee_cert.pem -days 365 # Sign and generate the employee certificate with the root/master key and certificate
cat root_cert.pem employee_cert.pem > employee_truststore.pem # Create a truststore (tag) to be used together with the key.
# -----

# Creating the Security (server) Key and Certificate
# -----
openssl genpkey -algorithm RSA -out security_key.pem -pkeyopt rsa_keygen_bits:2048 # Generate the security key
openssl req -new -key security_key.pem -out security.csr -subj "/CN=server" # Generate the security CSR
openssl x509 -req -in security.csr -CA root_cert.pem -CAkey root_key.pem -CAcreateserial -out security_cert.pem -days 365 # Sign and generate the security certificate with the root/master key and certificate
cat root_cert.pem security_cert.pem > security_truststore.pem # Create a truststore (tag) to be used together with the key.
# -----


# Creating the Malicious Root and Client Key and Certificate
# -----
openssl genpkey -algorithm RSA -out malicious_key.pem -pkeyopt rsa_keygen_bits:2048 # Generate the malicious root key
openssl req -x509 -new -key malicious_key.pem -days 3650 -out malicious_cert.pem -subj "/CN=fake-admin" # Generate the malicious root certificate
cat root_cert.pem malicious_cert.pem > malicious_truststore.pem # Combine root and malicious root certificates into a truststore
# -----
Enter fullscreen mode Exit fullscreen mode

命令太多了,但基本上是这样的:

  • Aroot_key.pemroot_cert.pem被生成。
  • 这些密钥和证书用于为员工签署其他密钥和证书:
    • security_key.pem由 签署root_key.pem
    • employee_key.pem由 签署root_key.pem
    • server_key.pem已由 签署root_key.pem
  • 所有这些密钥都位于一个名为的文件中security_truststore.pem
  • 有人试图使用 来创建一个名为 的假密钥malicious_key.pemroot_cert.pem

现在让我们做一些验证。理论上,只有 中的键security_truststore.pem才应该被允许加入:

# Validating the certificates with the truststores
# ----- 
openssl verify -CAfile security_truststore.pem employee_cert.pem # Check if the certificate is valid
# employee_cert.pem: OK

openssl verify -CAfile security_truststore.pem malicious_cert.pem # Check if the certificate is valid
# CN = fake-admin
#  error 18 at 0 depth lookup: self-signed certificate
#  error malicious_cert.pem: verification failed
# ----- 
Enter fullscreen mode Exit fullscreen mode

正如预期的那样,由于恶意密钥未由 root 用户签名,因此身份验证失败,该用户被踢出。

现在我们已经了解了加密的基础知识。但是在现实世界中,你会在哪里使用它呢?让我进一步介绍一下我目前的任务,这样你就会明白了。

4.数据库身份验证

假设你在 Docker 中运行任意数据库(例如 MySQL、Postgres、ScyllaDB、Redis 等)。当你在容器化环境中启动这些实例时,通常不需要密码,除非你设置了密码。无论如何,在现代 Web 的任何部分,当我们谈论身份验证时,我们都有很多选择,在谈论数据库时也是如此。

在这个例子中我们将使用ScyllaDB ,但是这种流程在许多数据库中相当常见

在此步骤中,我们将了解:

  1. 无需身份验证:实际上不需要任何凭证,只需旋转您的实例即可;
  2. 用户名/密码验证:一些基本凭证可以防止人们获取您的数据;
  3. 认证/角色认证身份验证:这是大公司喜欢玩的地方,你应该学习这一点。

在对加密 101 进行简要介绍之后,我们可以开始处理内容本身。

4.1 无需身份验证

在 Scylla 中,如果您在开发环境中(本地或使用 Docker)运行节点或集群,则默认情况下没有密码。此外,ScyllaDB 默认在端口 9042 上使用 CQL 协议,您可以在配置文件中轻松更改该协议。

我为什么要告诉你这个端口信息?因为这些信息以后会很重要,相信我。

您可以通过运行来启动 Docker 实例:

# Running a ScyllaDB Node with Docker
docker  run --name some_scylla -p 9042:9042 -p 9142:9142 -d scylladb/scylla:6.1.2 \
  --overprovisioned 1 --smp 1 

# Checking the node status -> Expect for UN (Up And Running)Cassandra
docker exec -it some_scylla nodetool status
# Datacenter: datacenter1
# =======================
# Status=Up/Down
# |/ State=Normal/Leaving/Joining/Moving
# -- Address   Load      Tokens Owns Host ID                              Rack 
# UN 10.10.5.2 509.46 KB 256    ?    9f597eb5-a77f-493f-9835-85dd1e571fcc rack1
# --

Enter fullscreen mode Exit fullscreen mode

之后,您可以通过运行以下命令登录cqlsh(CQL Shell) :

docker exec -it some_scylla cqlsh
# Connected to  at 10.10.5.5:9042
# [cqlsh 6.0.18 | Scylla 6.0.1-0.20240612.bc89aac9d017 | CQL spec 3.3.1 | Native protocol v4]
# Use HELP for help.
# cqlsh> select address, port, client_type, username from system.clients;
#
#  address   | port  | client_type | username
# -----------+-------+-------------+-----------
#  10.10.5.5 | 50854 |         cql | anonymous
#  10.10.5.5 | 50868 |         cql | anonymous
# -----------+-------+-------------+-----------
Enter fullscreen mode Exit fullscreen mode

是的,我们以匿名用户身份连接!非常适合开发新东西并在本地测试。但后来你决定将相同的配置部署到生产环境中……

当然,不到一个小时的时间,你就会被一些随机的数据库爬虫所拥有,哈哈。

拥有 PostgreSQL

如果需要,您可以阅读更多关于此勒索软件的信息。接下来,让我们添加一些基本凭据,并在下一步中进行正确配置。

认真地说,不要使用默认配置或未绑定唯一 IP 地址来访问数据库而将其开放到互联网上。

4.2 用户名/密码认证

在运行任何其他数据库时,您可以通过更改一系列配置文件来切换身份验证类型。在ScyllaDB,我们为其模块化和便捷的配置方式感到自豪。

如果您查看您的 docker(您可以通过单击此处(文件:scylla.yaml#247)/etc/scylla/scylla.yaml更好地查看存储库) ,您将发现这些配置标志:

# file: /etc/scylla/scylla.yaml
# ...
# ...
# Authentication backend, identifying users
# Out of the box, Scylla provides org.apache.cassandra.auth.{AllowAllAuthenticator,
# PasswordAuthenticator}.
#
# - AllowAllAuthenticator performs no checks - set it to disable authentication.
# - PasswordAuthenticator relies on username/password pairs to authenticate
#   users. It keeps usernames and hashed passwords in system_auth.credentials table.
#   Please increase system_auth keyspace replication factor if you use this authenticator.
# - com.scylladb.auth.TransitionalAuthenticator requires username/password pair
#   to authenticate in the same manner as PasswordAuthenticator, but improper credentials
#   result in being logged in as an anonymous user. Use for upgrading clusters' auth.
# authenticator: AllowAllAuthenticator
# ...
Enter fullscreen mode Exit fullscreen mode

默认值是 ,AllowAllAuthenticator允许具有超级权限的匿名连接。现在,我们取消注释该# authenticator:行,并将其替换为PasswordAuthenticator

# file: /etc/scylla/scylla.yaml
# ...
-#authenticator: AllowAllAuthenticator  # line ~247
+authenticator: PasswordAuthenticator
Enter fullscreen mode Exit fullscreen mode

好的!现在我们只需要告诉 Scylla 节点我们已经完成了这个更改。由于这是对系统环境的“关键”更改,因此我们需要drain重新启动节点。以下是分步指南:

# Before Editing
docker exec -it some_scylla nodetool drain # Stop gossiping and preparing to shut down
docker exec -it some_scylla supervisorctl stop scylla # Stop ScyllaDB
docker exec -it some_scylla cat /etc/scylla/scylla.yaml | grep authenticator: # Check the current flag

# Edit /etc/scylla/scylla.yaml ...
docker exec -it some_scylla sed -i 's/# authenticator:.*/authenticator: PasswordAuthenticator/' /etc/scylla/scylla.yaml

# After Edit
docker exec -it some_scylla cat /etc/scylla/scylla.yaml | grep authenticator: # Check if the update is there
docker exec -it some_scylla supervisorctl start scylla # Run ScyllaDB
Enter fullscreen mode Exit fullscreen mode

这样,我们终于可以运行了cqlsh,但却收到了一条巨大的“你需要凭证,贱人”的消息:

docker exec -it some_scylla cqlsh
Connection error: ('Unable to connect to any servers', {'10.10.5.5:9042': AuthenticationFailed('Remote end requires authentication')})
Enter fullscreen mode Exit fullscreen mode

默认情况下,在 ScyllaDB,我们可以使用用户名/密码“cassandra”(超级用户)登录:

docker exec -it some_scylla cqlsh -u cassandra -p cassandra
# Connected to  at 10.10.5.5:9042
# [cqlsh 6.0.18 | Scylla 6.0.1-0.20240612.bc89aac9d017 | CQL spec 3.3.1 | Native protocol v4]
# Use HELP for help.
# cassandra@cqlsh> select address, port, client_type, username from system.clients; 

#  address   | port  | client_type | username
# -----------+-------+-------------+-----------
#  10.10.5.5 | 56998 |         cql | cassandra
#  10.10.5.5 | 57014 |         cql | cassandra
# -----------+-------+-------------+-----------
Enter fullscreen mode Exit fullscreen mode

... 至此,我们了解了如何在 ScyllaDB 中配置身份验证的基础知识,如果您想知道为什么用户名/密码是“cassandra”,可以阅读我在本系列的第一篇文章。另外,在部署之前,请务必更改您的默认凭据。

CQL 协议默认在 9042 端口上运行,这是众所周知的。就像您可以通过让数据库在无需身份验证的情况下运行来获得所有权一样,您也可以通过在该端口上使用默认凭据来获得所有权。

目前,所有连接仍然正常unencrypted,但至少我们拥有最低限度的安全性,不过别担心!我们很快就会修复加密!在此之前,让我们在数据库中创建一些用户/角色。

4.3 创建用户和角色

在为该数据库创建新用户之前,我们需要了解它的工作原理。在 Scylla,我们Role Based Authentication每天都会用到它。因此,每个用户都被归类system.roles为一个角色。

这没问题,因为你可以将 设置PASSWORD为一个角色。虽然看起来有点奇怪,但我会向你展示它是如何工作的。看看吧:

scylladb@cqlsh> desc system.roles;

CREATE TABLE system.roles (
    role text,
    can_login boolean,
    is_superuser boolean,
    member_of set<text>,
    salted_hash text,
    PRIMARY KEY (role)
);

scylladb@cqlsh> select * from system.roles;

 role        | can_login | is_superuser |     member_of | salted_hash
-------------+-----------+--------------+---------------+--------------------
 scylladb    |      True |         True |          null | $6$rAJ6FflUo8Chf...
 employee    |     False |        False |          null | null
 danielhe4rt |      True |        False |  {'employee'} | $6$AF4F6CflAA8Cw...
-------------+-----------+--------------+---------------+--------------------


Enter fullscreen mode Exit fullscreen mode

此输出向我们提供了有关身份验证本身的一些信息,例如

  • can_login当标志设置为时,角色变为可验证的true
  • 角色在成为可验证角色后必须/可以有密码;
  • 角色可以属于another role,并将继承其所有权限。

这只是一个示例环境,旨在向您展示模型和功能的工作原理。请务必阅读文档。

在DCL(数据控制语言)DML(数据操作语言)方面,我们将执行如下基本命令:

-- Create our user/roles
CREATE ROLE developer;
CREATE ROLE danielhe4rt WITH PASSWORD = 'some_cool_password' AND LOGIN = true;

-- Grant roles to our users
GRANT developer TO danielhe4rt;
Enter fullscreen mode Exit fullscreen mode

...我们将按照文章开头创建的键在我们的 ScyllaDB Docker 实例上运行它:

docker exec -it some-scylla cqlsh -u cassandra -p cassandra -e "CREATE ROLE IF NOT EXISTS 'employee' WITH LOGIN = true;";
docker exec -it some-scylla cqlsh -u cassandra -p cassandra -e "CREATE ROLE IF NOT EXISTS 'server' WITH LOGIN = true;";
Enter fullscreen mode Exit fullscreen mode

注意:您只能使用经过身份验证的帐户创建新的角色/用户

4.4 证书/角色证书认证

在本教程的开头,我们通过一个故事介绍了一个持有有效钥匙进入建筑物的人,现在的目标是理解它与常规身份验证的区别。正如我所说,如果没有 TLS/SSL,您的数据在传输过程中将没有任何加密,这很糟糕,具体取决于您发送/接收的内容。

使用证书意味着在您发送数据之前,我们可以保证如果有人截取数据,只要他们没有解密的密钥就不会有问题。

  • 默认情况下,ScyllaDB 在端口 9042 上监听 CQL 协议,可以使用native_transport_port配置选项进行配置。
  • Scylla 还通过 TLS/SSL 加密支持 CQL 协议,该协议默认情况下是禁用的,可以使用native_transport_port_ssl配置选项启用。

安全连接的传统端口选择是 9142,但如果client_encryption_options指定了 而未native_transport_port_ssl指定 ,则将仅处理加密连接。如果设置为相同的值,native_transport_port也会发生相同的情况。native_transport_portnative_transport_port_ssl

我知道,这么多标志和选项看起来有点疯狂,但我会尽量简化。请查看控制端口分配/加密的规则,总结如下表:

np  := native_transport_port is set
nps := native_transport_port_ssl is set
ceo := client_encryption_options are enabled
eq  := native_transport_port_ssl == native_transport_port

+-----+-----+-----+-----+
|  np | nps | ceo |  eq |
+-----+-----+-----+-----+
|  0  |  0  |  0  |  *  |   =>   listen on native_transport_port, unencrypted
|  0  |  0  |  1  |  *  |   =>   listen on native_transport_port, encrypted
|  0  |  1  |  0  |  *  |   =>   don't listen
|  0  |  1  |  1  |  *  |   =>   listen on native_transport_port_ssl, encrypted
|  1  |  0  |  0  |  *  |   =>   listen on native_transport_port, unencrypted
|  1  |  0  |  1  |  *  |   =>   listen on native_transport_port, encrypted
|  1  |  1  |  0  |  *  |   =>   listen on native_transport_port, unencrypted
|  1  |  1  |  1  |  0  |   =>   listen on native_transport_port, unencrypted + native_transport_port_ssl, encrypted
|  1  |  1  |  1  |  1  |   =>   listen on native_transport_port(_ssl - same thing), encrypted
+-----+-----+-----+-----+

// More at: https://github.com/scylladb/scylladb/blob/master/docs/dev/protocols.md#cql-client-protocol
Enter fullscreen mode Exit fullscreen mode

这告诉我们,如果我们想要启用加密,我们需要在中更新一些内容scylla.yaml。我们不会使用PasswordAuthenticator,而是切换到com.scylladb.auth.CertificateAuthenticator功能。

在我们改变任何事情之前,让我们先清空并停止我们的集群:

docker exec -it some_scylla nodetool drain # Stop gossiping and preparing to shut down
docker exec -it some_scylla supervisorctl stop scylla # Stop ScyllaDB
Enter fullscreen mode Exit fullscreen mode

在上一步中,我们创建了一些启用了 LOGIN 的角色。并且我们在 OpenSSL 命令顶部添加了这些“角色”,并使用了CN=server/blabla,对吧?现在是时候让它变得有用,不再需要凭证了。

私钥 + 证书可以保存更多信息,例如握手完成后可以使用的原始字符串。在本例中,我们将用于登录的用户/角色存储在密钥中。这样,我们就可以对证书内容进行模式匹配,检查是否有任何CN=something与我们匹配select * from system.roles where role = 'something'

让我们通过进入我们的 ScyllaDB 实例来开始修改:

# Enter the ScyllaDB Instance
docker exec -it some_scylla shell

# root@c531i213hu:/#
# Install any editor of your choice
apt install nano

# Enter the ScyllaDB Config File
nano -l /etc/scylla/scylla.yaml
Enter fullscreen mode Exit fullscreen mode

打开配置文件后,让我们进行所需的修改。

4.4.1 更改身份验证类型

我保证,这是我们最后一次打开这个文件!这里的想法是将身份验证类型从 更改PasswordAuthenticatorcom.scylladb.auth.CertificateAuthenticator。我们还将设置一条规则,从每个证书中提取CN=标志,并将内容用于身份验证目的:

# file: /etc/scylla/scylla.yaml

-authenticator: PasswordAuthenticator # line ~247
+authenticator: com.scylladb.auth.CertificateAuthenticator
+auth_certificate_role_queries:
+  - source: SUBJECT
+    query: CN=([^,\s]+)
Enter fullscreen mode Exit fullscreen mode

4.4.2 启用加密端口

即使设置了身份验证器,我们仍然没有启用TLS/SSLnative_transport_port_ssl 。我们仍然需要取消注释,以便将端口 9142(用于传输加密数据)接入游戏。所以,回到scylla.yaml,让我们修改它:

# file: /etc/scylla/scylla.yaml
# ...
-# native_transport_port_ssl: 9142 # <- line ~131
+native_transport_port_ssl: 9142
Enter fullscreen mode Exit fullscreen mode

4.4.3 启用客户端加密端口

一步一步,我们一定成功!最终的修改是按照client_encryption_options上表的定义进行。我们需要取消所有注释,并确保所有配置都匹配。以下是每个配置的简要说明:

  • enabled:启用 TLS/SSL 加密 -> 更改为true(默认值:false)
  • 证书: absolute path您的服务器证书(security_cert.pem / server_cert.pem)
  • 密钥文件: absolute path由 root_key 签名的服务器密钥(security_key.pem / server_key.pem)
  • 信任库: absolute path包含服务器 + 根证书的服务器信任库(security_truststore.pem / server_truststore.pem)
  • require_client_auth:您的服务器必须收到证书才能进行身份验证->更改为 true

那么,让我们来努力实现这些改变:

# file: /etc/scylla/scylla.yaml
# ...
# enable or disable client/server encryption.
-# client_encryption_options:
-#   enabled: true
-#   certificate: /etc/scylla/certs/cert.pem
-#   keyfile: /etc/scylla/certs/key.pem
-#   truststore: /etc/scylla/certs/truststore.pem
-#   require_client_auth: true
+client_encryption_options:
+  enabled: true
+  certificate: /etc/scylla/certs/server_cert.pem
+  keyfile: /etc/scylla/certs/server_key.pem
+  truststore: /etc/scylla/certs/server_truststore.pem
+  require_client_auth: true
Enter fullscreen mode Exit fullscreen mode

好的!现在一切就绪。运行以下命令启动 ScyllaDB 集群:

docker exec -it some_scylla supervisorctl start scylla # Start ScyllaDB
Enter fullscreen mode Exit fullscreen mode

让我们看看我们的端口 9142 是否正在运行并监听 TLS/SSL 连接:

openssl s_client -connect localhost:9042 
# CONNECTED(00000003)
# 40873B60D2750000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../ssl/record/ssl3_record.c:354:
# no peer certificate available
# No client certificate CA names sent

openssl s_client -connect localhost:9142
# CONNECTED(00000003)
# Can't use SSL_get_servername
# depth=0 CN = server
# verify error:num=20:unable to get local issuer certificate
# verify return:1
# depth=0 CN = server
# verify error:num=21:unable to verify the first certificate
# verify return:1
# depth=0 CN = server
# verify return:1
# ---
# Certificate chain
# 0 s:CN = server
#   i:CN = administrator
#   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
#   v:NotBefore: Aug  1 20:09:38 2024 GMT; NotAfter: Aug  1 20:09:38 2025 GMT
# ---
# YAY IT'S ASKING FOR CERTIFICATES!!!
Enter fullscreen mode Exit fullscreen mode

此时,我们 100% 确定 TLS 已启用并请求与我们之前生成的密钥匹配的证书。

5.测试加密连接

要配置的东西太多了,但该如何连接呢?我们不会使用 CQLSH(因为设置起来很麻烦,而且我更倾向于在 Node 上实现它,而不是解释如何使用它),为了简单起见,我们将使用 NodeJS。

首先,让我们通过运行以下命令快速设置我们的驱动程序:

npm install @lambda-group/scylladb
Enter fullscreen mode Exit fullscreen mode

之后,您就可以创建一个指向您的节点的演示脚本,并且不要忘记在连接字符串中切换端口:

import { Cluster } from "@lambda-group/scylladb";

const cluster = new Cluster({  
    nodes: ["127.0.0.1:9142"],
    ssl: {  
        enabled: true,  
        truststoreFilepath: "/your/path/to/certificates/developer_cert.pem",  
        privateKeyFilepath: "/your/path/to/certificates/developer_key.pem",  
        caFilepath: "/your/path/to/certificates/developer_truststore.pem",  
        verifyMode: VerifyMode.Peer,  
    }});
let result = await session.execute(
    "SELECT address, port, username, driver_name, driver_version FROM system.clients"
    );

console.log(result)
// [
//  {
//     address: '127.0.0.1',
//     driver_name: 'scylla-js-driver',
//     driver_version: '0.0.1',
//     port: 58846,
//     username: 'developer' // We're logged in as the role 'developer'
//  }
// ]
Enter fullscreen mode Exit fullscreen mode

正如输出告诉我们的那样,我们仅通过向服务器发送密钥和证书就成功建立了连接!

6. 结论

由于多种原因,我花了很长时间才写出这篇“文章/教程”,但其中之一就是通过多次阅读来确保内容的准确性。

我还做了一个演示 (gh: danielhe4rt/scylladb-role-tls-auth),你可以运行一个makefile命令来设置所有这些步骤。所以如果你以某种方式来到了这里,请别忘了点个星哦 :D

安全是如今人们越来越关注的话题之一,深入了解它非常令人兴奋。总之,请告诉我你希望在本系列中看到哪些主题!

注意安全,别忘了喝水!

文章来源:https://dev.to/scylladb/database-101-ssltls-for-beginners-4lmn
PREV
数据库 101:适合初学者的更高级别的 Twitch Bot。
NEXT
数据库 101:如何为 100 万玩家的游戏建模排行榜。