基於ZFS和GnuPG的安全遠程備份方案

需求及方案

這事的需求是這樣的,公司服務器上有一些數據需要備份,主要是數據庫和一些共享文件,早年是通過磁帶機備份,然後離線保存磁帶實現的,但是這個方法實在是很麻煩,而且用了幾年以後,一盤磁帶已經裝不下所有備份了,再說那個老型號的磁帶機已經過保可以報廢了,所以前年的時候重新搞了一個遠程備份方案,用了一年多,基本靠譜,最近稍微調整一下順便作個記錄。

基本方案是這樣:

在本地備份服務器上將所有數據壓縮打包加密,通過互聯網傳到遠程服務器上保存。因爲遠程服務器在外地分公司那邊,那邊的同事是沒有權限訪問這些備份數據的,而且那邊的機房環境也不能保障安全,加上傳輸過程是通過互聯網,所以數據安全是很重要的。

雖然通過rsync over SSH可以解決互聯網傳輸中的安全問題,但遠程保存的安全性還是需要保證,所以加密是必須的。

具體實現

首先是本地備份服務器的搭建。

因爲源數據都是需要被Windows訪問的,所以這個備份服務器必須是可以通過網絡被Windows使用的。因爲原本共享數據就是在FreeBSD上通過Samba提供的,所以最初的備份方案中也是讓備份服務器通過共享給數據庫服務器,讓它備份過來,但是在Windows上這麼搞其實是很麻煩的(因爲默認的system用戶不能訪問共享)。

後來因爲搞了這個《用FreeBSD10搭建基於ZFS的iSCSI服務 》,所以現在是通過iSCSI來爲Windows提供存儲服務,比共享好得多,而且高版本的Windows自帶Initiator,用起來還是相當方便的。

之所以要用FreeBSD做備份,當然是因爲ZFS。我討厭Windows那個垃圾說過了很多次了,除了業務應用必須用Windows以外,我都換成了FreeBSD或Linux——比如遠程備份服務器就是CentOS,這是因爲分公司那邊的IT同事除了Windows就只會這個,不然我肯定也是要搞成FreeBSD的。

本地備份系統結構大體如下:

共享服務器(FreeBSD+ZFS+Samba) <=> 備份服務器(FreeBSD+ZFS+iSCSI) <=> 業務服務器(Windows)

共享服務器通過Samba共享出一個ZFS,這個ZFS啓用dedup以節約空間改善性能(啓用壓縮當然更節約一些,但性能有影響)。本機上通過對ZFS做每日快照實現本地快速備份。每週將最新快照完全打包發送到備份服務器(內網rsync)。

備份服務器上通過iSCSI向業務服務器提供一個ZFS,這個ZFS啓用壓縮以節約空間,因爲某弱智數據庫備份時都不會做壓縮的(不知道新版本有沒有改過),業務服務器將這個ZFS格式化爲一個NTFS盤做備份盤,然後數據庫每週做完全備份,每天做增量備份,都放在這個備份盤裏。

備份邏輯是這樣,因爲數據量太大,遠程備份需要時間很長,只能放在週末,每週執行一次,每日備份如上面所說,只在本地進行。

所以,每週在共享備份和數據庫備份完成以後,備份服務器對那個備份用的iSCSI ZFS作快照,並完全打包與共享備份的打包的快照文件一起加密後發送到遠程服務器。因爲是在本地加密,遠程服務器沒有密鑰,無法知道備份文件的內容,只能簡單保存文件。即使有人非法獲得這個打包的備份文件也無法解密出其中內容。

恢復備份的方法是這樣:

萬一本地系統完全故障或受到不可抗力災害,可以立即在一臺新安裝的FreeBSD服務器上把備份文件從遠程服務器上傳回來,再用備份的密鑰解密,再恢復出兩個ZFS快照(一個Samba共享,一個iSCSI target,前者可以直接訪問其中的文件,後者需要通過Initiator連接並mount爲NTFS盤),即可恢復原來的備份內容。

至於本地的日常恢復就更簡單了,直接回滾或克隆一下快照即可。

附:應對加密病毒的大殺器——ZFS快照

去年有個厲害的病毒叫CryptoLocker,它的做法是感染後用高強度加密你Windows電腦裏的所有文件(當然包括可以通過共享訪問到的),杯具在於因爲文件還在,你無法通過恢復被刪除文件的方式找回,但是因爲被加密,你也無法打開,結果就是除了給對方付錢取得解密私鑰以外,沒有其它辦法——除非有備份。

但是備份也有困難,一般來說除了源碼會作版本控制方式的備份以外,一般文件很少有人會做,長時間的備份又意義不大,但是頻繁做備份又成本太高。

所以你需要ZFS快照,快照就是一種對文件系統級的版本控制,無論當前文件被破壞成什麼樣,你都可以通過回滾快照或作快照克隆的方式恢復之前任意一個快照的備份,而快照本身又是一種差異備份,其備份成本是很低的,不論是創建還是回滾或克降,速度也都是非常快的。

你值得擁有!

GnuPG的使用

這個方案中用到的ZFS上面和我以前的文章都介紹過很多了,這裏再簡單介紹一下GPG:

全名叫:The GNU Privacy Guard, 是一個安全的加解密工具。除了可以給文件加解密以外,它還有郵件插件,可以裝在郵件客戶端裏給郵件加密或加簽名,防止郵件在傳輸過程中泄密或被修改。相比 普通的加密工具(比如壓縮軟件自帶的加密功能)來說,它具有更高的安全性(默認密鑰長達2048位,最長支持4096位),並且是非對稱加密(在郵件加密 中很重要)。

