zergduan commented on issue #4527:
URL: https://github.com/apache/rocketmq/issues/4527#issuecomment-1169614402

   
   1. 在 RocketMQ 的使用过程中,有以下服务器参与交互:Producer,Consumer,Broker,Namesrv,Dashboard;
       Producer,Consumer,Dashboard 只能作为 Client,即连接的发起方
       Namesrv 只能作为 Server,即连接的接收方
       Broker 同时作为 Server 和 Client,broker作为client主动连接Namesrv,borker也作为server被 
Producer 和 Consumer 连接
   
   2. Configuration_TLS.md 文档中描述的是一个 Client - Server 双向验证的 TLS 配置过程,因此 
Server上配置 server证书、server私钥、根证书,同时 Client 上也许需要配置 client证书、client私钥、根证书。并且所有 
Client ( Producer, Consumer, Dashboard,Broker 都需要配置 tls.enable=true,来确保发起 TLS 
连接。
   
   3. 其实 RocketMQ 是支持单向认证的,并且可同时支持 TLS 连接和非 TLS 连接, 所以我们一般都只需要配置 Server 端认证的 
TLS 就可以了,相对于双向认证,Server 端认证可以避免未来因证书过期导致的大批量更换 Client 证书的工作;同时支持 TLS 和非 TLS 
连接,可以让同一套 RocketMQ 同时对内提供服务(非TLS连接,比如Dashboard管理RocketMQ集群)和 
对外提供服务(公网或者跨站点访问RocketMQ的生产者,消费者连接),减少我们的管理成本。
   
   实现 Server 端单向认证,并且同时支持TLS连接和非TLS连接,需要我们完成一下工作:
   
   1). 在所有的Server上部署server证书和server私钥,Server包括:Namesrv,Broker
   2). 在需要TLS的Client上部署根证书,Client包括:Producer,Consumer,Dashboard,Broker
   3). 在所有的Server端,使用 tls.server.mode = permissive 来确保可以同时接收 TLS 和 非 TLS 连接
   4). 在需要TLS的Client上使用 tls.enable = true 来确保发起 TLS 连接
   5). 在不需要TLS的Client上使用tls.enable = false 来确保发起非 TLS 连接
   
   
   
   假设场景:
   
   Namesrv 和 Broker 之间通信不使用TLS
   Dashboard 和 Namesrv 之间同时不使用TLS
   ProducerA,ConsumerA 使用TLS连接Namesrv和Broker,并且使用Server端单向认证
   ProducerB,ConsumerB 使用非TLS连接Namesrv和Broker
   
   所以如果我们使用自签名证书来实现以上场景时的步骤为:
   
   step1 签署CA根证书
   openssl req -newkey rsa:2048 -keyout ca_rsa_private.pem -x509 -days 365 -out 
ca.pem
   
   
   step2 准备server端认证所需的私钥和证书
   
   step2.1 生成server私钥并签发server证书
   openssl req -newkey rsa:2048 -keyout server_rsa.key  -out server.csr
   openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey 
ca_rsa_private.pem -CAcreateserial -out server.pem
   
   step2.2 打包并加密server私钥
   openssl pkcs8 -topk8 -v1 PBE-SHA1-RC4-128 -in  server_rsa.key -out server.key
   
   注:在后面配置过程中,需要使用以下3个文件
   a. 打包并加密的server私钥 server.key,用于部署在Server端(Namesrv,Broker)
   b. server证书 server.pem,用于部署在Server端(Namesrv,Broker)
   c. CA根证书 ca.pem,用于部署在需要TLS连接的Client端
   
   
   step3A 配置Namesrv和Broker(Namesrv 和 Broker 之间通信不使用TLS)
   
   step3A.1 创建tls.properties
   # The flag to determine whether use test mode when initialize TLS context. 
default is true
   tls.test.mode.enable=false                     
   # Indicates how SSL engine respect to client authentication, default is none
   # 此参数控制是否开启客户端认证,此处设置为none,即关闭客户端认证,从而实现Server端单向认证
   tls.server.need.client.auth=none
   # The store path of server-side private key
   tls.server.keyPath=/opt/certFiles/server.key
   # The password of the server-side private key
   tls.server.keyPassword=123456
   # The store path of server-side X.509 certificate chain in PEM format
   tls.server.certPath=/opt/certFiles/server.pem
   
   step3A.2 编辑Namesrv的启动参数,在runserver.sh的JAVA_OPT中增加以下内容:
   JAVA_OPT="${JAVA_OPT} -Dtls.server.mode=permissive 
