labunix's blog

labunixのラボUnix

さくらVPSのバックアップ(github/cryptsetup/rsync+ssh)

■さくらVPSのバックアップについて
 スクリプトとデータの2種類を対象とする。

■システムをバックアップすると仮定すると、
 データ量が多いかと言うとそうでも無い。

# df | awk '{sum+=$3};END{print sum/1024/1024"GB"}'
2.69375GB

■システムをバックアップしない理由は以下。

 システムはカスタムインストールを使う
 定期的なバックアップ先の確保が困難
 確実なリストア方法を作るのが面倒

■githubを使ってスクリプトをバックアップするための準備。

# USER=labunix; \
  cd /home/${USER}; \
  mkdir myscripts;chown $USER:$USER myscripts

■前回のINPUTパケットの制限スクリプトを移動して、
 「/etc/rc.local」も変更する。

# USER=labunix; \
  mv /root/myvpsinput.sh /home/${USER}/myscripts/; \
  chown -R ${USER}:${USER} /home/${USER}/myscripts/

# grep -v "^#\|^\$" /etc/rc.local 
MYIPTABLES=/home/labunix/myscripts/myvpsinput.sh;test -x "${MYIPTABLES}" && /bin/bash "${MYIPTABLES}"
exit 0

# /etc/rc.local | head -3
[ ok ] Stopping authentication failure monitor: fail2ban.
[ ok ] Starting authentication failure monitor: fail2ban.
[ ok ] Restarting authentication failure monitor: fail2ban.

■初回のみ、リポジトリを作成して、さくらVPSの仮想マシンでは無い、
 自身の所有するサーバにcloneする。

$ git clone git@github.com:labunix/sakuravps.git

■リポジトリにscpでコピーしてgithubにアップロード
 実行時には3回のログインが必要

$ VPSIP=XXX.XXX.XXX.XXX; \
  VPSPORT=XX022; \
  USER=labunix; \
  LOCALGIT=/opt/git_work/sakuravps/; \
  GITREPO=git@github.com:labunix/sakuravps.git; \
  BACKUPSERIAL=`env LANG=C date '+%Y%m%d_%H%M%S'`
  cd $LOCALGIT; \
  git pull $GITREPO; \
  rsync -avz --delete -e "ssh -p ${VPSPORT}" ${USER}@${VPSIP}:~/myscripts ${LOCALGIT}
  git add .; \
  git commit -a -m "${BACKUPSERIAL} backup"; \
  git push $GITREPO

■sshpassやexpectで自動化出来るが、
 スクリプトの更新はログインしている時しかしないので、
 上記のスクリプトを手動で実行するものとする。

# apt-cache search sshpass
sshpass - Non-interactive ssh password authentication

# apt-cache search ^expect\$
expect - 対話型アプリケーションの自動化

■cryptsetupでデータの暗号化
 データを置く気がそもそも無い。
 どうしても置くとき用に暗号化パーティションを用意する。
 cryptsetup導入時にkernelの変更を伴うので再起動を行う。

# apt-get install -y cryptsetup
# modinfo dm_mod
filename:       /lib/modules/3.2.0-4-amd64/kernel/drivers/md/dm-mod.ko
license:        GPL
author:         Joe Thornber <dm-devel@redhat.com>
description:    device-mapper driver
alias:          devname:mapper/control
alias:          char-major-10-236
depends:        
intree:         Y
vermagic:       3.2.0-4-amd64 SMP mod_unload modversions 
parm:           major:The major number of the device mapper (uint)

# modinfo dm_crypt
filename:       /lib/modules/3.2.0-4-amd64/kernel/drivers/md/dm-crypt.ko
license:        GPL
description:    device-mapper target for transparent encryption / decryption
author:         Christophe Saout <christophe@saout.de>
depends:        dm-mod
intree:         Y
vermagic:       3.2.0-4-amd64 SMP mod_unload modversions 

# shutdown -r now && exit
$ exit

■再起動後はモジュールが読み込まれているはず。

$ lsmod | grep dm
dm_crypt               22586  0 
dm_mod                 63645  1 dm_crypt

■「/home」パーティションを分けた構成なので、イメージファイルを1GBで作成する。
 「Type uppercase yes」の入力は大文字の「YES」とすること。