順便說一句,GPG在加密前會做一次壓縮,所以對於加密後的文件小於源文件的情況請不要感到奇怪。

首先是安裝GPG,這個在ports找到gnupg安裝之即可,不多說。

注 意:GPG需要額外安裝一個輸入密碼的東西叫pinentry,但是在服務器上裝的時候要小心,它有四個選項,分別是TTY、NOCURSES、GTK、 QT,選擇後兩個GUI版的會把XWin給裝了,個人建議選擇NOCURSES,比TTY版本好看也可靠,TTY版有時不能正常工作——表現爲到需要輸入 密碼的地方時就報錯。

GPG的基本的使用說明可以參考阮一峯的文章《GPG入門教程》。

然後是創建你的密鑰——當然,如果你自己以前用過GPG,或者需要在新裝的服務器上恢復備份,想繼續用以前的密鑰也可以直接導入使用。

創建密鑰的方式是:

gpg --gen-key

注意:這裏輸入的密碼要記得,這個密碼是用於保護私鑰的,解密的時候會用到。

之後可以看看已經創建好的密鑰(分別是公鑰部分和私鑰部分):

gpg --list-keys
gpg --list-secret-keys

然後要做一件事情就是把密鑰導出備份到安全的地方:

gpg -o username.pub.key --export userid
gpg -o username.key --export-secret-keys userid

以上分別導出公鑰(username.pub.key)和私鑰(username.key)。因爲加密用公鑰,解密用私鑰,所以公鑰丟了無所謂,大不了重新創建一副,但是私鑰丟了,以前用這個公鑰加密的內容都無法解密。

注意:一定要保管好私鑰和私鑰密碼,一旦丟了你所有加密的內容都無法恢復。

萬一需要恢復密鑰時,可以重新導入(公鑰私鑰一樣,GPG會自動識別):

gpg --import username.pub.key
gpg --import username.key

但是需要注意的是,導入的KEY默認是不被信任的,每次使用時都會顯示一下KEY的指紋並提示你是否需要信任,選擇YES後纔會繼續,所以需要手工將其標記爲信任:

gpg --edit-key userid
# 進入交互式操作界面
>trust
# 選擇5,無限期信任
# 然後退出編輯即可
>quit

然後先測試一下:

dd if=/dev/urandom of=test.dat bs=1024 count=1024  # 創建一個1M的隨機內容文件
md5 test.dat # 原文件校驗值,注意FreeBSD是用md5命令,不同於Linux的md5sum
gpg -r userid -o test.gpg -e test.dat  # 指定用userid的公鑰加密test.dat,生成test.gpg加密文件

再把加密文件test.gpg解密試試:

gpg -d test.gpg -o test1.dat  # 自動使用加密的userid私鑰,如果沒有則報錯,需要輸入私鑰密碼
md5 test1.dat

輸入密碼應該就可以解出文件來,對個測試文件作一下MD5校驗,確認完全一致說明加密解密功能沒有問題。

具體配置

最後配置備份同步方案。

共享部分就不說了,跟一般的Samba配置沒什麼區別,無非是創建ZFS時加上dedup=on參數。下面說一下那個用於備份的ZFS創建:

zfs create -s -V 1T -b 4k -o compression=on tank/backup

這個ZFS的容量爲1T,啓用壓縮。然後配置爲了iSCSI target,具體方法見前文。

在備份服務器上創建一個cron任務,每週執行,運行以下命令(當然應該寫到一個腳本里去,而且其中的命令全部要加上絕對路徑,cron任務可是沒有PATH環境變量的):

TODAY=`date +%Y%m%d`  # 注意命令參數與Linux下不同
zfs snapshot tank/backup@$TODAY
zfs send tank/backup@$TODAY | gpg -r userid -o /path_to_backup/$TODAY.bak -e - # 生成ZFS今天的快照(本身就是壓縮過的)並通過管道傳給GPG進行加密並保存爲$TODAY.bak文件
zfs destroy tank/backup@$TODAY # 之後快照就可以刪除了,當然要保留一段時間也可以,自己處理
rsync -e "ssh" /path_to_backup/$TODAY.bak user@remotebackup:~/backup/  # remotebackup爲遠程備份服務器的域名或IP
#rm $TODAY.bak # 傳輸成功即可刪除備份文件,或者也可以保留一段時間,自己處理

必要的話還可以在其中加入發郵件的功能,以便及時瞭解備份是否成功——FreeBSD的cron會自動把命令執行結果發送郵件,除非你自己把標準輸出和標準錯誤都重定向到日誌文件或其它地方。

恢復備份的命令:

zfs create -s -V 1T -b 4k -o comporession=on tank/backup
gpg -d someday.bak | zfs recv -F tank/backup

當然在解密的時候需要輸入私鑰密碼。

請支持GPG

GPG的作者Werner全職爲這個開源項目工作,併爲此創建了g10code公司運作此項目,但因爲基本沒什麼盈利,公司目前有一些經營困難(見相關報道),他一度打算關閉公司中止項目,是斯諾登讓他看到了隱私保護的意義,所以決定籌錢繼續幹下去。

詳情見《GnuPG and g10code》。

歡迎大家捐款支持這樣的有意義的工作,這纔是真正的爲人民服務。像我這麼有錢任性的,纔不會告訴你們已經捐了50歐。當然這是去年的事,要是現在捐還可以省不少人民幣(歐元匯率跌了好多)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章