背景html
在衆多開源緩存技術中,Redis無疑是目前功能最爲強大,應用最多的緩存技術之一,參考2018年國外數據庫技術權威網站DB-Engines關於key-value數據庫流行度排名,Redis暫列第一位,可是原生Redis版本在安全方面很是薄弱,不少地方不知足安全要求,若是暴露在公網上,極易受到惡意攻擊,致使數據泄露和丟失。git
本文主要是在原生開源軟件Redis3.0基礎上,系統的在安全特性方面進行的加強,不少加強點涉及了開源代碼的修改,後續章節闡述的Redis緩存數據庫的安全規範, 理論上適用於全部應用Redis的產品。github
本系列共連載三篇,分九個章節,本文從合法監聽接口,未公開接口,訪問通道控制三個章節闡述了Redis緩存數據庫加固措施redis
安全問題:Redis Server監聽的端口默認爲6379,容易被掃描攻擊。算法
解決方案:修改成非默認端口,並在端口矩陣中說明。sql
安全問題:Redis支持監聽0.0.0.0。數據庫
解決方案:由於若是有多網卡,應該將監聽地址設置爲只有數據庫客戶端須要鏈接的網卡地址。若是隻容許本機訪問,應該只監聽127.0.0.1。緩存
安全問題:官方RedisCluster方案缺省會增長一個集羣端口,且是在客戶端端口偏移10000,這個問題很是隱蔽。安全
解決方案:在端口矩陣中對額外的這個集羣端口有說明。修改源碼,新增一個redis.conf偏移量配置項cluster-port-increment,缺省配置+1,這樣能夠作到端口範圍可控,避免衝突。服務器
安全問題:Redis只有一個超戶,權限過大。
解決方案:權限最小化原則,增長配置項,角色區分超戶,普通用戶和只讀用戶三種。
角色 |
redis.conf對應配置項 |
權限說明 |
超戶 |
requirepass |
全部功能。 |
普通用戶 |
requireuserpass |
不能進行管理類命令,如shutdown等 |
只讀用戶 |
requirereaduserpass |
在普通用戶基礎上,進一步限制只能進行讀操做。沒有script命令權限。 |
普通用戶不能進行的操做有:
命令 |
解釋 |
save |
SAVE 命令執行一個同步保存操做,將當前Redis 實例的全部數據快照(snapshot) 以RDB 文件的形式保存到硬盤。 |
bgsave |
在後臺異步(Asynchronously) 保存當前數據庫的數據到磁盤。 |
bgrewriteaof |
執行一個AOF 文件重寫操做。重寫會建立一個當前AOF 文件的體積優化版本。即便BGREWRITEAOF 執行失敗,也不會有任何數據丟失,由於舊的AOF 文件在BGREWRITEAOF 成功以前不會被修改。 |
shutdown |
中止全部客戶端 若是有至少一個保存點在等待,執行SAVE 命令 若是AOF 選項被打開,更新AOF 文件 關閉redis 服務器(server) |
sync |
用於複製功能(replication) 的內部命令。 |
psync |
用於複製功能(replication) 的內部命令。 |
replconf |
暫無用處 |
monitor |
實時打印出Redis 服務器接收到的命令,調試用。 |
slaveof |
SLAVEOF 命令用於在Redis 運行時動態地修改複製(replication) 功能的行爲。 |
debug |
調試命令 |
config |
配置參數 |
restore |
反序列化給定的序列化值,並將它和給定的key 關聯。 |
migrate |
將key 原子性地從當前實例傳送到目標實例的指定數據庫上,一旦傳送成功,key 保證會出如今目標實例上,而當前實例上的key 會被刪除。 |
dump |
序列化給定key ,並返回被序列化的值,使用RESTORE 命令能夠將這個值反序列化爲Redis 鍵 |
安全問題:經過在redis-cli指定-a參數,密碼會被ps出來,屬於敏感信息。
解決方案:修改Redis源碼,在main進入後,當即隱藏掉密碼,避免被ps出來。(可參考開源Mysql代碼)
對於需在現網維護階段使用的命令/參數、端口等接入方式(包括但不限於產品的生產、調測、維護用途),需經過產品資料等向客戶或監管機構公開或受限公開。
安全問題: redis-cli訪問參數帶密碼敏感信息,會被ps出來,也容易被系統記錄操做日誌。
解決方案:改成經過API方式(Python可使用redis-py)來安全訪問,禁止經過sudo方式切換到dbuser帳號使用redis-cli。
重現條件:能夠經過iptables禁掉redis端口來模擬重現。
安全問題:Redis原生認證存在重放攻擊:只是簡單的交互一次auth xxx
解決方案:採用預共享祕鑰(對稱加密算法+隨機數的雙向認證),同時在方案設計上作到最大限度兼容,讓客戶端改形成本最小,目前平臺配套目前支持客戶端有:Java,Python,C,Lua。
方案設計以下:
Redis認證協議變動,其中auth命令區分兩種功能,經過首字母區分:
auth命令含義 |
區分 |
認證第一階段:客戶端傳遞隨機數 |
請求:auth <RAND_C 響應:-ERR >TokenBA |
認證第二階段 |
auth >TokenAB |
預共享祕鑰認證時序圖
說明:Redis爲文本協議, 安全隨機數長度固定爲32字節的可顯示字符串,鏈接2個隨機數的分隔符爲」@」。
主要認證流程:
1.客戶端向服務端執行命令: auth <RAND_C
1) 首字母<表示是認證第一階段。(便於服務端從協議層區分)
2) RAND_C表示客戶端生成安全隨機數。
2.服務端產生響應錯誤回覆
1) 獲取RAND_C,並生成RAND_S
2) 產生TokenBA=AES128(RAND_S@RAND_C)
3) 響應錯誤回覆:-ERR >TokenBA
說明:錯誤描述爲服務端生成的安全隨機數。
3.客戶端驗證
1) 驗證TokenBA是否合法
解密出RAND_S@RAND_C,看看RAND_C是不是本身生成的隨機數
2) 客戶端產生TokenAB=AES128(RAND_C@RAND_S@dbname@ossdbuser@pwd)
3) 調用認證接口: auth >TokenAB
4.服務端認證
1) 驗證TokenAB是否合法
解密出RAND_C@RAND_S,看看RAND_S是不是本身生成的隨機數
2) 驗證用戶和密碼合法性: dbname@ossdbuser@pwd
安全問題:Redis沒有庫名,系統若是隻經過用戶名+密碼,容易猜想和攻擊。
解決方案:經過認證時帶上庫名, 由於每一個服務的庫名都配置不一樣,增長攻擊複雜度, 認證格式以dbname@dbuser@pwd區分。
安全問題:Redis也是一種數據庫服務,通常一個進程佔用一個端口,集羣還會額外多佔用一個端口。
解決方案:在端口矩陣寫明系統申請的Redis端口範圍。
安全問題:原生Redis沒有限制客戶端認證超時時間,存在慢攻擊。
解決方案:修改源碼,限制在60秒內認證成功,不然服務器將主動斷開鏈接。
說明: 控制完成客戶端認證的時間上限。這能夠防止無效客戶端長時間佔用鏈接通道。
安全問題:增長SSL通訊能夠提升數據傳輸的安全。
解決方案:
1.不改動官方源碼,經過在客戶端和服務端部署SSL Proxy,相似stunnel。
2.支持SSL可配置,涉及開源代碼修改。
說明:由於Redis屬於交互密集型,每秒處理幾萬次請求,支持SSL後性能會有比較大損失。
安全問題:目前Redis沒有ACL控制。
解決方案:
1. 目前基於平臺共享祕鑰,其中祕鑰是隨機生成,每套系統不同,間接也作到了IP範圍控制。
2. 經過iptables控制進一步限制接入IP範圍。
3. 若是要具體控制到用戶+IP級別,相似Mysql認證。做者antirez已經意識到這個問題,有望在將來版本提供,連接以下:Multi users AUTH and ACLs for Redis
安全問題:官方推薦Java客戶端Jedis集羣最新版還不支持認證。
解決方案:增長認證參數,與服務端共享祕鑰認證保持一致。
安全問題:Jedis認證接口密碼爲參數string。
解決方案:Jedis客戶端認證新增一套char[]接口。
1. RedisCluster多主多從,內部高度自制,所以Redis的認證masterauth須要加密保存到配置文件。
2.配置集羣關係時,基於Gossip協議,Cluster meet須要有認證保護。