RocketMq開啟安全認證ACL-解決伺服器系統安全漏洞

sowler發表於2024-05-21

1、為什麼要開啟ACL

透過之前的文章我們已經知道怎麼安裝RocketMq了。如果你還不會安裝RocketMq可以檢視我的這篇文章:快速入門一篇搞定RocketMq-實現微服務實戰落地 進行軟體安裝,附文章地址:https://www.cnblogs.com/sowler/p/18173752 。雖說已經安裝成功了,但是它現在在伺服器上面還處於"裸奔"狀態。如果是公司內網伺服器還好,有一層安全保障。但是如果是公網伺服器駭客可以根據RocketMq埠號入侵伺服器系統植入木馬病毒,給伺服器帶來安全漏洞。所以如果部署在公網環境下,強烈建議開啟RocketMq的ACL機制以加強系統的安全性。

2、ACL的作用

ACL主要是為了增強系統的安全性和保護訊息佇列資料的機密性。透過ACL,可以限制使用者或應用程式對訊息佇列的訪問許可權,只有經過授權的使用者才能進行相關操作,如傳送訊息、消費訊息等。防止未經授權的使用者或惡意應用程式對訊息佇列進行操作,減少潛在的安全風險和資料洩露的可能性。同時,ACL還可以幫助管理者更好地控制系統的訪問許可權,提高系統的可控性和安全性。總體來說,開啟ACL是一種有效的安全措施,可以保護RocketMq系統免受未經授權的訪問和潛在的安全威脅。

3、ACL是什麼

RocketMQ的ACL(Access Control List)是一種安全機制,用於對訊息中介軟體的訪問進行授權和限制。ACL機制可以確保只有具備相應許可權的使用者才能執行特定的操作,從而保護訊息系統的安全性。而ACL管理員可以對以下操作進行細粒度的控制和許可權管理:

  • Topic級別許可權控制: 管理員可以對每個Topic設定讀寫許可權,決定哪些使用者或角色有權傳送和訂閱該主題的訊息。
  • Consumer組許可權控制: 管理員可以為每個消費者組分配訂閱許可權,控制哪些使用者或角色有權使用該消費者組並接收訊息。
  • IP地址訪問控制: 管理員可以基於客戶端的IP地址進行訪問控制,只允許特定的IP地址範圍訪問訊息中介軟體。

4、伺服器開啟ACL

首先我們檢視RocketMq官網選擇4.X版本的文件進行檢視,找到控制許可權選單。連結:https://rocketmq.apache.org/zh/docs/4.x/bestPractice/04access

透過說明,我們可以看到許可權控制配置檔案位置在 /conf/plain_acl.yml ,知道配置檔案後進入 conf 目錄,首先先備份一份檔案防止後面改錯了無法恢復,然後在編輯該檔案。

#備份檔案
cp plain_acl.yml plain_acl.yml.init.bak

#編輯檔案
vim plain_acl.yml

配置資訊如下

#白名單中,不會走acl鑑權
globalWhiteRemoteAddresses:
#- 192.168.0.102


accounts: #使用者資訊,預設配置了兩個使用者資訊。一個管理員使用者,一個普通使用者
- accessKey: rocket0001Mq #使用者名稱
  secretKey: 1234asdf 	  #密碼
  whiteRemoteAddress: #192.168.0.102
  admin: false
  defaultTopicPerm: DENY
  defaultGroupPerm: SUB
  topicPerms:
  - topicA=DENY
  - topicB=PUB|SUB
  - topicC=SUB
  groupPerms:
  # the group should convert to retry topic
  - groupA=DENY
  - groupB=PUB|SUB
  - groupC=SUB

- accessKey: rocketAdminMq  #使用者名稱
  secretKey: admin1234asdf  #密碼
  whiteRemoteAddress: #192.168.1.*
  # if it is admin, it could access all resources
  admin: true

透過官網文件我們可以看到配置說明

許可權說明:

plain_acl.yml 配置檔案中按照上述說明定義好許可權屬性後,接下來我們需要修改 broker.conf 配置檔案開啟ACL開關。官網文件上面也給了相關說明,參照官網配置即可。

編輯 vim broker.conf 檔案,在檔案末尾加入配置 aclEnable=true

#所屬叢集名字
brokerClusterName=DefaultCluster
#broker名字,叢集的時候不同的配置檔案填寫的不一樣,如果在這裡使用:broker-a,在另外一個使用:broker-b
brokerName=broker-a

#0表示Master,>0表示Slave
brokerId=0

#刪除檔案時間點,預設凌晨4點
deleteWhen=04

#檔案保留時間,預設48小時
fileReservedTime=48

#Broker角色  ASYNC_MASTER 非同步複製/SYNC_MASTER 同步雙寫
brokerRole=ASYNC_MASTER