# mkdir -p /home/cryptsetup && cd /home/cryptsetup
# dd if=/dev/zero of=luks.img bs=1024k count=1000
1000+0 レコード入力
1000+0 レコード出力
1048576000 バイト (1.0 GB) コピーされました、 1.63887 秒、 640 MB/秒

# cryptsetup --verbose -y luksFormat -c aes-cbc-essiv:sha256 --key-size 256 luks.img

WARNING!
========
This will overwrite data on luks.img irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: 
Verify passphrase: 
Command successful.

# cryptsetup luksOpen `pwd`/luks.img luks
Enter passphrase for /home/cryptsetup/luks.img: 

■暗号化ファイルシステムなので、ジャーナリングは不要。
 「ext2」でフォーマット。

# mkfs.ext2 /dev/mapper/luks
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
63872 inodes, 255488 blocks
12774 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=264241152
8 block groups
32768 blocks per group, 32768 fragments per group
7984 inodes per group
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

■ユーザデータ用にマウント

# USER=labunix; \
  DEST=/home/${USER}/mydata; \
  test -b /dev/dm-0 || cryptsetup luksOpen /home/luks.img luks
  test -d "${DEST}" || mkdir ${DEST} && chown ${USER}:${USER} "${DEST}"; \
  mount | grep luks >/dev/null || mount /dev/mapper/luks ${DEST}

# mount | grep luks
/dev/mapper/luks on /home/labunix/mydata type ext2 (rw,relatime,errors=continue,user_xattr,acl)

■アンマウント方法

# USER=labunix; \
  DEST=/home/${USER}/mydata; \
  umount $DEST; \
  cryptsetup luksClose luks

# mount | grep luks

■I/O性能も悪くない。

# hdparm -Tt /dev/vda1 

/dev/vda1:
 Timing cached reads:   12530 MB in  1.97 seconds = 6353.11 MB/sec
 Timing buffered disk reads: 486 MB in  0.96 seconds = 508.80 MB/sec

# hdparm -Tt /dev/dm-0 

/dev/dm-0:
 Timing cached reads:   12882 MB in  1.97 seconds = 6534.49 MB/sec
 Timing buffered disk reads: 998 MB in  2.39 seconds = 417.17 MB/sec

■ヘッダはバックアップしておく

# cryptsetup luksHeaderBackup luks.img --header-backup-file luks.header_`env LANG=C date '+%Y%m%d_%H%M%S'`; \
  for list in luks.header_*;do openssl enc -e -aes-256-ofb -in "$list" -out /home/labunix/myscripts/${list}.enc && rm -f "$list" ;done
enter aes-256-ofb encryption password:
Verifying - enter aes-256-ofb encryption password:

■復号化のテスト

# openssl enc -d  -aes-256-ofb -in /home/labunix/myscripts/luks.header_20140828_222222.enc -out check.header; \
  cryptsetup luksHeaderBackup luks.img --header-backup-file luks.header; \
  diff -s check.header  luks.header; \
  rm check.header luks.header
enter aes-256-ofb decryption password:
ファイルcheck.headerとluks.headerは同一

■上記を踏まえ、スクリプト化

 sakuravps
 https://github.com/labunix/sakuravps

■GUI用にXRDP/vino(VNC)、gnome-session gnome-terminal、
 テキストブラウザのw3m、tarの解凍用にbzip2を先に導入しておく。
 firefoxの「libxul.so」が「xulrunner」経由でサウンド等のGUIアプリを呼ぶ。
 キーボードUIはお好みで。
 お試し期間は通信量が2Mの制限があって時間がかかる。コーヒータイム。
 なお、kernelの変更があるので、再起動も忘れずに。

# apt-get install -y w3m bzip2 xrdp vino gnome-session gnome-terminal xulrunner*
# apt-get install -y anthy uim uim-anthy uim-applet-gnome im-switch

# shutdown -r now && exit

■暗号化パーティションにFirefoxを導入

# ./myscripts/luks_mount.sh 
Enter passphrase for /home/luks.img: 
/dev/mapper/luks on /home/labunix/mydata type ext2 (rw,relatime,errors=continue,user_xattr,acl)

