在前文[15分鐘從零開始搭建支持10w+用戶的生產環境(二)]中提了一句MongoDB的安全,有小伙伴留心了,在公眾號后臺問,所以今天專門開個文,寫一下關于MongoDB的安全,
一、我的一次MongoDB被黑經歷
近幾年,MongoDB應用越來越多,MongoDB也越來越火,
從2015年開始,MongoDB被一些「非法組織/黑客」盯上了,他們的做法也很簡單,連到你的資料庫上,把你的資料拿走,然后把你的庫清空,留一個訊息給你,索要位元幣,
跟最近流行的勒贖病毒一個套路,
我在某個云上有一臺服務器,主要用來做各種研究和測驗,隨時可以格了重裝的那種,上面跑著一個MongoDB,是用默認的引數簡單啟動的一個單實體,
早上起來,跑程式測驗時,程式直接報錯,
跟蹤代碼,發現是頭天寫進去的資料不見了,
進到資料庫,發現資料庫都在,但里面的表全被清空了,多了一個Readme的表,查看這個表的內容:
> db.Readme.find().pretty()
{
"_id" : "5c18d077fd42b92d8f6271c3",
"BitCoin" : "3639hBBC8M7bwqWKj297Jc61pk9cUSKH5N",
"eMail" : "[email protected]",
"Exchange" : "https://localbitcoins.com",
"Solution" : "Your database is downloaded and backed up on our secured servers. To recover your lost data: Send 0.2 BTC to our BitCoin address and Contact us by eMail with your server IP address and a proof of Payment. Any eMail without your IP address and a proof of Payment will be ignored. Your are welcome!"
}
簡單來說,這是一個通知:你的資料被我們綁架了,想要贖回去,需要0.2個位元幣,
一身冷汗,如果這是一個生產環境,如果這是一個系統的運營資料,后果不堪設想,
究其原因,這個資料庫在啟動時,用了默認的引數,未加任何防護,
所以,
一定不要用默認的設定運行MongoDB資料庫!
一定不要用默認的設定運行MongoDB資料庫!
一定不要用默認的設定運行MongoDB資料庫!
二、安全實踐
1. 修改埠
MongoDB啟動時,使用了幾個默認的埠:
27017: 用于一般的單實體(mongod),或者集群中路由服務器(mongos)
27018: 用于集群中的分片服務器
27019: 用于集群中的配置服務器
實際布署時可以把默認埠換成別的埠,
命令列:
$ ./mongod --port port_number
組態檔:
port=port_number
2. 系結IP
這個要區分一下MongoDB的版本,
查詢MongoDB版本的命令:
$ ./mongod --version
在MongoDB Version 3.6之前,MongoDB啟動時默認系結到服務器的所有IP上,換句話說,通過所有的IP都可以訪問資料庫,這兒的安全隱患在于外網IP,
在3.6之后,MongoDB啟動默認系結127.0.0.1,從外網無法訪問,去掉了這個隱患,
設定系結IP,命令列:
$ ./mongod --bind_ip your_ip #單IP系結
或
$ ./mongod --bind_ip your_ip1,your_ip2 #多IP系結
組態檔:
bind_ip=your_ip #單IP系結
或
bind_ip=your_ip1,your_ip2 #多IP系結
MongoDB還提供了一個一次系結所有IP的引數,命令列:
$ ./mongod --bind_ip_all
組態檔:
bind_ip_all=true
另外,系結時,your_ip也可以換成域名your_host,效果是一樣的,
在生產環境中,出于安全的需要,通常可以設定資料庫系結到服務器的內網IP,供資料層操作資料庫就好,如果有特殊需要,可以臨時系結到外網IP,操作完成后再去掉,
資料庫切換系結IP和埠,對資料庫本身沒有任何影響,
3. 資料庫服務器內部身份認證
資料庫服務器的內部身份認證,是更高一個層次的安全策略,用于保證主從/復制集/集群中各個資料庫服務器的安全合法接入,
內部身份認證,首先需要有一個數字密鑰,
數字密鑰可以使用機構簽發的證書來生成,也可以使用自生成的密鑰,
當然在低安全級別的情況下,你也可以隨手寫一個密鑰來使用,
自生成密鑰的生成命令:
$ openssl rand -base64 756 > path_to_keyfile
然后設定密鑰檔案的讀寫權限:
$ chmod 400 path_to_keyfile
看一下密鑰檔案:
$ ls -l
-rw-r--r-- 1 test test 1024 5 10 17:51 test.key
下面,為資料庫啟用密鑰檔案,命令列:
$ ./mongod --keyFile path_to_keyfile
組態檔:
keyFile=path_to_keyfile
注意:
-
內部認證用在多于一個服務器的情況,例如:主從/復制集/集群上,做服務器之間的互相認證,單個服務器可做可不做,實際上無效,
-
內部認證要求認證的服務器使用相同的密鑰檔案,也就是說,所有的服務器使用同一個密鑰檔案,
-
密鑰檔案有安全要求,檔案權限必須是400,否則資料庫啟動時會有報錯,
4. 用戶和角色鑒權
MongoDB支持為資料庫創建用戶和分配角色,用用戶和角色來管理和使用資料庫,
MongoDB創建用戶操作和上面不同,上邊的內容,是在資料庫運行以前進行,而創建用戶,是在資料庫運行以后,
$ ./mongo your_ip:your_port
> use admin
switched to db admin
> db.createUser({"user" : "user_name", "pwd" : "user_password","roles" : [{"role" : "userAdminAnyDatabase", "db" : "admin"}]})
Successfully added user: {
"user" : "user_name",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
這樣我們就加入了一個用戶,
MongoDB內建的角色分以下幾類:
- 超級用戶:root
- 資料庫用戶角色:read、readWrite
- 資料庫管理角色:dbAdmin、dbOwner、userAdmin
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
- 可操作所有資料庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 備份、恢復角色:backup、restore
角色不詳細解釋了,角色名稱的英文寫的很明白,
在實際操作中,通常會將用戶建在admin中,用roles里的db來指定用戶可以使用或管理的資料庫名稱,
通過這一通操作,我們已經在資料庫中創建好了用戶,下面需要服務器啟用鑒權,
命令列:
./mongod --auth
組態檔:
auth=true
這個用于mongod啟動的資料庫,對于集群的router,即mongos,會默認啟用auth,所以不需要顯式啟用,
當MongoDB啟用鑒權后,再用mongo客戶端連接資料庫,就需要輸入用戶帳號資訊了,
$ ./mongo -u user_name -p user_password your_ip:your_port/admin
或
$ ./mongo -u user_name -p your_ip:your_port/admin #提示輸入密碼
同樣,在代碼中,資料庫連接串也同步變成了:
"MongoConnection": "mongodb://user_name:user_password@localhost:27017/admin?wtimeoutMS=2000"
三、總結
一般來說,做完上面的安全處理,就可以完全滿足生產環境的安全要求了,
再高的要求,可以通過啟用TLS來強化,這會是另一個文章,
![]() |
微信公眾號:老王Plus 掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送 本文著作權歸作者所有,轉載請保留此宣告和原文鏈接 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/4609.html
標籤:NoSQL
上一篇:Redis 持久化詳解
下一篇:Redis學習筆記(二) 鏈表