##刷盤方式  ASYNC_FLUSH 非同步刷盤 SYNC_FLUSH 同步刷盤
flushDiskType=ASYNC_FLUSH

#nameServer地址,多個,分號分割
namesrvAddr=192.168.42.130:9876

#設定IP 公網Ip
brokerIP1=192.168.42.130

#允許Broker自動建立Topic
autoCreateTopicEnable=true

#Broker 對外服務的監聽埠
listenPort=10911

#開啟ACL安全認證
aclEnable=true

開啟後重新啟動 Broker 程式。重啟成功後,如果中間需要修改 plain_acl.yml 配置檔案,修改成功後,不需要重新啟動 BrokerStartup 重新了。ACL有自動過載機制,會自動載入已經修改的 plain_acl.yml 配置檔案。

5、rocketmq-dashboard 開啟認證

透過伺服器端開啟ACL後,在開啟MQ監控中心 rocketmq-dashboard 發現報錯了,已經連線不上mq伺服器了,這就說明ACL開啟成功了。報錯資訊 No accessKey is configured

[2024-05-17 11:53:30.956]  INFO create MQAdmin instance ClientConfig [namesrvAddr=192.168.42.130:9876, clientIP=192.168.1.4, instanceName=1715918010272, clientCallbackExecutorThreads=8, pollNameServerInterval=30000, heartbeatBrokerInterval=30000, persistConsumerOffsetInterval=5000, pullTimeDelayMillsWhenException=1000, unitMode=false, unitName=null, vipChannelEnabled=false, useTLS=false, language=JAVA, namespace=null] success.
[2024-05-17 11:53:31.149] ERROR Unexpected error occurred in scheduled task
java.lang.RuntimeException: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1  DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionLoader.validate(PlainPermissionLoader.java:189) BROKER: 192.168.42.130:10911
For more information, please visit the url, http://rocketmq.apache.org/docs/faq/
	at com.google.common.base.Throwables.propagate(Throwables.java:241)
	at org.apache.rocketmq.dashboard.task.DashboardCollectTask.collectTopic(DashboardCollectTask.java:161)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1  DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionLoader.validate(PlainPermissionLoader.java:189) BROKER: 192.168.42.130:10911

所以我們需要透過賬號密碼來連線mq伺服器,在rocketmq-dashboard 的配置檔案 application.properties 中新增賬號密碼資訊。

rocketmq.config.accessKey=rocketAdminMq
rocketmq.config.secretKey=admin1234asdf

新增配置成功後重新打包部署到伺服器。啟動成功再次訪問 rocketmq-dashboard

沒有報錯,啟動成功。

6、Java透過認證方式連線

RocketMq開啟ACL後,在不配置賬號密碼情況下,啟動專案傳送MQ訊息的時候也會報錯。報錯資訊如下:

2024-05-18 16:37:54.260 ERROR -[TaskUtils.java:95]- Unexpected error occurred in scheduled task
org.springframework.messaging.MessagingException: Send [3] times, still failed, cost [90]ms, Topic: blog_operation_sow, BrokersSent: [broker-a, broker-a, broker-a]
Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1  DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionManager.validate(PlainPermissionManager.java:403) BROKER: 192.168.42.130:9876

No accessKey is configured 透過報錯資訊顯示,需要配置賬號和密碼,所以需要配置ACL的連線資訊連線Mq伺服器傳送訊息。配置檔案新增資訊:

rocketmq: # rocketMQ配置
  # name server地址
  name-server: 192.168.42.130:9876
  producer:
    group: message_group
    # 傳送訊息超時時間,預設3000
    sendMessageTimeout: 10000
    # 傳送訊息失敗重試次數,預設2
    retryTimesWhenSendFailed: 2
    # 非同步訊息重試此處,預設2
    retryTimesWhenSendAsyncFailed: 2
    # 訊息最大長度,預設1024 * 1024 * 4(預設4M)
    maxMessageSize: 4096
    # 壓縮訊息閾值,預設4k(1024 * 4)
    compressMessageBodyThreshold: 4096
    # 是否在內部傳送失敗時重試另一個broker,預設false
    retryNextServer: false
    access-key: rocketAdminMq  # 擁有改 ‘message_group’組傳送許可權的使用者資訊
    secret-key: admin1234asdf # 密碼
  consumer:
    pull-batch-size: 10
    group: message_group
    access-key: rocketAdminMq # 擁有改‘message_group’組消費許可權的使用者資訊
    secret-key: admin1234asdf		# 密碼

配置成功後,測試訊息傳送資訊:

// 定時向Mq傳送資料
@Component
public class RocketStorage {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Scheduled(fixedDelay = 1000L * 60,initialDelay = 1000L * 20)
    public void store() {
        //String message = String.format("%s,%s,%s",value,type,timestamp);
        System.out.println("aaaaaa");
        rocketMQTemplate.convertAndSend("blog_operation_sow","aaaaaaaaa");
    }

}