# cd mydata/; \
# URL="http://ftp.mozilla.org/pub/mozilla.org/firefox/releases/latest/linux-x86_64/ja/"; \
  w3m -dump_source "$URL" | \
  sed s/">"/"&\n"/g | grep href=\"firefox | awk -F\" '{print $2}' | \
  echo "${URL}`xargs`" | \
  xargs wget;unset URL; \

# USER=labunix; \
  chown $USER:$USER firefox*; \
  exit

$ cd mydata/; \
  tar jxvf firefox-31.0.tar.bz2

■依存関係は以下。

$ cat firefox/dependentlibs.list
libnspr4.so
libplc4.so
libplds4.so
libnssutil3.so
libnss3.so
libsmime3.so
libssl3.so
libmozsqlite3.so
libmozalloc.so
libxul.so

■ポート転送の設定
 RDPポートは開けません。

$ mkdir .ssh
$ cat .ssh/config 
Host		XRDP
HostName	XXX.XXX.XXX.XXX
User		root
GatewayPorts    yes
LocalForward	3389	127.0.0.1:3389

■「ssh -X」でログイン時に「/var/log/auth.log」に出るエラーの対処
 以下はメッセージの通り、X転送が出来ないことを示している。
 「socket」ではなく「inet」を使う。

error: Failed to allocate internet-domain X11 display socket.

# grep -B 1 ^Listen /etc/ssh/sshd_config 
AddressFamily inet
ListenAddress 0.0.0.0
# /etc/init.d/ssh restart
[ ok ] Restarting OpenBSD Secure Shell server: sshd.

■sshのログイン時に「-X」オプションを付与してX転送を許可する。
 「gnome-terminal」が開く事を確認。

$ gnome-terminal &

■firefoxを起動

$ cd mydata/firefox/ && ./firefox &

■XRDPの外部からの接続を許可
 ポート転送で許可した時だけ利用可能にするので、
 iptablesはずっと開けたままとする。

# iptables -A INPUT -i eth0 -d 153.121.74.197 -p tcp -m tcp --dport 13389 -j ACCEPT

■xrdpが外部から接続出来るようにeth0のIP「XXX.XXX.XXX.XXX」に変更

# cd /etc/xrdp && \
  wget -O - http://w.vmeta.jp/temp/km-0411.ini | tee km-0411.ini && \
  ln -s km-0411.ini km-e0200411.ini && \
  ln -s km-0411.ini km-e0010411.ini

# grep -A 7 "^\[xrdp1\]" /etc/xrdp/xrdp.ini
[xrdp1]
name=sesman-Xvnc
lib=libvnc.so
username=ask
password=ask
ip=XXX.XXX.XXX.XXX
port=-1

# grep ^ListenAddress /etc/xrdp/sesman.ini 
ListenAddress=XXX.XXX.XXX.XXX

# /etc/init.d/xrdp restart

# cat .ssh/config 
Host		XRDP
HostName	127.0.0.1
Port		8022
User		labunix
GatewayPorts    yes
LocalForward	13389	127.0.0.1:3389

■「XRDP」にログインしてポート転送している間だけリモートデスクトップが使用出来る。
 画面サイズは小さく、若干もっさり。
 RDPクライアントはWheezyの「vinagre」を使用した。
 「im-switch」で入力メソッドを切り替えて、日本語、英語入力を確認。

$ ssh XRDP
labunix@127.0.0.1's password:

■XRDPで接続、firefoxの設定を行う
 「履歴を一切記憶しない」など。

■IPAフォントも入れておく。

# apt-get install -y ^fonts-ipafont*

■「myscripts/myvpsinput.sh」を編集して
 自身のサーバからバックアップスクリプトを実行

$ ./myscripts/sakuravps_rsync.sh

■さすがにGUIだと結構リソースを使う。
 若干swapを使うようになるのでGUIを常用するなら、
 もっと上位の契約にするべき。

# df | awk '{sum+=$3};END{print sum/1024/1024"GB"}'
12.2589GB

