dubbo與zookeeper權限關聯


一、背景

在日常生產中最常用使用zookeeper作為dubbo注冊中心使用,但是經常在使用過程中,由於安全掃描,出現zookeeper未授權訪問漏洞,需要對zookeeper節點添加權限,但是dubbo至今沒有增加zookeeper權限控制功能,所以需要自己改造源碼實現。

二、zookeeper簡單介紹

zookeeper是分布式服務架構,主要用來解決分布式應用中經常遇到的一些數據管理問題,比如:統一命名服務、狀態同步服務、集群管理、分布式應用配置項的管理等。

zookeeper上節點最常用的5種操作權限:

Create、Read、Write、Delete、Admin也就是增、刪、改、查、管理權限,簡寫crwda

(這五種權限中,delete是指對子節點刪除權限,其他四種權限指本身節點權限)

身份驗證有4中方式:

  • world:有個單一的ID,anyone,表示任何人。
  • auth:不使用任何ID,表示任何通過驗證的用戶(是通過ZK驗證的用戶?連接到此ZK服務器的用戶?)。
  • digest:使用 用戶名:密碼
    字符串生成MD5哈希值作為ACL標識符ID。權限的驗證通過直接發送用戶名密碼字符串的方式完成,
  • ip:使用客戶端主機ip地址作為一個ACL標識符,ACL表達式是以 addr/bits
    這種格式表示的。ZK服務器會將addr的前bits位與客戶端地址的前bits位來進行匹配驗證權限。

看到了授權需要的模式是secheme🆔perm形式,下面就說說secheme

secheme介紹

  • world表示所有。創建節點的默認權限,有唯一的id是anyone授權的時候模式為world:anyone:rwcda
    表示所有人都有對這個節點的rwcda權限。這里用的是id,而不是expression。
  • auth不需要id。不過這里應該用expression來表示。
  • digest使用用戶名:密碼編碼成md5的方式作為訪問權限列表id。但是這里id不作為授權語句的一部分,這里也是用expression方式。用戶名:密碼先進行shal編碼后再用base64編碼。這個比較惡心。
  • host使用用戶主機作為訪問空着列表的id。但是這里需要注意的是表達式用的主句的后綴即可。舉個栗子:如果表達式設置為
    corp.com 可以匹配 host1.corp.com 和
    host2.corp.com的主機名,但是host1.zookeeper.com則不能匹配。
  • ip:跟主機名類似。這里使用客戶端的ip地址作為權限訪問列表的id。表達式可以用
    addr/bits這種方式設置ip白名單。

常用加密命令:

方法一、auth設置權限

  • 設置這個權限之前首先需要

addauth digest zookeeper:zookeeper

  • 然后再設置auth

setAcl /test auth:zookeeper:zookeeper:crwda

  • 檢查權限

getAcl /test

  • 可以看到權限已經設置成功了。

get /test

方法二、digest設置權限 (這個里面有個大坑)

可以看出比較明顯的:

  1. 設置之前不需要通過addauth添加對應的授權認證,而是直接授權便可。
  2. 命令行設置了什么,然后在獲取對應的權限的時候就會把對應的字符串顯式記錄下來,而不會進行任何編碼,
    如上面的zookeeper:zookeeper。這種方式就需要自己去編碼了。
  3. 這也是個比較坑爹的事情,設置密碼之前需要把密碼先自己進行sha1編碼然后吧結果進行base64編碼。如果編碼的方式錯誤你將永遠失去這個節點的訪問權。不編碼就訪問不了

使用sha1編碼和base64編碼之后設置digest方式保存起來

之后就可以使用addauth的方式訪問啦

使用代碼連接創建帶權限的zookeeper節點

創建節點數據時:

讀取Zookeeper數據時:

三、dubbo如何使用zookeeper作為注冊中心

通常使用dubbo一般有四種方式,xml配置、API調用、properties加載、注解配置。使用zookeeper作為注冊中心主要配置如下:

  1. xml schema擴展

  1. properties配置

  1. API代碼設置

  1. 注解配置

四、dubbo實現zookeeper權限關聯

最近又把dubbo拾起來啦,以前用過dubbo,后來12年阿里巴巴不維護啦,后來隨着springcloud的不斷崛起,使用dubbo的人越來越少,但是在國內還是有好多dubbo的熱愛着,也是因為這樣,在2017年的時候阿里將dubbo奉獻給Apache社區,后面估計會越來越好。

這個無論是之前阿里維護還是現在放到Apache社區,直到目前為止,dubbo都沒做好這塊,使用zookeeper加權限連接,其實挺簡單的,下面大致講以下怎么做。

這里做之前先說一下實現dubbo連接加權限的zookeeper有兩種方式,這個取決於dubbo連接zookeeper是通過兩種客戶端連接的,分別是zkclient和curator,而且dubbo提前預留量注冊中心變量設置用戶名和密碼,這里使用的zookeeper加權方式是digest方式,使用用戶名和密碼方式對zookeeper節點加權限。

這里需要注意的是,自從dubbo轉到Apache下面之后,源碼改動不少,其中在dubbo
2.6.0以后版本,dubbo將默認使用zkclient訪問zookeeper改成了默認使用curator客戶端訪問
而且在2.5.4版本之后將com.github.sgroschupf 下面的zkclient 0.1版本改成了
com.101tec 下面的zkclient 0.2版本啦。

