跳到主要内容
跳到主要内容

配置 SSL-TLS

Not supported in ClickHouse Cloud
注意

本页不适用于 ClickHouse Cloud。此处所述流程已在 ClickHouse Cloud 服务中自动化完成。

本指南提供简单且最小化的配置,用于将 ClickHouse 配置为使用 OpenSSL 证书验证连接。作为演示,我们将使用自签名的证书颁发机构(CA)证书和密钥,并为各节点创建证书,以便在配置好相应设置后建立连接。

注意

TLS 的实现相当复杂,需要考虑许多选项以确保部署的安全性和健壮性。本文是一个基础教程,提供基本的 SSL/TLS 配置示例。请咨询贵组织的 PKI/安全团队,以生成适用于贵组织的正确证书。

请参阅这篇关于证书使用的基础教程,以获取入门级概览。

1. 创建 ClickHouse 部署

本指南基于 Ubuntu 20.04,ClickHouse 使用 DEB 软件包(通过 apt)安装在以下主机上。域名为 marsnet.local

主机IP 地址
chnode1192.168.1.221
chnode2192.168.1.222
chnode3192.168.1.223
注意

请参阅 快速开始 了解有关安装 ClickHouse 的更多详细信息。

2. 创建 SSL 证书

注意

使用自签名证书仅用于演示目的,不应在生产环境中使用。应创建证书请求,由组织签发并使用将在设置中配置的 CA 链进行验证。不过,这些步骤可用于配置和测试设置,之后可以替换为实际将使用的证书。

  1. 生成用于新 CA 的密钥:

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

    openssl req -x509 -subj "/CN=marsnet.local CA" -nodes -key marsnet_ca.key -days 1095 -out marsnet_ca.crt
    
    注意

    将密钥和 CA 证书备份到集群外部的安全位置。在生成节点证书后,应从集群节点中删除该密钥。

  3. 验证新 CA 证书的内容:

    openssl x509 -in marsnet_ca.crt -text
    
  4. 为每个节点创建证书请求(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
    
  5. 使用 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
    
  6. 验证证书的使用者(subject)和颁发者(issuer)信息:

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

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

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

注意

必须在每个节点上执行此操作。每个主机上应使用各自对应的证书和密钥。

  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
    

4. 使用 ClickHouse Keeper 配置基础集群环境

在此部署环境中,每个节点使用以下 ClickHouse Keeper 设置。每台服务器都会有各自的 <server_id>。(例如,节点 chnode1<server_id>1</server_id>,依此类推。)

注意

ClickHouse Keeper 推荐使用端口 9281。但是,该端口是可配置的,如果此端口在环境中已被其他应用程序占用,则可以设置为其他端口。

有关所有选项的完整说明,请访问 https://clickhouse.com/docs/operations/clickhouse-keeper/

  1. 在 ClickHouse 服务器的 config.xml 文件中的 <clickhouse> 标签内添加以下内容

    注意

    对于生产环境,建议在 config.d 目录中使用单独的 .xml 配置文件。 更多信息请访问 https://clickhouse.com/docs/operations/configuration-files/

    <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>
    
  2. 在所有节点上取消注释并更新 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>
    
  3. chnode1chnode2 上更新并添加以下集群设置。chnode3 将用于 ClickHouse Keeper 仲裁。

    注意

    在此配置中,仅配置了一个示例集群。测试用示例集群必须被删除或注释掉;或者,如果存在正在测试的现有集群,则必须更新端口并添加 <secure> 选项。如果在安装过程中或在 users.xml 文件中将 default 用户配置为使用密码,则必须设置 <user<password>

    以下配置会在两台服务器上创建一个包含 1 个分片、2 个副本的集群(两个节点各一个副本)。

    <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>
    
  4. 定义宏值,以便创建用于测试的 ReplicatedMergeTree 表。在 chnode1 上:

    <macros>
        <shard>1</shard>
        <replica>replica_1</replica>
    </macros>
    

    chnode2 上:

    <macros>
        <shard>1</shard>
        <replica>replica_2</replica>
    </macros>
    

5. 在 ClickHouse 节点上配置 SSL-TLS 接口

下面的设置在 ClickHouse 服务器的 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 原生安全 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

    注意

    必须根据正在配置的节点,更新每个文件名和路径以保持一致。 例如,在配置 chnode2 主机时,将 <certificateFile> 条目更新为 chnode2.crt

    <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>
    

    更多信息,请访问 https://clickhouse.com/docs/operations/server-configuration-parameters/settings/#server_configuration_parameters-openssl

  7. 在每个节点上配置 gRPC 以使用 SSL:

    <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/

  8. 至少在其中一个节点上,在其自身的 config.xml 文件(默认位于 /etc/clickhouse-client/)中配置 ClickHouse 客户端使用 SSL 建立连接:

    <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>
    
  9. 禁用 MySQL 和 PostgreSQL 的默认兼容端口:

    <!--mysql_port>9004</mysql_port-->
    <!--postgresql_port>9005</postgresql_port-->
    

6. 测试

  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 端口描述
    8443HTTPS 接口
    9010服务器间 HTTPS 端口
    9281ClickHouse Keeper 安全端口
    9440安全的原生 TCP 协议端口
    9444ClickHouse Keeper Raft 端口
  3. 验证 ClickHouse Keeper 运行状况
    典型的 4 letter word (4lW) 命令在未使用 TLS 且通过 echo 调用时将无法使用,下面是如何结合 openssl 使用这些命令。

    • 使用 openssl 启动交互会话
  openssl s_client -connect chnode1.marsnet.local:9281
CONNECTED(00000003)
depth=0 CN = chnode1
verify error:num=20:无法获取本地颁发机构证书
verify return:1
depth=0 CN = chnode1
verify error:num=21:无法验证第一个证书
verify return:1
---
证书链
 0 s:CN = chnode1
   i:CN = marsnet.local CA
---
服务器证书
-----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
    # highlight-next-line
    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
    # highlight-next-line
    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
    # highlight-next-line
    zk_followers    2
    zk_synced_followers     1
    closed
    
  1. 使用 --secure 参数和 SSL 端口启动 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。

    配置 SSL
    注意

    浏览器会显示证书不受信任,这是因为是从工作站访问,且这些证书未添加到客户端机器的根 CA 信任存储中。 当使用由公共 CA 或企业 CA 签发的证书时,则应显示为受信任。

  3. 创建一个复制表:

    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 │
    └───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
    
  4. chnode1 上插入几行数据:

    INSERT INTO repl_table
    (id, column1, column2)
    VALUES
    (1,'2022-04-01','abc'),
    (2,'2022-04-02','def');
    
  5. 通过在 chnode2 上查看行数据来验证复制情况:

    SELECT * FROM repl_table
    
    ┌─id─┬────column1─┬─column2─┐
    │  1 │ 2022-04-01 │ abc     │
    │  2 │ 2022-04-02 │ def     │
    └────┴────────────┴─────────┘
    

总结

本文重点介绍了如何在 ClickHouse 环境中配置 SSL/TLS。生产环境中的具体设置会根据不同需求而有所差异,例如证书验证级别、协议、密码套件等。你现在应该已经清楚了解了配置并实现安全连接所需的各个步骤。