Linux/보안장비 운용

rsync + ssh + 공개 키 + crond 를 이용한 원격 백업 시스템 구축하기

GGkeeper 2022. 3. 3. 23:55

실습> rsync + ssh + 공개키 + crond를 이용한 원격 백업 시스템 구축하기

Real   Server: 192.168.101.100
Backup Server: 192.168.101.101

+--------+      +--------+
|      +-----------      |
|  S1  | |      |    S2  |
|      +---------->      |
+--------+      +--------+
백업 대상서버        백업서버   
 101.100         101.101
(real server)   (backup server)   
(rsync server)  (rsync clinet)  

위에서의 단점 BackupServer가 root로 접근이 가능하면 문제가 되므로 PermitRootLogin 은 3개의 값을 지정할 수 있다.
yes : root 접근허용 가능
no  : root 접근허용 금지
forced-commands-only : 공개키의 명령만 실행하겠다는 의미
                       root로 접근은 금지하되 특정 명령어는 가능하게 할때 사용한다.

-- 순서 --
1. 백업대상 서버에서 설정 및 sshd 재시작
2. 백업서버에서 백업대상 서버로 root 로 접근이 가능한지 TEST
3. 백업대상 서버에서 공개키(authorized_keys) 파일을 복사
4. /root/bin/validate-rsync 생성
5. 백업서버에서 rsync 로 백업
6. 백업스크립트 작성 
7. crond 에 등록 
8. ssh-agent 실행
9. ssh-agent 환경변수 세팅 
10. ssh-add 실행
11. 백업스크립트 수정
12. 백업 테스트
13. 복원
-- 순서 --

1. 백업대상 서버에서 설정 및 sshd 재시작
/etc/ssh/sshd_config 에서 PermitRootLogin forced-commands-only로 설정한다.
RealServer ~# vi /etc/ssh/sshd_config 
PermitRootLogin forced-commands-only 

RealServer ~# systemctl reload sshd

2. 백업서버에서 백업대상 서버로 root 로 접근이 가능한지 TEST
결론: root로 접근이 안된다.
BackupServer ~# ssh 192.168.101.100
root@192.168.101.100's password: 
Permission denied, please try again.
root@192.168.101.100's password: 
Permission denied, please try again.
root@192.168.101.100's password: 
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

3. 백업대상 서버에서 공개키(authorized_keys) 파일을 복사
BackupServer ~# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  <-- 엔터
Enter passphrase (empty for no passphrase):   <-- P@ssw0rd 입력
Enter same passphrase again:   <-- P@ssw0rd 입력
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:yiT9Mh/MRuyrLXUwf57veBww6fFtrDlqV1gxMlCocpk root@web1.linuxmaster.net
The key's randomart image is:
+---[RSA 2048]----+
|           .+.   |
|           . o o |
|          +  .o o|
|     . ooE  =   .|
|    . o S+ . = = |
|     + B. o o + =|
|      =.B. o o * |
|      .* o  +.B  |
|      .o+  .o*o. |
+----[SHA256]-----+

root로 접속이 안되는걸 확인했다면 다시 설정파일을 수정한다. (공개키를 복사하기 위해서 root접근을 열어줌)
PermitRootLogin yes로 수정하고 sshd 를 재시작한다.

RealServer ~# vi /etc/ssh/sshd_config 
PermitRootLogin yes

RealServer ~# systemctl reload sshd


RealServer ~# ssh localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:sNNXOE97kZTiu5BwsqYZmmlRl47O/13+DwzpI6qd21c.
ECDSA key fingerprint is MD5:b1:8b:b7:62:61:26:a7:7d:60:86:ac:40:bb:82:d0:42.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
root@localhost's password:  <-- yes
^C  <-- yes 누르고 Ctrl + C 를 입력해서 종료한다.

RealServer ~# ls .ssh
known_hosts

암호문이 있는 공개키를 Real Server에 복사한다.
복사할 때 파일명을 /root/.ssh/authorized_keys 으로 복사해야 한다.
BackupServer ~# scp .ssh/id_rsa.pub 192.168.101.100:.ssh/authorized_keys
root@192.168.101.100's password: 
id_rsa.pub                                         100%  407   128.7KB/s   00:00 

RealServer ~# ls .ssh
authorized_keys  known_hosts
~~~~~~~~~~~~~~~

공개키 복사가 완료되면 다시 root로 로그인하지 못하도록 설정파일을 수정하고 sshd를 재시작한다.
RealServer ~# vi /etc/ssh/sshd_config 
PermitRootLogin forced-commands-only

RealServer ~# systemctl reload sshd

