網站安全性,其中一個是擁有安全的備份檔案,尤其是資料庫的費份,包含了帳號、密碼雜湊、使用者個資等,更應該注重安全性。該備份不應明碼儲存,更不應放在同一臺主機上的 web 權限可以取得之處,以免網站被攻破時,連帶將你的備份帶走保存;甚至刪除你的原始備份,這樣就完全沒有備份的效果了。
因此,實現備份時,種種顧慮下,第一步一定是將備份的檔案正確的加密,我們建議使用非對稱金鑰來實現這樣的工作,因為非對稱金鑰可以讓系統自動備份時,使用可以公開的公鑰進行檔案加密,就算被竊取走,也不用擔心備份的檔案被解密。需要解密時,使用僅存於少數人中的私鑰解密,讓加密備份安全無虞。
1. 產生非對稱金鑰
使用 Linux 環境,可以使用 OpenSSL 來達成此工作。先使用以下指令產生非對稱金鑰:
openssl req -x509 -nodes -newkey rsa:2048 -keyout private.key -out public.key
該金鑰如前述,public.key 要儲存於伺服器中, private.key 則是存在真正有權限的使用者安全處。
2. 進行資料庫備份
如果使用 MariaDB,我們推薦使用 Markabackup 來進行資料庫的備份,比起傳統的 mysqldump,mariabackup 支援熱備份,且對網站的造成影響較小,不會讓資料庫在備份過程中斷線,詳細可以參考比較。一般來說,備份全部的檔案,用以下指令即可:
mariabackup --user=your_backup_account --password=your_password --backup
然而,有些撇步要注意,上述的指令,是將整個資料庫檔案一一備份,出來的是一個跟現有資料庫一樣的資料夾。然而,為了壓縮、上傳和加密方便,我們希望跟 mysqldump 一樣,可以備份為一整個檔案,不要備份程一個資料夾,mariabackup 提供了以下指令作業:
--stream=xbstream
若加上 pipe ,壓縮、輸出成一個檔案,以下是完整的資料庫備份指令,將整個資料備份用 stream 方式輸出到 /tmp/mydb.backup.gz 這個檔案。因為用 stream,所以可以用 gzip 壓縮
mariabackup --user=your_backup_account --password=your_password --backup --stream=xbstream | gzip > /tmp/mydb.backup.gz
3. 將備份檔案加密
OpenSSL 是 Linux 常用來加密使用的工具,其中支援了一個非對稱加密標準: S/MIME ,並且可以指定加密的演算法。S/MIME 這樣的封裝,因為原先是設計給電子郵件訊息加密,因此支援大檔案的加密,不過以我們的備份檔案中,不是針對文字加密,所以要用 -binary 這個參數,整體的指令長這樣:
openssl smime -encrypt -binary -aes256 -in /tmp/mydb.backup.gz -out /tmp/mydb.backup.enc -outform DER public.key
可以注意到,-aes256 是使用的演算法,以及指定輸出的格式為 DER。
然而這樣的指令有一個問題,當碰到檔案很大時,openssl 的「-in 」會將整個檔案讀到記憶體後再進行加密,如果整合上述的 Mariabackup,會讓整個資料庫備份讀到記憶體。一來中間仍是有明碼儲存的斷點,另一來也會讓伺服器的記憶體負擔過高。
4. 將備份、加密指令組合
備份和加密,其實可以是一整串組合,關鍵在於加密是否可以用 pipe 來 stream 讀取。好在 OpenSSL S/MIME 的方式,提供了一個可以串流 binary 進來加密的參數「-stream」。整體組合起來,檔案是這樣子:
mariabackup --user=your_backup_account --password=your_password --backup --stream=xbstream | gzip | openssl smime -stream -encrypt -binary -aes256 -out mydb.backup.gz.enc -outform DER public_key.pem
這樣一來,可以將備份直接串流在記憶體加密,寫進磁碟中了,不用擔心中間還有儲存一段明文的歷程。
5. 解密、還原的提示
使用 mbstream -x 來解密串流的整個檔案,解出來的會是一個可以運行的 MariaDB 資料庫資料夾。將檔案和資料夾的 user / owner 改成 mariadb 的 running user,替換現有的資料庫目錄,即可正確運作。整體的指令如下:
cd your_restore_dir openssl smime -decrypt -binary -inform DEM -inkey private.key -in mydb.backup.gz.enc -binary | gunzip -c | mbstream -x chown -R mysql /your_restore_dir