-Dtls.config.file=/opt/rocketmq-4.9.3/conf/tls.properties"
   
   step3A.3 编辑Broker的启动参数,在runbroker.sh的JAVA_OPT中增加以下内容:
   JAVA_OPT="${JAVA_OPT} -Dtls.server.mode=permissive 
-Dtls.config.file=/opt/rocketmq-4.9.3/conf/tls.properties"
   
   
   step3B 配置Namesrv和Broker(Namesrv 和 Broker 之间通信使用TLS)
   
在RocketMQ运行过程中,Namesrv只会作为Server,而Broker会同时作为Server和Client,所以此时Namesrv和Broker的配置并不一致,如下:
   
   step3B.1 创建tls.properties for Namesrv
   # The flag to determine whether use test mode when initialize TLS context. 
default is true
   tls.test.mode.enable=false                     
   # Indicates how SSL engine respect to client authentication, default is none
   # 此参数控制是否开启客户端认证,此处设置为none,即关闭客户端认证,从而实现Server端单向认证
   tls.server.need.client.auth=none
   # The store path of server-side private key
   tls.server.keyPath=/opt/certFiles/server.key
   # The password of the server-side private key
   tls.server.keyPassword=123456
   # The store path of server-side X.509 certificate chain in PEM format
   tls.server.certPath=/opt/certFiles/server.pem
   
   step3B.2 创建tls.properties for Broker
   # The flag to determine whether use test mode when initialize TLS context. 
default is true
   tls.test.mode.enable=false                     
   # Indicates how SSL engine respect to client authentication, default is none
   # 此参数控制是否开启客户端认证,此处设置为none,即关闭客户端认证,从而实现Server端单向认证
   tls.server.need.client.auth=none
   # The store path of server-side private key
   tls.server.keyPath=/opt/certFiles/server.key
   # The password of the server-side private key
   tls.server.keyPassword=123456
   # The store path of server-side X.509 certificate chain in PEM format
   tls.server.certPath=/opt/certFiles/server.pem
   # 以下2个参数是当Broker作为Client时生效的
   # To determine whether verify the server endpoint's certificate strictly
   # 当Broker作为Client进行Server端认证时,此参数控制是否做严格验证,比如是否验证Server的主机名与Server证书中的CN相同
   tls.client.authServer=false                    
   # The store path of trusted certificates for verifying the server endpoint's 
certificate
   # 此参数提供了根证书的位置,当Broker作为Client进行Server端认证时,需要找到根证书来确认server证书的合法性
   tls.client.trustCertPath=/opt/certFiles/ca.pem
   
   step3B.3 编辑Broker的启动参数,在runbroker.sh的JAVA_OPT中增加以下内容:
   # 参数tls.enable=true用来控制,当Broker作为Client时,发起TLS连接
   JAVA_OPT="${JAVA_OPT} -Dtls.server.mode=permissive 
-Dtls.config.file=/opt/rocketmq-4.9.3/conf/tls.properties  -Dtls.enable=true"
   
   
   step4 非TLS连Prodcuer、Consumer、Dashboard配置
   无需特殊修改
   
   
   step5 TLS连接Producer、Consumer配置
   
   step5.1 创建tlsclient.properties
   # The store path of trusted certificates for verifying the server endpoint's 
certificate
   # 此参数提供了根证书的位置,作为Client进行Server端认证时,需要找到根证书来确认server证书的合法性
   tls.client.trustCertPath=/opt/certFiles/ca.pem
   
   step5.2 JVM中需要加以下参数.tls.config.file的值需要使用之前创建的文件:
   # 
作为Client进行Server端认证时,tls.client.authServer参数控制是否做严格验证,比如是否验证Server的主机名与Server证书中的CN相同
   # 参数tls.enable=true用来控制,Client发起TLS连接
   -Dtls.client.authServer=false -Dtls.enable=true -Dtls.test.mode.enable=false 
 -Dtls.config.file=/opt/certs/tlsclient.properties
   
   step 5.3 在连接代码中,需要将setUSETLS设置为true
   public class ExampleProducer {
       public static void main(String[] args) throws Exception {
           DefaultMQProducer producer = new 
DefaultMQProducer("please_rename_unique_group_name");
           //setUseTLS should be true
           producer.setUseTLS(true);
           producer.start();
   
           // Send messages as usual.
           producer.shutdown();
       }    
   }


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to