authorized_keys 파일을 열어서
from="192.168.101.101",command="/root/bin/validate-rsync" 를 추가한다.
RealServer ~# vi .ssh/authorized_keys 
from="192.168.101.101",command="/root/bin/validate-rsync" ssh-rsa AAAAB3NzaC1yc2EAAAA(생략 ...)

4. /root/bin/validate-rsync 생성
/root/bin 디렉터리로 이동해서 validate-rsync 파일을 생성한다.
RealServer ~# mkdir bin; cd bin
RealServer bin# vi validate-rsync
#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
          *\&*) echo "Rejected" ;;
          *\(*) echo "Rejected" ;;
          *\{*) echo "Rejected" ;;
          *\;*) echo "Rejected" ;;
          *\<*) echo "Rejected" ;;
          *\`*) echo "Rejected" ;;
          rsync\ --server*) $SSH_ORIGINAL_COMMAND ;;
          *) echo "Rejected" ;;
esac

RealServer bin# chmod 755 validate-rsync 

5. 백업서버에서 rsync 로 백업
BackupServer에서 Real Server에 있는 /etc 디렉터리를 백업한다.
root로 접근이 가능하다. 성공여부는 /etc 디렉터리가 복사되면 성공한 것이다.
BackupServer ~# rm -rf /backup/*
BackupServer ~# rsync -az -e ssh 192.168.101.100:/etc /backup
Enter passphrase for key '/root/.ssh/id_rsa':  <-- 암호문 P@ssw0rd를 입력한다.
BackupServer ~# tree -L 1 /backup/
/backup/
└── etc

6. 백업스크립트 작성 
BackupServer ~# vi bin/rsyncBackup.sh 
#!/bin/sh
# 파일명: rsyncBackup.sh
# 프로그램 설명: rsync 서버 백업 스크립트
# 작성자: 리눅스마스터넷
# 버전: 2022030301

today=$(date +%Y%m%d)
rsyncServer="192.168.101.100"
#backupDir="EVER_LOG EVER_ETC HOME"
backupDir="/var/log /etc /home"

# 날짜 디렉터리가 존재하지 않으면 생성한다.
if [ ! -d /backup/$today ]; then
    mkdir -m 700 /backup/$today
fi

# rsync server 로 접속해서 백업한다.
for dir in $backupDir
do
   echo ">>> $dir Directory Backup <<<"
   if [ -x /usr/bin/rsync ]; then
       #rsync -az $rsyncServer::$dir /backup/$today/$dir
       rsync -az -e ssh $rsyncServer:$dir /backup/$today
   fi
done

BackupServer ~# rsyncBackup.sh 
>>> /var/log Directory Backup <<<
Enter passphrase for key '/root/.ssh/id_rsa':  <-- P@ssw0rd 를 입력한다.
>>> /etc Directory Backup <<<
Enter passphrase for key '/root/.ssh/id_rsa':  <-- P@ssw0rd 를 입력한다. 
>>> /home Directory Backup <<<
Enter passphrase for key '/root/.ssh/id_rsa':  <-- P@ssw0rd 를 입력한다. 
BackupServer ~# tree -L 2 /backup/
/backup/
└── 20220303
    ├── etc
    ├── home
    └── log

ssh-agent를 실행한다.
ssh-agent를 실행하면 변화되는 내용 두 가지는 아래와 같다.
첫 번째 : 소켓 파일이 생성된다. (/tmp/ssh-yYeeCgpi8NQB/agent.44230)
두 번째 : 프로세스가 실행된다. (ssh-agent)
BackupServer ~# ssh-agent 
SSH_AUTH_SOCK=/tmp/ssh-yYeeCgpi8NQB/agent.44230; export SSH_AUTH_SOCK;
SSH_AGENT_PID=44231; export SSH_AGENT_PID;
echo Agent pid 44231;

소켓 파일이 생성되므로 이 소켓 파일을 확인한다.
BackupServer ~# ls -l /tmp/ssh-yYeeCgpi8NQB/agent.44230
srw-------. 1 root root 0  3월  3 20:11 /tmp/ssh-yYeeCgpi8NQB/agent.44230

ssh-agent가 메모리에 떠있으므로 이 프로세스를 확인한다.
BackupServer ~# ps aux | grep agent
root      44231  0.0  0.1  72472   780 ?        Ss   20:10   0:00 ssh-agent
root      44234  0.0  0.2 116972  1024 pts/2    R+   20:12   0:00 grep --color=auto agent

위에서 출력된 환경변수를 실행해야 한다.
BackupServer ~# SSH_AUTH_SOCK=/tmp/ssh-yYeeCgpi8NQB/agent.44230; export SSH_AUTH_SOCK;
BackupServer ~# SSH_AGENT_PID=44231; export SSH_AGENT_PID;

SSH로 이름이 들어간 환경변수를 확인한다.
BackupServer ~# set | grep SSH
SSH_AGENT_PID=44231  <--
SSH_AUTH_SOCK=/tmp/ssh-yYeeCgpi8NQB/agent.44230  <--
SSH_CLIENT='192.168.101.1 9924 22'
SSH_CONNECTION='192.168.101.1 9924 192.168.101.101 22'
SSH_TTY=/dev/pts/2
_=SSH_AGENT_PID

암호문을 ssh-add를 통해서 입력한다.
BackupServer ~# ssh-add
Enter passphrase for /root/.ssh/id_rsa:   <-- P@ssw0rd를 입력한다.
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

BackupServer ~# rm -rf /backup/*

Real Server로 접속할 때 자동으로 ssh-agent가 암호문을 대신 전달해주므로 암호문을 입력하지 않아도 접속이 된다.
그러므로 Real Server의 자료를 백업할 수 있다.
BackupServer ~# rsyncBackup.sh 
>>> /var/log Directory Backup <<<
>>> /etc Directory Backup <<<
>>> /home Directory Backup <<<
BackupServer ~# tree -L 2 /backup/
/backup/
└── 20220303
    ├── etc
    ├── home
    └── log

4 directories, 0 files

ssh-agent 프로세스를 종료하는 방법은 ssh-agent -k를 사용한다. (kill 보다는 이 방법을 사용하는 것을 추천)
ssh-agent -k 를 사용하면 
첫 번째 : 소켓 파일이 삭제된다. (/tmp/ssh-yYeeCgpi8NQB/agent.44230)
두 번째 : 프로세스가 종료된다. (ssh-agent)
세 번째 : 환경변수는 아래 출력되는 unset으로 직접 삭제해야 한다.
BackupServer ~# ssh-agent -k
unset SSH_AUTH_SOCK;
unset SSH_AGENT_PID;
echo Agent pid 44231 killed;
BackupServer ~# unset SSH_AUTH_SOCK; unset SSH_AGENT_PID;

ssh-agent 환경변수 정보를 파일로 저장해서 실행하는 경우
BackupServer ~# ssh-agent > ssh-agent.txt
BackupServer ~# . ssh-agent.txt 
BackupServer ~# ssh-add 
BackupServer ~# rsyncBackup.sh 

7. crond 에 등록 
위에서 이미 등록을 했기 때문에 여기서는 확인만 한다.
새벽 4시 20분에 rsyncBackup.sh 가 실행될 수 있도록 등록한다.
BackupServer ~# vi /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
MAILTO=root

20 04 * * * root rsyncBackup.sh

8. ssh-agent 실행
ssh-agent를 실행해서 출력되는 내용을 파일로 저장한다.
BackupServer ~# cd
BackupServer ~# ssh-agent > ssh-agent.txt

9. ssh-agent 환경변수 세팅 
. ssh-agent.txt를 실행하면 ssh-agent.txt 안에 저장된 환경변수들이 설정된다.
BackupServer ~# . ssh-agent.txt 

10. ssh-add 실행
ssh-add 를 실행해서 암호문을 추가한다.
BackupServer ~# ssh-add 
Enter passphrase for /root/.ssh/id_rsa:  <-- P@ssw0rd
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

11. 백업스크립트 수정
ssh-agent 환경변수가 저장된 파일을 실행하는 부분을 스크립트에 추가한다.
BackupServer ~# vi bin/rsyncBackup.sh 
#!/bin/sh
# 파일명: rsyncBackup.sh
# 프로그램 설명: rsync 서버 백업 스크립트
# 작성자: 리눅스마스터넷
# 버전: 2022030301

today=$(date +%Y%m%d)
rsyncServer="192.168.101.100"
#backupDir="EVER_LOG EVER_ETC HOME"
backupDir="/var/log /etc /home"

# ssh-agent 환경변수가 저장된 파일을 실행시킨다.
. /root/ssh-agent.txt

# 날짜 디렉터리가 존재하지 않으면 생성한다.
if [ ! -d /backup/$today ]; then
    mkdir -m 700 /backup/$today
fi

# rsync server 로 접속해서 백업한다.
for dir in $backupDir
do
   echo ">>> $dir Directory Backup <<<"
   if [ -x /usr/bin/rsync ]; then
       #rsync -az $rsyncServer::$dir /backup/$today/$dir
       rsync -az -e ssh $rsyncServer:$dir /backup/$today
   fi
done

12. 백업 테스트
BackupServer ~# rm -rf /backup/*
BackupServer ~# ls /backup/
BackupServer ~# date 
2022. 03. 03. (목) 21:18:39 KST
BackupServer ~# date 03040418
2022. 03. 04. (금) 04:18:00 KST

BackupServer ~# tail -f /var/log/cron
  :
  :(생략)
Mar  4 04:20:01 web1 CROND[44600]: (root) CMD (rsyncBackup.sh)
^C  <-- Ctrl + C를 눌러서 종료한다.

. /root/ssh-agent.txt 파일을 실행하면 백업이 잘 되는 것을 확인할 수 있다.
BackupServer ~# tree -L 2 /backup
/backup
└── 20220304
    ├── etc
    ├── home
    └── log

4 directories, 0 files

. /root/ssh-agent.txt 부분을 주석처리하고 실행했을 때 잘 실행되는지 확인한다.
BackupServer ~# rm -rf /backup/*
BackupServer ~# ls /backup
BackupServer ~# vi bin/rsyncBackup.sh 
#!/bin/sh
# 파일명: rsyncBackup.sh
# 프로그램 설명: rsync 서버 백업 스크립트
# 작성자: 리눅스마스터넷
# 버전: 2022030301

today=$(date +%Y%m%d)
rsyncServer="192.168.101.100"
#backupDir="EVER_LOG EVER_ETC HOME"
backupDir="/var/log /etc /home"

# ssh-agent 환경변수가 저장된 파일을 실행시킨다.
#. /root/ssh-agent.txt

# 날짜 디렉터리가 존재하지 않으면 생성한다.
if [ ! -d /backup/$today ]; then
    mkdir -m 700 /backup/$today
fi

# rsync server 로 접속해서 백업한다.
for dir in $backupDir
do
   echo ">>> $dir Directory Backup <<<"
   if [ -x /usr/bin/rsync ]; then
       #rsync -az $rsyncServer::$dir /backup/$today/$dir
       rsync -az -e ssh $rsyncServer:$dir /backup/$today
   fi
done

시간을 다음 날 04:18분으로 변경한다.
BackupServer ~# date
2022. 03. 04. (금) 04:23:25 KST
BackupServer ~# date 03050418
2022. 03. 05. (토) 04:18:00 KST
BackupServer ~# ls /backup/
BackupServer ~# tail -f /var/log/cron
  :
  :(생략)
Mar  5 04:20:01 web1 CROND[44630]: (root) CMD (rsyncBackup.sh)
^C  <-- Ctrl + C를 눌러서 종료한다.

ssh-agent 환경변수가 저장된 파일을 실행시키지 않으면 백업이 안된다!!!
BackupServer ~# tree -L 2 /backup
/backup
└── 20220305

1 directory, 0 files

13. 복원
모든 테스트가 다 끝났으면 정상적으로 복원한다.

rsyncBackup.sh 파일에서 ssh-agent 환경변수가 저장된 파일을 실행시키는 부분을 주석을 제거한다.
BackupServer ~# vi bin/rsyncBackup.sh 
#!/bin/sh
# 파일명: rsyncBackup.sh
# 프로그램 설명: rsync 서버 백업 스크립트
# 작성자: 리눅스마스터넷
# 버전: 2022030301

today=$(date +%Y%m%d)
rsyncServer="192.168.101.100"
#backupDir="EVER_LOG EVER_ETC HOME"
backupDir="/var/log /etc /home"

# ssh-agent 환경변수가 저장된 파일을 실행시킨다.
. /root/ssh-agent.txt

# 날짜 디렉터리가 존재하지 않으면 생성한다.
if [ ! -d /backup/$today ]; then
    mkdir -m 700 /backup/$today
fi

# rsync server 로 접속해서 백업한다.
for dir in $backupDir
do
   echo ">>> $dir Directory Backup <<<"
   if [ -x /usr/bin/rsync ]; then
       #rsync -az $rsyncServer::$dir /backup/$today/$dir
       rsync -az -e ssh $rsyncServer:$dir /backup/$today
   fi
done

정확한 시간을 설정한다.
BackupServer ~# rdate -s time.bora.net
BackupServer ~# date
2022. 03. 03. (목) 21:30:47 KST

'Linux > 보안장비 운용' 카테고리의 다른 글

시간 동기화 설정하기  (0) 2022.03.04
로그 log  (0) 2022.03.04
rsync + ssh 백업 테스트 2  (0) 2022.03.03
rsync + ssh 백업 테스트  (0) 2022.03.03
rsync 데몬 중지  (0) 2022.03.03