Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

配置 TLS

ClickHouse Cloud 不支持此功能

本指南介绍如何以简单、最少的配置,让 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 证书

  1. 生成一个将用于新 CA 的私钥:

    openssl genrsa -out marsnet_ca.key 2048
  2. 生成一个新的自签名 CA 证书。以下命令将创建一个新证书,该证书将使用 CA 私钥为其他证书签名:

    openssl req -x509 -subj "/CN=marsnet.local CA" -nodes -key marsnet_ca.key -days 1095 -out marsnet_ca.crt
  1. 验证新 CA 证书的内容:

    openssl x509 -in marsnet_ca.crt -text
  2. 为每个节点创建证书签名请求 (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
  3. 使用 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
  4. 验证证书中的 subject 和签发方:

    openssl x509 -in chnode1.crt -text -noout
  5. 检查新证书是否可通过 CA 证书验证:

    openssl verify -CAfile marsnet_ca.crt chnode1.crt
    chnode1.crt: OK

创建并配置用于存储证书和密钥的目录

  1. 在每个节点上,创建一个 ClickHouse 可访问目录中的文件夹。建议使用默认配置目录 (例如 /etc/clickhouse-server) :

    mkdir /etc/clickhouse-server/certs
  2. 将 CA 证书、节点证书以及与各节点对应的密钥复制到新的 certs 目录中。

  3. 更新所有者和权限,使 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/certs
    total 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>,其余节点以此类推。)

  1. 在 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>
  1. 取消所有节点上 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>
  2. chnode1chnode2 上更新并添加以下集群设置。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>
  1. 定义宏配置值,以便创建用于测试的 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 中配置:

  1. 为部署设置显示名称 (可选) :

    <display_name>clickhouse</display_name>
  2. 将 ClickHouse 设置为监听外部端口:

    <listen_host>0.0.0.0</listen_host>
  3. 在每个节点上配置 https 端口,并禁用 http 端口:

    <https_port>8443</https_port>
    {/*<http_port>8123</http_port>*/}
  4. 在每个节点上配置 ClickHouse Native 安全 TCP 端口,并禁用默认的非安全端口:

    <tcp_port_secure>9440</tcp_port_secure>
    {/*<tcp_port>9000</tcp_port>*/}
  5. 在每个节点上配置 interserver https 端口,并禁用默认的非安全端口:

    <interserver_https_port>9010</interserver_https_port>
    {/*<interserver_http_port>9009</interserver_http_port>*/}
  6. 使用证书和路径配置 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>

如需了解更多信息,请访问此页面

  1. 在每个节点上为 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/

  2. 在至少一个节点上配置 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>
  3. 禁用 MySQL 和 PostgreSQL 的默认模拟端口:

    {/*mysql_port>9004</mysql_port*/}
    {/*postgresql_port>9005</postgresql_port*/}

测试

  1. 逐个启动所有节点:

    service clickhouse-server start
  2. 确认安全端口已启动并正在监听,每个节点上的输出应与以下示例类似:

    root@chnode1:/etc/clickhouse-server# netstat -ano | grep tcp
    tcp        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 端口
  3. 检查 ClickHouse Keeper 的健康状态 常见的 4 字母命令 (4lW) 在未启用 TLS 时无法直接通过 echo 使用,以下说明如何用 openssl 执行这些命令。

    • 使用 openssl 启动一个交互式会话
openssl s_client -connect chnode1.marsnet.local:9281
CONNECTED(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
  1. 使用 --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 :)
  2. 使用 https 接口登录位于 https://chnode1.marsnet.local:8443/play 的 Play UI。

    配置 TLS
  1. 创建一个复制表:

    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 │
    └───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
  2. chnode1 上添加几条记录:

    INSERT INTO repl_table
    (id, column1, column2)
    VALUES
    (1,'2022-04-01','abc'),
    (2,'2022-04-02','def');
  3. 通过查看 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.xmlconfig.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。生产环境中的具体设置会因需求不同而有所差异,例如证书验证级别、协议、密码套件等。不过,相信你现在已经对配置和建立安全连接所需的步骤有了较为清晰的认识。

Navigation