1、改造zkclient客戶端dubbo源碼實現

  • 替換zkclient jar包

這里無論是新版本還是舊版本,都需要將zkclient包替換成com.101tec
的0.5以上版本
,因為只有0.5以上的版本才支持ACL加權控制。(本人建議使用0.8以上的版本)

如果你是2.5.4以前的版本(包括2.5.4版本,就是12年之后17年之前發布的最新版本)需要將

替換成

(這個之前版本比較麻煩,需要到源碼中將所有的pom都需要修改)

如果你是使用2.5.4以后的版本比較簡單,只需要將dubbo-parent中的

<zkclient_version>0.2</zkclient_version>

改成

<zkclient_version>0.8</zkclient_version>

  • dubbo使用zkclient客戶端源碼解析

這里簡單的介紹也一下dubbo連接Zookeeper的實現原理,首先服務的提供者和消費者在RegistryProtocol利用注冊中心暴露(export)和引用(refer)服務的時候會根據配置利用Dubbo的SPI機制獲取具體注冊中心注冊器

這里的RegistryFactory是ZookeeperRegistryFactory看如下工廠代碼

在這里創建zookeepr注冊器ZookeeperRegistry。

ZookeeperTransporter是操作zookeepr的客戶端的工廠類,用來創建zookeeper客戶端,這里客戶端並不是zookeeper源代碼的自帶的,而是采用第三方工具包,主要來簡化對zookeeper的操作,例如用zookeeper做注冊中心需要對zookeeper節點添加watcher做反向推送,但是每次回調后節點的watcher都會被刪除,這些客戶會自動維護了這些watcher,在自動添加到節點上去。

  • dubbo源碼改造適配zookeeper添加ACL權限

這里又要分版本對待,對dubbo添加zookeeper權限適應於2.2.0-2.5.6版本之間dubbo使用者,2.5.6之后版本添加了ZkClientWrapper類,對zkclient又做成守護線程形式,需要進一步改造,后面也會專門提高2.5.6之后怎么改造的。

適配2.2.0-2.5.6版本之間dubbo源碼改造

  1. 在使用zkClient
    連接Zookeeper中最重要的一個類是ZkclientZookeeperClient,Zookeeper的連接、節點創建和節點訪問都在這個類中,我們需要重點改造的類。

  1. ZkclientZookeeperClient在構造函數中創建連接Zookeeper,在連接的時候使用用戶名密碼連接:

  1. 將ZkclientZookeeperClient中的“createPersistent(String
    path)”和“createEphemeral(String path)”創建節點設置權限:

到目前為止,源碼就改動這么多,連接Zookeeper的用戶名和密碼通過dubbo配置注冊中心的時候配置,通過spring加載代URL中。
然后下面就說說具體怎么配置怎么用。

  1. 改造后的dubbo連接Zookeeper配置

從 2.2.0 版本開始缺省為 zkclient 實現,以提升 zookeeper 客戶端的健狀性,配置:

<dubbo:registry ... client="zkclient" username="admin" password="admin" />

dubbo.registry.client=zkclient

dubbo.registry.username=admin

dubbo.registry.password=admin

zookeeper://10.20.153.10:2181?client=zkclient&username=admin&password=admin

到此直接啟動即可,dubbo就可自動對注冊dubbo的group節點添加ACL權限。

適配2.5.6以上版本dubbo源碼改造

  1. 添加handleSessionEstablishmentError監控方法

  1. 重寫ZkClientWrapper構造方法

  1. 針對client.start();設置權限登錄

  1. 修改ZkClientWrapper類中“createPersistent(String
    path)”和“createEphemeral(String path)”創建節點設置權限:

到目前為止,源碼就改動這么多,連接Zookeeper的用戶名和密碼通過dubbo配置注冊中心的時候配置,通過spring加載代URL中。
然后下面就說說具體怎么配置怎么用。

  1. 改造后的dubbo連接Zookeeper配置

從 2.2.0 版本開始缺省為 zkclient 實現,以提升 zookeeper 客戶端的健狀性,配置:

<dubbo:registry ... client="zkclient" username="admin" password="admin" />

dubbo.registry.client=zkclient

dubbo.registry.username=admin

dubbo.registry.password=admin

zookeeper://10.20.153.10:2181?client=zkclient&username=admin&password=admin

到此直接啟動即可,dubbo就可自動對注冊dubbo的group節點添加ACL權限。

2、改造curator客戶端dubbo源碼實現

改造curator是最簡單的方式,因為dubbo使用curator已經考慮到zookeeper加ACL了,只是代碼設置不生效罷了,只要稍微動一下即可。

  1. 修改CuratorZookeeperClient源碼

  1. 改造后的dubbo連接Zookeeper配置

從 2.6.0 版本開始缺省為 curator 實現,以提升 zookeeper 客戶端的健狀性,配置:

<dubbo:registry ... client="curator" username="admin" password="admin" />

dubbo.registry.client=curator

dubbo.registry.username=admin

dubbo.registry.password=admin

zookeeper://10.20.153.10:2181?client=curator&username=admin&password=admin

啟動之后即可實現對zookeeper添加權限控制啦。

至此源碼已經全部修改完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM