本指南介绍如何以简单、最少的配置,让 ClickHouse 使用 OpenSSL 证书验证连接。为便于演示,这里会创建自签名的证书颁发机构 (CA) 证书和密钥,以及节点证书,并使用适当的配置建立连接。
创建 ClickHouse 部署
本指南基于 Ubuntu 20.04 编写,且 ClickHouse 是在以下主机上通过 DEB 软件包 (使用 apt) 安装的。域名为 marsnet.local:
| Host | IP Address |
|---|---|
chnode1 |
192.168.1.221 |
chnode2 |
192.168.1.222 |
chnode3 |
192.168.1.223 |
创建 TLS 证书
-
生成一个将用于新 CA 的私钥:
openssl genrsa -out marsnet_ca.key 2048 -
生成一个新的自签名 CA 证书。以下命令将创建一个新证书,该证书将使用 CA 私钥为其他证书签名:
openssl req -x509 -subj "/CN=marsnet.local CA" -nodes -key marsnet_ca.key -days 1095 -out marsnet_ca.crt
-
验证新 CA 证书的内容:
openssl x509 -in marsnet_ca.crt -text -
为每个节点创建证书签名请求 (CSR) 并生成私钥:
openssl req -newkey rsa:2048 -nodes -subj "/CN=chnode1" -addext "subjectAltName = DNS:chnode1.marsnet.local,IP:192.168.1.221" -keyout chnode1.key -out chnode1.csr openssl req -newkey rsa:2048 -nodes -subj "/CN=chnode2" -addext "subjectAltName = DNS:chnode2.marsnet.local,IP:192.168.1.222" -keyout chnode2.key -out chnode2.csr openssl req -newkey rsa:2048 -nodes -subj "/CN=chnode3" -addext "subjectAltName = DNS:chnode3.marsnet.local,IP:192.168.1.223" -keyout chnode3.key -out chnode3.csr -
使用 CSR 和 CA 创建新的证书与私钥对:
openssl x509 -req -in chnode1.csr -out chnode1.crt -CA marsnet_ca.crt -CAkey marsnet_ca.key -days 365 -copy_extensions copy openssl x509 -req -in chnode2.csr -out chnode2.crt -CA marsnet_ca.crt -CAkey marsnet_ca.key -days 365 -copy_extensions copy openssl x509 -req -in chnode3.csr -out chnode3.crt -CA marsnet_ca.crt -CAkey marsnet_ca.key -days 365 -copy_extensions copy -
验证证书中的 subject 和签发方:
openssl x509 -in chnode1.crt -text -noout -
检查新证书是否可通过 CA 证书验证:
openssl verify -CAfile marsnet_ca.crt chnode1.crt chnode1.crt: OK
创建并配置用于存储证书和密钥的目录
-
在每个节点上,创建一个 ClickHouse 可访问目录中的文件夹。建议使用默认配置目录 (例如
/etc/clickhouse-server) :mkdir /etc/clickhouse-server/certs -
将 CA 证书、节点证书以及与各节点对应的密钥复制到新的 certs 目录中。
-
更新所有者和权限,使 ClickHouse 能够读取这些证书:
chown clickhouse:clickhouse -R /etc/clickhouse-server/certs chmod 600 /etc/clickhouse-server/certs/* chmod 755 /etc/clickhouse-server/certs ll /etc/clickhouse-server/certstotal 20 drw-r--r-- 2 clickhouse clickhouse 4096 Apr 12 20:23 ./ drwx------ 5 clickhouse clickhouse 4096 Apr 12 20:23 ../ -rw------- 1 clickhouse clickhouse 997 Apr 12 20:22 chnode1.crt -rw------- 1 clickhouse clickhouse 1708 Apr 12 20:22 chnode1.key -rw------- 1 clickhouse clickhouse 1131 Apr 12 20:23 marsnet_ca.crt
使用 ClickHouse Keeper 配置基础版集群环境
在此部署环境中,每个节点均使用以下 ClickHouse Keeper 配置。每台服务器都有其独立的 <server_id>。 (例如,节点 chnode1 对应 <server_id>1</server_id>,其余节点以此类推。)
- 在 ClickHouse server 的
config.xml文件中,在<clickhouse>标签内添加以下内容
<keeper_server>
<tcp_port_secure>9281</tcp_port_secure>
<server_id>1</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>trace</raft_logs_level>
</coordination_settings>
<raft_configuration>
<secure>true</secure>
<server>
<id>1</id>
<hostname>chnode1.marsnet.local</hostname>
<port>9444</port>
</server>
<server>
<id>2</id>
<hostname>chnode2.marsnet.local</hostname>
<port>9444</port>
</server>
<server>
<id>3</id>
<hostname>chnode3.marsnet.local</hostname>
<port>9444</port>
</server>
</raft_configuration>
</keeper_server>-
取消所有节点上 Keeper 设置的注释并更新,然后将
<secure>标志设为 1:<zookeeper> <node> <host>chnode1.marsnet.local</host> <port>9281</port> <secure>1</secure> </node> <node> <host>chnode2.marsnet.local</host> <port>9281</port> <secure>1</secure> </node> <node> <host>chnode3.marsnet.local</host> <port>9281</port> <secure>1</secure> </node> </zookeeper> -
在
chnode1和chnode2上更新并添加以下集群设置。chnode3将用作 ClickHouse Keeper 的仲裁节点。
以下将创建一个集群,该集群在两台服务器上各有一个分片副本 (每个节点一个) 。
<remote_servers>
<cluster_1S_2R>
<shard>
<replica>
<host>chnode1.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
<replica>
<host>chnode2.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
</shard>
</cluster_1S_2R>
</remote_servers>-
定义宏配置值,以便创建用于测试的 ReplicatedMergeTree 表。在
chnode1上:<macros> <shard>1</shard> <replica>replica_1</replica> </macros>在
chnode2上:<macros> <shard>1</shard> <replica>replica_2</replica> </macros>
在 ClickHouse 节点上配置 TLS 接口
以下设置需要在 ClickHouse server 的 config.xml 中配置:
-
为部署设置显示名称 (可选) :
<display_name>clickhouse</display_name> -
将 ClickHouse 设置为监听外部端口:
<listen_host>0.0.0.0</listen_host> -
在每个节点上配置
https端口,并禁用http端口:<https_port>8443</https_port> {/*<http_port>8123</http_port>*/} -
在每个节点上配置 ClickHouse Native 安全 TCP 端口,并禁用默认的非安全端口:
<tcp_port_secure>9440</tcp_port_secure> {/*<tcp_port>9000</tcp_port>*/} -
在每个节点上配置
interserver https端口,并禁用默认的非安全端口:<interserver_https_port>9010</interserver_https_port> {/*<interserver_http_port>9009</interserver_http_port>*/} -
使用证书和路径配置 OpenSSL
<openSSL>
<server>
<certificateFile>/etc/clickhouse-server/certs/chnode1.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-server/certs/chnode1.key</privateKeyFile>
<verificationMode>relaxed</verificationMode>
<caConfig>/etc/clickhouse-server/certs/marsnet_ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<caConfig>/etc/clickhouse-server/certs/marsnet_ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>relaxed</verificationMode>
<invalidCertificateHandler>
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>如需了解更多信息,请访问此页面
-
在每个节点上为 gRPC 配置 TLS:
<grpc> <enable_ssl>1</enable_ssl> <ssl_cert_file>/etc/clickhouse-server/certs/chnode1.crt</ssl_cert_file> <ssl_key_file>/etc/clickhouse-server/certs/chnode1.key</ssl_key_file> <ssl_require_client_auth>true</ssl_require_client_auth> <ssl_ca_cert_file>/etc/clickhouse-server/certs/marsnet_ca.crt</ssl_ca_cert_file> <transport_compression_type>none</transport_compression_type> <transport_compression_level>0</transport_compression_level> <max_send_message_size>-1</max_send_message_size> <max_receive_message_size>-1</max_receive_message_size> <verbose_logs>false</verbose_logs> </grpc>如需了解更多信息,请访问 https://clickhouse.com/docs/interfaces/grpc/
-
在至少一个节点上配置 ClickHouse client,使其在自身的
config.xml文件中通过 TLS 建立连接 (默认位于/etc/clickhouse-client/) :<openSSL> <client> <loadDefaultCAFile>false</loadDefaultCAFile> <caConfig>/etc/clickhouse-server/certs/marsnet_ca.crt</caConfig> <cacheSessions>true</cacheSessions> <disableProtocols>sslv2,sslv3</disableProtocols> <preferServerCiphers>true</preferServerCiphers> <invalidCertificateHandler> <name>RejectCertificateHandler</name> </invalidCertificateHandler> </client> </openSSL> -
禁用 MySQL 和 PostgreSQL 的默认模拟端口:
{/*mysql_port>9004</mysql_port*/} {/*postgresql_port>9005</postgresql_port*/}
测试
-
逐个启动所有节点:
service clickhouse-server start -
确认安全端口已启动并正在监听,每个节点上的输出应与以下示例类似:
root@chnode1:/etc/clickhouse-server# netstat -ano | grep tcptcp 0 0 0.0.0.0:9010 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 0.0.0.0:9440 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 0.0.0.0:9281 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 192.168.1.221:33046 192.168.1.222:9444 ESTABLISHED off (0.00/0/0) tcp 0 0 192.168.1.221:42730 192.168.1.223:9444 ESTABLISHED off (0.00/0/0) tcp 0 0 192.168.1.221:51952 192.168.1.222:9281 ESTABLISHED off (0.00/0/0) tcp 0 0 192.168.1.221:22 192.168.1.210:49801 ESTABLISHED keepalive (6618.05/0/0) tcp 0 64 192.168.1.221:22 192.168.1.210:59195 ESTABLISHED on (0.24/0/0) tcp6 0 0 :::22 :::* LISTEN off (0.00/0/0) tcp6 0 0 :::9444 :::* LISTEN off (0.00/0/0) tcp6 0 0 192.168.1.221:9444 192.168.1.222:59046 ESTABLISHED off (0.00/0/0) tcp6 0 0 192.168.1.221:9444 192.168.1.223:41976 ESTABLISHED off (0.00/0/0)ClickHouse 端口 描述 8443 HTTPS 接口 9010 服务器间 HTTPS 端口 9281 ClickHouse Keeper 安全端口 9440 安全的 native TCP 协议端口 9444 ClickHouse Keeper Raft 端口 -
检查 ClickHouse Keeper 的健康状态 常见的 4 字母命令 (4lW) 在未启用 TLS 时无法直接通过
echo使用,以下说明如何用openssl执行这些命令。- 使用
openssl启动一个交互式会话
- 使用
openssl s_client -connect chnode1.marsnet.local:9281CONNECTED(00000003)
depth=0 CN = chnode1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = chnode1
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:CN = chnode1
i:CN = marsnet.local CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICtDCCAZwCFD321grxU3G5pf6hjitf2u7vkusYMA0GCSqGSIb3DQEBCwUAMBsx
...-
在 OpenSSL 会话中执行 4LW 命令
mntr--- Post-Handshake New Session Ticket arrived: SSL-Session: Protocol : TLSv1.3 ... read R BLOCK zk_version v22.7.3.5-stable-e140b8b5f3a5b660b6b576747063fd040f583cf3 zk_avg_latency 0 zk_max_latency 4087 zk_min_latency 0 zk_packets_received 4565774 zk_packets_sent 4565773 zk_num_alive_connections 2 zk_outstanding_requests 0 zk_server_state leader zk_znode_count 1087 zk_watch_count 26 zk_ephemerals_count 12 zk_approximate_data_size 426062 zk_key_arena_size 258048 zk_latest_snapshot_size 0 zk_open_file_descriptor_count 187 zk_max_file_descriptor_count 18446744073709551615 zk_followers 2 zk_synced_followers 1 closed
-
使用
--secure参数和 TLS 端口启动 ClickHouse 客户端:root@chnode1:/etc/clickhouse-server# clickhouse-client --user default --password ClickHouse123! --port 9440 --secure --host chnode1.marsnet.local ClickHouse client version 22.3.3.44 (official build). Connecting to chnode1.marsnet.local:9440 as user default. Connected to ClickHouse server version 22.3.3 revision 54455. clickhouse :) -
使用
https接口登录位于https://chnode1.marsnet.local:8443/play的 Play UI。
-
创建一个复制表:
clickhouse :) CREATE TABLE repl_table ON CLUSTER cluster_1S_2R ( id UInt64, column1 Date, column2 String ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/default/repl_table', '{replica}' ) ORDER BY (id);┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │ │ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │ └───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘ -
在
chnode1上添加几条记录:INSERT INTO repl_table (id, column1, column2) VALUES (1,'2022-04-01','abc'), (2,'2022-04-02','def'); -
通过查看
chnode2上的数据行来验证复制:SELECT * FROM repl_table┌─id─┬────column1─┬─column2─┐ │ 1 │ 2022-04-01 │ abc │ │ 2 │ 2022-04-02 │ def │ └────┴────────────┴─────────┘
为独立运行的 ClickHouse Keeper 配置 OpenSSL
当 ClickHouse Keeper 以独立进程方式运行时 (而不是嵌入在 ClickHouse server 中) ,必须在 Keeper 配置文件中单独配置 OpenSSL 证书和相关设置。否则,Keeper 将无法为客户端通信 (tcp_port_secure) 或 Keeper 节点之间的 Raft 复制建立安全连接。
将以下 <openSSL> 部分添加到每个节点上的独立运行的 ClickHouse Keeper 配置文件中:
<openSSL>
<server>
<certificateFile>/etc/clickhouse-keeper/certs/chnode1.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-keeper/certs/chnode1.key</privateKeyFile>
<verificationMode>relaxed</verificationMode>
<caConfig>/etc/clickhouse-keeper/certs/marsnet_ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<caConfig>/etc/clickhouse-keeper/certs/marsnet_ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>relaxed</verificationMode>
<invalidCertificateHandler>
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL><server> 部分用于通过安全的 Keeper 端口 (tcp_port_secure) 接收客户端传入连接。<client> 部分用于在 Raft 复制期间建立 Keeper 节点之间的出站连接。
OpenSSL 验证模式和证书处理器
<openSSL> 配置支持多种 <verificationMode> 和 <invalidCertificateHandler> 选项,用于控制 ClickHouse 如何验证 TLS 证书。这些设置适用于 clickhouse-server、clickhouse-client 以及独立运行的 ClickHouse Keeper。
验证模式
在 <openSSL> 的 <server> 或 <client> 部分中设置 <verificationMode>:
| 模式 | 描述 |
|---|---|
none |
不进行证书验证。连接会被加密,但不会检查对端的身份。仅用于测试。 |
relaxed |
如果提供了对端证书,则验证该证书;但如果未提供证书,也不会失败。 |
once |
在服务端,仅在初始握手时验证客户端证书,并跳过重新协商。在客户端,其行为与 relaxed 相同。 |
strict |
要求提供对端证书并进行完整验证。如果证书缺失、已过期,或不是由受信任的 CA 签发,连接将失败。建议在生产环境中使用。 |
无效证书处理器
在 <openSSL> 的 <server> 或 <client> 部分中设置 <invalidCertificateHandler>。该处理程序用于确定证书验证失败时如何处理。在服务器端,它控制对无效客户端证书的响应;在客户端,它控制对无效服务器证书的响应。
| 处理程序 | 说明 |
|---|---|
RejectCertificateHandler |
如果证书无效,则拒绝连接。这是默认且推荐的设置。 |
AcceptCertificateHandler |
即使证书无效,也接受连接。仅用于测试。 |
示例:禁用证书验证
如需完全跳过证书验证 (例如在测试环境中使用自签名证书时) ,请将 verificationMode 设置为 none,并使用 AcceptCertificateHandler。
对于 clickhouse-client,你也可以使用 --accept-invalid-certificate CLI 标志,该标志会自动应用这两项设置。
clickhouse-client (/etc/clickhouse-client/config.xml):
<openSSL>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>none</verificationMode>
<invalidCertificateHandler>
<name>AcceptCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>clickhouse-server (config.xml 或 config.d/ 中的某个文件) 。<server> 部分仍然需要证书和密钥路径,因为即使服务器不验证客户端证书,也必须向客户端提供自己的证书:
<openSSL>
<server>
<certificateFile>/etc/clickhouse-server/certs/server.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-server/certs/server.key</privateKeyFile>
<verificationMode>none</verificationMode>
<caConfig>/etc/clickhouse-server/certs/ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>none</verificationMode>
<invalidCertificateHandler>
<name>AcceptCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>独立运行的 ClickHouse Keeper (Keeper 配置文件) :
<openSSL>
<server>
<certificateFile>/etc/clickhouse-keeper/certs/keeper.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-keeper/certs/keeper.key</privateKeyFile>
<verificationMode>none</verificationMode>
<caConfig>/etc/clickhouse-keeper/certs/ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>none</verificationMode>
<invalidCertificateHandler>
<name>AcceptCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>总结
本文重点介绍了如何为 ClickHouse 环境配置 TLS。生产环境中的具体设置会因需求不同而有所差异,例如证书验证级别、协议、密码套件等。不过,相信你现在已经对配置和建立安全连接所需的步骤有了较为清晰的认识。