消費者監聽接收資料:

@RocketMQMessageListener(consumerGroup = "message_group",topic = "blog_operation_sow")
public class RocketDataConsumer implements RocketMQListener {

    @Autowired
    @Qualifier("dataPersist")
    private IDataPersist dataPersist;

    @Override
    public void onMessage(Object o) {
        log.info("Operation RocketMq 接收到的資訊 . . . . . .:{}",o);
        dataPersist.put(o.toString(),1,System.currentTimeMillis());
    }
}

啟動專案檢視控制檯資訊,可以看到資料傳送和接收成功。

7、Java開啟認證踩坑說明

7.1 問題記錄

在配置檔案加入 access-keysecret-key 後,剛開始一直報 AclException: No accessKey is configured 錯誤,但是配置檔案中已經配置賬號密碼資訊了。不知道為什麼沒有生效。後來看了一下引入的Maven依賴版本為:

        <!--RocketMQ-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.2.1</version>
        </dependency>

透過IDEA檢視依賴jar包發現引入的RocketMq依賴版本高了。

透過上圖可以看到,我們引入的客戶端版本是4.9.1版本,但是伺服器目前部署的版本是4.4.0。然後以為是maven依賴引入的版本太高了,就把rocketMq依賴降到了4.4.0版本。maven依賴如下:

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>

再次透過IDEA檢視客戶端依賴,發現版本已經改為4.4.0了

修改maven依賴成功後,再次啟動專案。以為這次會啟動成功,但是還是啟動失敗了。版本問題已經解決了,就不是版本問題了。後來看了下相關問題說明。發現RocketMq是在4.4.0版本才開始有ACl認證的,可能是這個版本客戶端不支援透過yaml 配置檔案配置ACl的賬號密碼資訊。需要手動進行編寫Java配置檔案進行傳送訊息。然後我就直接放棄了這種方法,直接升級伺服器RocketMq版本從4.4.0升級為4.9.1。

7.2 升級版本

既然決定升級伺服器RocketMq版本資訊了,那就開幹。有了之前的安裝經驗,這次也很好安裝。首先在官網下載RocketMq的4.9.1版本。地址:https://rocketmq.apache.org/download 下載成功後上傳伺服器到rocketMq目錄下。

進入rocktmq-4.9.1目錄,按照之前的步驟進行操作即可。先修改啟動指令碼,先備份在修改。進入 bin 目錄下開始備份。

cp runserver.sh runserver.sh.init.bak 

cp runbroker.sh runbroker.sh.init.bak 

修改JVM引數即可。備份成功後,然後在進入 conf 目錄,修改配置檔案資訊並開啟ACL配置,如何開啟ACL和上面操作一致。我們也可以備份一下 broker.confplain_acl.yml 檔案,把在rocketmq-4.4.0目錄裡面的配置資訊直接複製到 rocketmq-4.9.1目錄下面。複製成功後,給需要給配置檔案授可執行許可權。

chmod +x broker.conf plain_acl.yml

接下來就可以啟動rocketmq了,按照之前方式啟動即可。先啟動 namesrv 在啟動 broker

nohup sh bin/mqnamesrv -n 192.168.42.130:9876 > /dev/null 2>&1 &  

nohup sh bin/mqbroker -n 192.168.42.130:9876 -c conf/broker.conf autoCreateTopicEnable=true >/dev/null 2>&1 &

啟動成功後,版本就升級成功了。由於rocketmq預設採用持久化儲存,當使用持久化儲存模式時,訊息會被寫入磁碟,並儲存在指定的儲存路徑下。預設情況下,儲存路徑為$HOME/store也可以透過配置檔案進行修改。在儲存路徑下,RocketMQ會根據一些規則和目錄結構來組織訊息儲存檔案。其中,訊息資料檔案commitlog儲存在$HOME/store/commitlog目錄下,而消費進度檔案 consumequeue 儲存在$HOME/store/consumequeue目錄下。由於有持久化儲存,所以原來的資料也不會丟失。

7.3 檢視監控

由於RocketMq的配置檔案還是採用之前的,所以不需要改動 rocketmq-dashboard 可以直接訪問地址。檢視叢集資訊:

從上圖version 版本可以看出當前版本為 4.9.1 說明已經連線升級成功了。可以檢視監控資料:

至此,RockeMq伺服器版本升級完畢。

8、總結

透過以上方式,RocketMq安全措施就配置成功了。這是我自己在使用RocketMq的搭建過程,分享出來讓大家少走彎路,中間也許會有一些地方考慮不周,歡迎各位指點。感謝大家閱讀。

公眾號文章連結:https://mp.weixin.qq.com/s/XTB9rrtpAh5q9QI6LkqSEw 如果文章對你有所幫助,歡迎大家點個推薦和關注。

相關文章