# ps axo pid,cmd,%cpu,%mem | awk '($NF>1)||($(NF-1)>0.0){print}'
 2703 /usr/sbin/spamd --create-pr  0.0  3.0
 2800 /usr/sbin/amavisd-new (mast  0.0  4.6
 2801 spamd child                  0.0  2.8
 2802 spamd child                  0.0  2.8
 2803 /usr/sbin/snort -m 027 -D -  0.6  5.5
 2823 /usr/sbin/amavisd-new (virg  0.0  4.6
 2824 /usr/sbin/amavisd-new (virg  0.0  4.6
 2846 /usr/sbin/clamd -c /etc/cla  0.2 13.7
 3012 /usr/bin/freshclam -d --qui  0.1  0.1
 5810 ssh XRDP                     0.3  0.4
 5816 sshd: labunix@pts/1          0.2  0.1
18006 Xvnc :11 -geometry 800x600   0.5  0.7
18139 /usr/lib/scim-1.0/scim-pane  0.1  0.6
18189 gnome-panel                  0.1  1.3
19568 Xvnc :12 -geometry 800x600   0.7  0.7
19650 /usr/bin/metacity            0.1  0.8
19660 gnome-panel                  0.1  1.4
20280 gnome-control-center --over  0.3  2.2
20852 /usr/sbin/xrdp               0.5  0.5
20911 Xvnc :13 -geometry 800x600   1.9  0.7
20959 /usr/lib/gnome-settings-dae  0.1  1.0
20990 /usr/bin/metacity            0.3  0.8
20999 gnome-panel                  0.4  1.4
21391 nautilus /home/labunix       0.5  1.7

■GUIに頼らなければ、まだリソースに余裕がある。

$ ps axo pid,cmd,%cpu,%mem | awk '($NF>1)||($(NF-1)>0.0){print}'
 2709 /usr/sbin/spamd --create-pr  0.3  3.0
 2771 /usr/sbin/snort -m 027 -D -  0.1  5.5
 2811 /usr/sbin/amavisd-new (mast  0.3  4.7
 2812 spamd child                  0.0  2.9
 2813 spamd child                  0.0  2.9
 2835 /usr/sbin/amavisd-new (virg  0.0  4.7
 2836 /usr/sbin/amavisd-new (virg  0.0  4.7
 2838 /usr/sbin/clamd -c /etc/cla  0.0 13.4
 3007 /usr/bin/freshclam -d --qui  0.7  0.1
 3271 /usr/bin/python /usr/bin/fa  0.1  0.4
 3619 -bash                        0.1  0.1

$ top -b -n 1 | head -5
top - 02:26:43 up 8 min,  1 user,  load average: 0.00, 0.02, 0.03
Tasks:  92 total,   1 running,  91 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.3 us,  0.4 sy,  0.0 ni, 97.4 id,  0.6 wa,  0.0 hi,  0.0 si,  0.4 st
KiB Mem:   2061060 total,   857636 used,  1203424 free,    15068 buffers
KiB Swap: 13671420 total,        0 used, 13671420 free,   218512 cached

■結局のところ、ログイン中で無いとバックアップはとれないので、
 自身のサーバ側には以下の設定だけで良いことになる。

$ grep BACKUPMYDATA myscripts/sakuravps_rsync.sh 
BACKUPMYDATA=/home/${USER}/sakura_vpsbackup
rsync -avz --delete --exclude "firefox/" -e "ssh -p ${VPSPORT}" ${USER}@${VPSIP}:~/mydata ${BACKUPMYDATA}

■暗号化された「luks.header」は自身のサーバのみ保存されるように変更した。
 暗号化自体が不要になった気がするが、今回はスルーする。

■ログイン、ログオフ時に忘れないように。

$ tail -n 1 .bash[r_][cl]*
==> .bash_logout <==
echo "su Pass";su root -c '/home/labunix/myscripts/luks_unmount.sh'

==> .bashrc <==
echo "su pass";su root -c '/home/labunix/myscripts/luks_mount.sh'

■ログオフ時のメッセージ
 luksのアンマウントのみ

ログアウト
su Pass
パスワード:

■ログイン時のメッセージ
 ここまで色々聞かれると、
 「自身のサーバからバックアップスクリプトの実行をしなきゃ」と思う。

su pass
パスワード:
enter aes-256-ofb encryption password:
Verifying - enter aes-256-ofb encryption password:
Enter passphrase for /home/luks.img: 
/dev/mapper/luks on /home/labunix/mydata type ext2 (rw,relatime,errors=continue,user_xattr,acl)