1. 키 생성 LOCAL 서버 홈디렉토리에서 $>ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/home/search/.ssh/id_dsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: 모두 그냥엔터 The key fingerprint is: 23:66:20:a5:d5:f9:7b:76:8b:a5:6c:99:1e:e1:5c:7f search@index1
인터넷 서비스를 계획하다 보면 차후에 많은 양의 데이터를 각각의 서버별로 어떻게 동기화를 실행할것인지 걱정이 될것이다. 물론 많은 자금을 들여서 스토리지를 구입을 하면 좋지만, 웹서버 3-4대분량이나 소량의 데이터를 위해서 스토리지를 구입하기에는 가격이 만만하지 않다.
이런 중소형의 미러링을 위해서 생각해 볼수 있는 방법중에 하나가 rsync다. rsync는 파일크기의 변화나 시간의 변화등을 이용 동기화를 한다. 테스트 결과 적은량의 리소스로 빠른동기화의 효과를 볼수 있었다. 물론 원격에서 접근해서 미러링을 한다는 것 자체가 보안에 문제가 있기는 하지만, 매우 유용한 프로그램인 것은 확실하다. 어떻게 사용하느냐는 사용자들의 선택일 것이다.
+Rsync의 주요 특징
링크, device, 소유자, 그릅, 허가권 복사를 지원
GNU tar와 비슷한 exclude, exclude-from 옵션 지원
RSH 또는 SSH등 사용가능
root 권한이 필요없음
anonymous 또는 인증 rsync 서버 지원(미러링에 유용함)
+Install #1 소스 설치
Rsync의 설치는 매우 간단하다. 설치라고 할것도 없다. 요즘 리눅스 플랫폼에는 거의 기본으로 들어있기 때문이다. 혹시 모르니 간단하게 설치를 해보자. 설치는 소스설치와 RPM설치로 진행하겠다. 될수 있으면 RPM으로 설치하는것을 권장한다. rsync홈페이지에 가보면 리눅스 플랫폼 외에도 다양한 플렛폼에서 사용할수 있도록 바이너리 화일이 제공된다.
먼저 소스 설치를 해보자. 아래 링크에서 Rsync소스 파일을 다운로드 받는다. 적당한 디렉토리로 이동후 압축을 해제하고 설치해 보자. configure옵션은 별다른게 없다. install화일에도 아래와 같이 나와있었다.
rsync는 xinetd기반으로 동작한다. 아래와 같이 설정화일을 만들어 준다. 아래 파일은 TCP 837포트를 이용해 미러링을 시킬 때 설정하면 된다. 만약 SSH를 사용할 것이라면 별도의 설정화일은 필요하지 않다.
[root@localhost]#
[root@localhost]# vi /etc/xinetd.d/rsync
service rsync
{
disable = no
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}
[root@localhost]# /etc/rc.d/init.d/xinetd restart
xinetd를 재시작 시키면 아래와 같이 873번 포트가 열릴 것이다.
[root@localhost]#
[root@localhost]# nmap localhost
873/tcp open rsync
이제 rsyncd.conf 설정화일을 작성해 보자. rsyncd.conf화일은 TCP 837포트를 사용할 때 설정해줘야 된다. 필자는 백업용도의 미러링 설정을 할 것이다.
[root@localhost]#
[root@localhost]# vi /etc/rsyncd.conf
[/home/backup]
path = /home/backup
comment = www.nasord.com
uid = nobody
gid = nobody
use chroot = yes
read only = yes
hosts allow = 192.168.0.2
max connections = 3
timeout 600
설정화일 옵션이다. 옵션은 간단하며, 기본적으로 위의 옵션들만 있으면 동작이 된다. 나머지 옵션들은 man을 참고 하기 바란다.
[/home/backup] 서비스명 path : 미러링 경로 comment : 설명 uid : 파일전송하는 사용자의 id. 기본값은 nobody gid : 파일전송하는 사용자의 그룹 id. 기본값은 nobody use chroot : 위의 path를 root 디렉토리로 사용. 보안상 필요함. read only : 읽기전용 hosts allow : 호스트별 접속허용. 기본값은 all host이므로 보안을 유지하려면 반드시 설정함 max connections : 동시접속자수 timeout : 클라이언트에서 접근시 타임아웃시간. anonymous 로 운영하는 경우 설정을 해야 클라이언트가 죽었을 때 서버에서 접속을 해체할 수 있음.
보안상 hosts allow와 use chroot는 설정을 해줄 것을 권장한다.
+클라이언트 실행
위의 설정으로 서버측 설정은 모두 끝났다. 이제 실제로 동기화를 시켜보자. 실행방법은 TCP 873포트를 이용한 실행과 SSH를 이용한 실행으로 나눠서 설명하겠다.
rsync의 실행옵션은 무지 많다. 다 알려면 복잡하고, 아래 옵션만 알아도 사용하는데 지장없다. 나머지 옵션이 궁금하면 man을 참고 바란다.
-a는 archive mode (심볼릭 링크, 속성, 퍼미션, 소유권등 보존).
-v verbose(상세하게 보여움).
-z compress(전송시 압축을 함).
-u update only(새로운 파일을 덮어쓰지 않음)
--delete 서버쪽에 없고 클라이언트쪽에만 있는 파일을 지움
위의 실행 예제를 보면 호스트 설정다음에 : "콜론"이 보일것이다. : 는 ssh나 rsh를 이용할 때 사용하고 ::는 TCP 873포트를 이용할때 설정해 주면 된다. 타겟경로를 지정해줄 때도 경로뒤에 /가 붙는 것과 안붙을 경우 차이가 난다. 타겟경로를 /home/backup라고 해주면 backup폴더가 생성되고 자료들이 backup폴더 안으로 들어가고 타겟 경로를 /home/backup/라고 해주면 백업 경로에 바로 저장이 된다. 주의 하기 바란다. 주기적인 미러링을 위해서는 cron을 이용하여 동기화 시키면 된다.
+설치 후기
Rsync는 상당히 유용한 도구임에는 틀림없다. 하지만 보안상 취약하니 설정에 주의해서 사용해야 된다. 2002년 rsync의 취약점을 이용한 exploit이 나왔다. 2.5.1버전이나 이전 버전들에 한해서 적용이 되는 것이니 2.5.1버전 이상을 사용해야 된다. 마지막으로 rsync영문 매뉴얼을 링크 걸어 놓겠다. 참고 하기 바란다.
백업 서버가 별도로 있는 경우 rsync 와 cron 을 이용해 주기적으로 백업을 할 수 있습니다.
-------------------------------------------------------------------- 개인적인 경험으로는 백업을 받을때 rsync 로 받는 방법과 NFS 로 원본 디스크를 마운트 해 놓고 카피 하는 방법 두가지 중에 NFS 가 속도도 빠르고 서버에 부하도 적게 걸리는것으로 확인 되었습니다.
다만 NFS 가 보안상 좋지가 않아 .. 조금 찝찝하다고 하는데 아직까지 제가 해 본 바로는 문제는 없었습니다. ---------------------------------------------------------------------
맨 위에 [origin] 은 2번 서버 세팅시 필요한 부분입니다. path 는 백업을 받을 디렉토리를 설정 하는 부분입니다. hosts allow 는 rsync 접속을 허용할 IP 입니다.
그리고 나서 /etc/xinetd.d/rsync 파일을 편집합니다.
----------------- /etc/xinetd.d/rsync ------------------------------------ # default: off # description: The rsync server is a good addition to am ftp server, as it \ # allows crc checksumming etc. service rsync { disable = no socket_type = stream wait = no user = root server = /usr/bin/rsync server_args = --daemon log_on_failure += USERID -------------------------------------------------------------------------
disable 을 no 로 설정 해 주면 데몬 사용 허가로 설정 됩니다.
이제 rsync 데몬을 실행 합니다.
[root@myserver]# /etc/rc.d/init.d/xinetd reload Reloading configuration: [ OK ]
rsync 데몬이 정상적으로 떠 있는지 확인 해 봅니다. rsync 데몬은 873 포트를 이용하니
[root@myserver]# telnet localhost 873 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. @RSYNCD: 26
rsync 데몬이 정상 반응 하는것을 확인 했습니다.
이제 백업 서버 ( 123.123.123.2 ) 서버에서 cron 설정을 해 주면 됩니다.
모든 사용자들은 적어도 한번쯤 백업을 계획한다. 그러나 유감스럽게도, 우리 대부분은 “백업하지 않는” 것이 오히려 습관처럼 되어있다.
Disclaimer:
이 기사는 단행본, 하우투 문서들, 맨 페이지, 유즈넷 뉴스그룹, 그리고 셀 수 없는 시간을 키보드와 씨름하며 얻은 유용한 정보들을 제공한다. 비록 모든 주제에 대해 통달했다는 것을 뜻하지는 않지만, 초급자가 중급 사용자가 되는 발판이 될 것이다. 모든 예제들은 우리 홈 네트워크로부터 그대로 가져왔으므로 우리가 아는 한 잘 동작한다.
이 가이드를 어떻게 사용할까
·[Enter]처럼 각 괄호에 담긴 단어들은 키보드에서 그 키를 누르거나 마우스 1번 버튼을 누르라는 뜻이다.
·{your name here}처럼 구불구불한 괄호 안에 담긴 단어들은 사용자가 입력해야 할 “진짜” 데이터에 대응하는 데이터를 뜻한다.
·이탤릭체로(기울어진) 쓰여진 텍스트는 사용자 자신이 셸 프롬프트에 써넣어야 할 명령을 뜻한다.
필요한 것 들 ( Prerequisites)
당신의 시스템에 리눅스가 설치되었다면, 필요한 모든 것이 이미 갖추어져 있을 것이다.
백업 계획 (Backup Plan)
당신이 홈 네트워크에서 백업을 계획하고 있다면, 몇 가지 작업순서를 정할 필요가 있다. 하드디스크가 전혀 못쓰게 되더라도(crash), 백업의 진정한 가치는 실수로 지운 파일이나 변경된 파일 모두를 반드시 되살리는 것이다. 언제고 당신은 (아마 그리 오래지 않아) 어떤 중요한 파일들을 지우거나 변경할 것이다. 그리고 백업도 없이 부트마저 불가능하게 만들게 될 것이다. 사실 이런 것을 털어놓기는 부끄럽지만, 나는 실제로 /root 디렉터리를 한 방에 날려버렸었다.
譯註: 백업 대체로 백업의 가치를 절실하게 느낄 때는 이미 돌이킬 수 없는 큰 대가를 치른 뒤일 경우가 많다. 우습게도, 백업에 대한 이 글을 나는 두 번째 쓰고 있다. 새로 구성한 시스템에 백업에 대한 장치를 미처 못하고 있었는데 마침 원본이 손상되어 버렸기 때문이다.
Note▶ 당신의 시스템이 크랙된 적이 있다면 백업은 깊이 생각한 후에 결정해야 한다. 백업은 수행과정을 매우 단순하게 하거나 녀석들이 시스템을 망치지 못하도록 계획되어야 한다.(특히 홈 네트워크에서는) 홈 네트워크를 위한 백업계획은 다음 두 가지 영역에 걸쳐 다루어진다: 얼마나 많이 백업을 하려는가? 그리고 어떻게 최소한의 수고로 백업을 할 것인가?
얼마나 백업을 할 것인가
백업하는 공간은 바로 돈이므로 나는 모든 백업을 최소한으로 유지하려 애쓴다. 그래서 나는 단지 선택된 디렉터리만 백업할 뿐, 전체 파일 시스템은 백업하지 않는다. /usr와 /opt 등 디렉터리는 인스톨 시디롬에 그 대부분이 들어있으므로, 하드 드라이브가 손상되더라도 기본적인 것들은 그저 다시 설치하면 그만이다. 그러나, 시스템 환경이나 사용자 설정값이 들어있는 /etc나 /home 디렉터리는 어디에서도 복구할 수 없으므로 정말 중요하다. 백업작업의 효율성과 경제성을 높이기 위해, 당신은 백업 계획에, 선택된 디렉터리를 가끔씩(월 또는 주 단위) 전체 백업을 수행하고, 그 다음엔 변경된 파일만 매일 백업(증분 백업 incremental backups)하도록 설정해야 한다.
譯註: 증분(增分) 백업 적당한 말을 찾으려 애썼는데 결국 이해하기 어려운 말이 되어버렸다. incremental backups는 증분 백업, 또는 부가(附加)적인 백업이라고 번역되기도 하는데, 전체 백업 후에, 백업 시스템의 효율성을 높이기 위해 변경된 파일들만 대상으로 백업을 추가하는 것을 뜻한다.
어떻게 백업하는가
테이프 드라이버는 홈 네트워크 백업용으로 사용하기에는 대체로 너무 비싸고, 플로피 디스크는 실용성이 없다. (나는 백업 디스크 수가 132 장을 넘었을 때 플로피 디스크를 포기해버렸다) 우리는 여분의 하드 드라이브를 사용하는 방법이 가장 좋은 해결책이라고 생각한다. 단, 여기서 말하는 하드 드라이브가 파티션이 아니라는 것에 주의한다! 내 하드 드라이브에 문제가 생긴 모든 경우에 드라이브 전체가 죽거나 못쓰게 되었지, 피해가 하나의 파티션에 끝나지 않았다. 하드 드라이브를 사용하는 방법이 비록 가장 안전한 방법은 아니지만(譯註: 온라인으로 침투한 크래커에게 시스템이 점령당했을 때 테이프 드라이버가 아마 상대적으로 안전할 것이다), 얼마나 많이 백업할 것인지 범위를 한정하는 방법도 있다.(하지만, 이미 크래커가 은밀히 활동하고 있다면!)
譯註: 백업 파티션과 드라이브 하드 드라이브에 백업하려면 반드시 원본이 들어있는 하드디스크와 물리적으로 다른 파티션에 설치해야 한다. 나는 하드디스크 하나에 파티션을 몇 개 만들고 그 가운데 하나에 백업파일들을 보존하고 있었다. 루트 파티션에 문제가 생겼을 때 몇 번 백업파티션의 데이터로 복원할 수 있었고, 그래서 나는 꽤 안심하고 있었지만, 하드디스크 스핀들 모터가 고장나자 백업파티션은 아무 소용도 없었다.
백업 프로그램들
모든 un*x 계열의 배포판에는 백업에 사용할 수 있는 세 개의 일반적인 프로그램이 포함되어 있다: tar, cpio, 그리고 dump가 그 것으로 각각의 유틸리티는 저마다 장점과 단점을 가지고 있다.
TAR: tar(Tape ARchive)는 소규모 네트워크에서 백업 프로그램으로 가장 일반적으로 사용되는 유틸리티이다. 이 유틸리티는 오래 전부터 여러 가지 용도로 사용되어 왔고, 앞으로도 아마 꽤 오랫동안 남아있을 것이다. 대부분의 사람이 모르고 있지만, tar는 테이프에 파일들을 옮겨 넣기 위해서 만들어진 것으로 백업용으로 설계된 것이 아니다. tar의 목적은 백업이 아니라 다른 컴퓨터들에서도 설치될 수 있도록 파일들을 테이프에 옮겨 쓰는 것이다. 그런 이유로 tar는 증분 백업기능이 미약하다.
CPIO: cpio는 증분 백업 기능을 제외하고 tar와 비슷한 유틸리티이다. 사실, cpio는 “파일 리스트” 기능조차 없다: 백업본에 포함할 파일들을 선택하려면, cpio는 find 프로그램으로부터 파일이름을 파이핑하여 사용해야만 한다. 하지만 cpio는 tar에 비해 두 가지 장점을 가진다: cpio는 더 작은 비압축 백업본을 만들고, 백업본에 손상된 부분이 있더라도 프로그램이 그냥 죽어버리지 않는다.
譯註: cpio 아래는 find 명령의 출력을 cpio의 표준입력으로 사용하는 일반적인 방법이다. /home 디렉터리 아래 모든 파일을 테이프 드라이브(/dev/st0)로 백업한다:
$ find /home -print | cpio -o > /dev/st0
find 유틸리티의 -mtime, -newer 등 옵션을 사용하면 증분 백업도 쉽게 할 수 있다. -newer 옵션으로 비교하는 /backup/time/home_full 파일은 최근 백업시간을 기록한 파일이다: $ find /home -mtime -l -name .bak -print | cpio -o > /dev/st0 $ find /home -newer /backup/time/home_full -print | cpio -o > /dev/st0
cpio와 tar는 압축을 하지 않고, 많은 파일을 묶어 하나의 덩어리로 만드는 유틸리티이다. ‘더 작은 비압축본’은 cpio가 더 효율적으로 파일을 묶을 수 있다는 것을 뜻한다.(일반적으로 백업 대상 파일의 전체크기가 백업매체의 크기보다 훨씬 크다면 tar가 더 유리하다.)
‘그냥 죽어버리지 않는다’는 말은 백업본에 손상된 부분이 있다면 그 부분을 건너뛰고 계속해서 작업을 수행한다는 뜻이다. 이 기능이 정말 고마울 때가 있을 것이다.
DUMP: dump는 tar나 cpio와 완전히 다른 프로그램이다. 이 유틸리티는 파일들이 아닌, 파일시스템 전체를 백업한다. dump는 파일 시스템이 하드 드라이브에 있거나, 심지어 그 파일시스템 안에 있는 파일이라도 상관하지 않는다. dump 유틸리티는 0-9 단계의 증분 백업을 지원하며, 한 파일시스템을 한번에, 신속하게, 그리고 효율적으로 옮겨 쓴다. 하지만, 가상 디렉터리를 다룰 수 없으며, tar나 cpio보다 훨씬 많은 백업공간을 잡아먹는다.
우리의 백업 방법
우리는 run-backup이라는 이름을 가진 백업 스크립트를 사용한다. 이 글의 끝인 Part 3에 쓰여진 글을 그대로 하드 드라이브의 적당한 위치로 옮긴 다음, 아래 명령을 수행해 실행할 수 있도록 설정한다:
chmod 777 run-backup [Enter]
run-backup 스크립트에서 어떤 부분을 고쳐야 할까
이 스크립트는 변수 네 개만 바꾸면 어떤 컴퓨터에서도 실행할 수 있도록 디자인되었다: COMPUTER, DIRECTORIES, BACKUPDIR, 그리고 TIMEDIR. 현재 우리는 리눅스 박스 두 대와 솔라리스 박스 두 대에서 이 스크립트를 실행하고 있다. BACKUPDIR은 우리 머신에 nfs로 마운트 되어 있지만, 컴퓨터에 연결된 다른 어떤 하드 드라이브라도 상관없다.
스크립트가 하는 일은 무엇인가?
스크립트가 실행되면, 먼저 오늘이 이 달의 첫 번째 날인지 검사한다. 만약 그렇다면, 스크립트는 DIRECTORIES 변수에 설정된 디렉터리와 파일리스트 전체를 tar로 묶고, 예를 들어 myserver-01Nov.tgz처럼 파일이름에 컴퓨터 이름과 날짜, 그리고 tgz를 붙인 다음, BACKUPDIR 변수에 설정된 디렉터리에 집어넣는다. 백업본의 파일이름들은 각각 서로 다르므로, 당신이 지우지 않는 한 BACKUPDIR 속에 계속 남아있을 것이다.
그 다음에, 오늘이 만약 이 달의 첫 날은 아니지만 일요일이라면, 스크립트는 DIRECTORIES에 설정된 목록 전체에 대한 백업을 만들고, BACKUPDIR 안에 있는 일요일 파일에 덮어쓴다. 다시 말하면, 백업 디렉터리에는 오직 하나의 일요일 파일만 있어서 매주 일요일마다 이 파일을 덮어쓰는 것이다. 그런 방법으로 하드 드라이브 공간을 쓸데없이 낭비하지 않도록 만들면서도 여전히 한 주 전의 전체 백업은 남아있게 된다.
스크립트는 또 일요일의 날짜를 TIMEDIR 디렉터리에 넣어둔다. 만약 오늘이 첫 번째 일요일이 아니라면, 스크립트는 전체 백업이 있었던 일요일 이후에 변경된 파일에 대해서만 모두 증분 백업을 만든다. 그런 이유로 일요일이 지나고 매 요일의 백업은 마지막 파일보다 계속 커지게 될 것이다.
당신은 최근 24시간 이내에 변경된 파일만 증분 백업을 하고 매 요일의 백업은 최소한으로 유지하려고 애쓰겠지만, 혹시 당신의 하드 드라이브가 이번 금요일에 먼 남쪽(?)으로 가버린다면, 당신은 일요일, 월요일, 화요일, 수요일, 그리고 목요일의 백업을 복원해야만 할 것이다. 일요일과 다른 요일들의 백업으로 백업본은 계속 더 많은 파일을 포함하지만, 당신은 단지 일요일과 목요일의 백업만으로 복원해야한다. 아래에 백업 디렉터리의 간단한 보기가 있다:
root 828717 Oct 1 16:19 myserver-01Oct.tgz root 14834 Oct 22 01:45 myserver-Fri.tgz root 5568 Oct 18 01:45 myserver-Mon.tgz root 14999 Oct 23 01:44 myserver-Sat.tgz root 1552152 Oct 24 01:45 myserver-Sun.tgz root 5569 Oct 21 01:45 myserver-Thu.tgz root 5570 Oct 19 01:45 myserver-Tue.tgz root 5569 Oct 20 01:45 myserver-Wed.tgz
스크립트를 어떻게 실행시킬까?
우리는 매일 새벽 1시(모두 잠들어 있을 시간)에 cron 작업으로 스크립트를 실행한다. cron에 대한 자세한 도움말은 Part 2에 있다.
주의: 증분 백업은 일요일에 백업한 시간을 알아야한다. 만약 당신이 주중에 백업 스크립트를 시작했다면, TIMEDIR 디렉터리 안에 시간파일을 만들어야 한다.(echo $NOW > $TIMEDIR/$COMPUTER-full-date #update full backup date) 예문으로 제공되는 스크립트에서 이 파일 이름은: myserver-full-date이고 그 속에는 다음 한 줄이 들어있다:
26-Sep
복원 Restoring:
복원은 백업보다 상대적으로 쉬운데, 한 가지만 잘 기억하자: tar는 파일이름 앞에 / 문자를 포함하지 않는다. 그러므로 /etc/passwd 파일을 복원한다면 먼저 / 디렉터리로 옮겨간 다음에 아래처럼 명령을 써야한다:
tar -zxvf {wherever_file_is}/myserver-Sun.tgz etc/passwd
譯註: cpio, dump 복원 cpio로 만들어진 백업도 일부분을(또는 전체) 복원할 수 있다. 아래는 테이프 백업장치로부터 /etc 디렉터리를 복원하는 명령이다. -m 옵션은 파일 속성을 그대로 복원하며, -d 옵션은 서브디렉터리 구조도 복원하는 옵션이다:
cpio -imd ‘/etc’ < /dev/st0
dump로 만들어진 백업은 restore로 복원한다. dump처럼 restore도 사용자에게 상세한 설명을 제공하며, 대화형으로 동작한다.
다음 달에는 dhcp를 살펴보기로 한다.
Copyright 1999, JC Pollman and Bill Mote Published in Issue 47 of Linux Gazette, November 1999 & http://www.linuxlab.co.kr/~el/
Part 2: Cron
리눅스 배포판에는 작업일정 관리와 관련된 프로그램으로 두 가지가 따라 나온다: cron과 at가 그 것으로, 둘 다 시스템이 부트될 때 데몬으로 실행된다 - 그래서 이들 프로그램은 결코 끝나지 않는다(시스템이 종료되거나 데몬을 죽이기 전까지). cron 스케줄은 일정을 반복해서 수행하고 at은 한번만 수행한다.
cron은 crontab 파일로부터 실행에 필요한 정보를 읽어들인다. 시스템과 각각의 사용자는 자신의 crontab 파일을 가진다. 시스템의 crontab은 /etc/crontab에 있다. 이 파일은 그대로 둔다. run-backup 일정을 설정하기 위해, root 사용자로 자신의 crontab 파일을 만들어야 한다.
루트의 crontab 파일을 만들자
먼저 EDITOR 변수를 정의한다. 이 변수는 아마 로그인하는 모든 사용자들이 반드시 읽어들이는 /etc/profile 에 넣어두는 방법이 가장 좋을 것이다. /etc/profile을 열고 아래 두 줄을 추가한다.
EDITOR=vi [Enter] export EDITOR [Enter]
만약 vi보다 더 좋아하는 에디터가 있다면, 당신이 좋아하는 것으로 바꾸길 바란다. 바뀐 변수가 시스템에 반영되려면 로그아웃한 다음 다시 로그인해야한다. 그 다음 아래처럼 쓴다:
crontab /etc/crontab [Enter]
이 명령은 시스템의 crontab을 복사하여, 당신이 사용할 crontab 파일을 만든다. 이제, 아래 명령으로 당신의 crontab 파일을 편집한다:
crontab -e [Enter]
crontab은 실행되는 프로그램과 설정파일 모두에 사용되는 이름이라는 것을 기억한다 - passwd랑 비슷하다. 아마 아래와 비슷한 줄들이 보일 것이다(原註: 이 예문은 RedHat 배포판의 crontab이다):
우리가 실행하려는 명령들이 아니므로 HOME=/ 줄 아래 모든 것을 지우고, run-backup 스크립트가 저장되어 있는 디렉터리 이름을 PATH에 추가한다.
crontab 안에서 각각의 줄은 프로그램 하나씩을 실행한다. crontab 파일은 특별한 형식을 가지는데: 프로그램이 실행되는 데 필요한 다섯 개의 필드로 구성된다.
주의: 시스템 crontab 안에는 프로그램을 실행하기 위해 cron 데몬에게 알려주어야 하는 특별한 사용자(예를 들어 root)가 설정되어 있지만, 사용자 crontab에는 이 필드가 필요 없다. 다섯 개의 필드는 다음과 같다:
minutes hours day-of-month month day-of-week
맨 페이지에 따르면:
시간과 날짜 필드는:
field allowed values minute 0-59 hour 0-23 day of month 1-31 month 1-12 (or names, see below) day of week 0-7 (0 or 7 is Sun, or use names)
어떤 필드에 애스터리스크(*, asterisk)가 있다면, “처음부터-끝까지” 항상 설정되어 있다는 의미이다.
숫자로 된 범위는 허용된다. 하이픈(-, hyphen)으로 두 숫자를 구분하여 범위를 설정하며 앞에 있는 숫자가 뒤보다 작아야한다. 특정 범위는 그 사이 숫자들을 포함한다. 예를 들어, 시간 필드에 사용된 8-11은 8, 9, 10 그리고 11시에 정해진 항목을 실행한다.
목록은 허용된다. 목록은 숫자들(또는 범위들)을 쉼표(,)로 구분하여 설정한다. 예를 들어: “1,2,5,9”, “0-4,8-13”.
간격 수치(step values)는 범위에 덧붙여 사용할 수 있다. 범위 뒤에 “/<number>”를 덧붙여 지정한 범위 안에서 특정 수치를 건너뛴다. 예를 들자면, “0-23/2”는 한 시간 건너 다른 한 시간마다 특정한 명령을 실행하기 위해 시간 필드에 사용될 수 있다.(V7 표준에서 “0,2,4,6,8,10,12,14,16,18,20,22”이 선택된다.) 간격은 애스터리스크 뒤에도 허용되므로, 당신이 “매 두 시간마다”를 말하려 한다면 그저 “*/2”라고 사용한다.
“month”와 “day of week” 필드에는 이름이 사용될 수도 있다. 특정한 요일이나 달을 구분할 수 있도록 앞에서 세 글자 정도를 사용한다(문제가 없는 경우). 범위나 목록에는 이름이 허용되지 않는다.
날짜와 요일이 함께 설정되어 있다면, 두 설정 모두 적용된다. 예를 들어 “30 4 1,15 * 5”라고 다섯 개의 필드가 설정되었다면 매달 1일과 15일, 4시 30분에 명령을 실행하고, 또 매주 금요일마다 같은 명령을 실행한다.
이제, 우리가 매일 새벽 한 시 5분이 되면 백업 스크립트를 실행하려 한다면, 우리 crontab 파일은 다음과 같을 것이다:
그리고 스크립트는 무슨 일이 있었는지 알리기 위해 작업이 끝난 후에는 root에게 email을 보낸다. run-backup 스크립트가 만족할만하게 작동해서 굳이 메일을 확인할 필요가 없다거나, crond로부터 자꾸 날아드는 email이 귀찮아졌다면 MAILTO 줄을 다음과 같이 고친다:
MAILTO=””
더 많은 정보를 원한다면, 맨 페이지를 살펴본다:
man crontab (/usr/bin/crontab, 실행파일에 대한 도움) man 5 crontab (/etc/crontab, 설정파일에 대한 도움) man cron (cron과 cron 데몬에 대한 도움)
Part 3: run-backup 스크립트
#!/bin/sh # 전체와 증분 백업 스크립트 # full and incr backup script # created 27 Sep 99 # Based on a script by Daniel O’Callaghan <danny@freebsd.org>
# 아래 변수 다섯 개를 당신의 컴퓨터/백업에 알맞은 것으로 바꾼다.
COMPUTER=myserver # 컴퓨터 이름 DIRECTORIES=”/etc /home” # 백업할 대상 디렉터리 BACKUPDIR=/backup/backups # 백업본이 만들어질 디렉터리 TIMEDIR=/backup/backups/last-full # 전체 백업한 날짜를 저장할 디렉터리 TAR=/bin/tar # tar 유틸리티 이름과 위치
# 이 아래 줄은 모두 손대지 말고 그대로 둔다.
PATH=/usr/local/bin:/usr/bin:/bin DOW=`date +%a` # 요일 이름, 예를 들어 Mon DOM=`date +%d` # 월 단위 날짜, 예를 들어 27 DM=`date +%d%b` # 날짜와 달, 예를 들어 27Sep
# 그 달의 첫 날에 영구적인 전체 백업을 만든다. # 매주 일요일마다 전체 백업을 만든다 - 이전에 만든 일요일 백업을 덮어쓴다. # 한가한 시간에 증분 백업을 만든다. # 각각의 증분 백업은 지난주에 만든, # 같은 이름을 가진 증분 백업을 덮어쓴다. # # 만약 NEWER = “” 이라면, tar는 지정한 디렉터리 안의 모든 파일을 백업한다.
# 그렇지 않다면 NEWER 날짜보다 새로운 파일들만 백업한다. # NEWER는 매주 일요일마다 쓰여진 날짜파일로부터 날짜를 가져온다.
if [ $DOM = “01” ]; then # 달마다 하는 전체 백업 NEWER=”” $TAR $NEWER -z -c -f $BACKUPDIR/$COMPUTER-$DM.tgz $DIRECTORIES fi
if [ $DOW = “Sun” ]; then # 매주 일요일마다 전체 백업 NEWER=”” NOW=`date +%d-%b` echo $NOW > $TIMEDIR/$COMPUTER-full-date # 전체백업 데이터를 업그레이드. $TAR $NEWER -z -c -f $BACKUPDIR/$COMPUTER-$DOW.tgz $DIRECTORIES
else # 증분 백업 - 지난주의 백업을 덮어쓴다. # 지난번 전체 백업을 한 날짜를 가져온다. NEWER=”--newer `cat $TIMEDIR/$COMPUTER-full-date`” $TAR $NEWER -z -c -f $BACKUPDIR/$COMPUTER-$DOW.tgz $DIRECTORIES fi
譯註: tar 옵션 tar는 원래 xvzf처럼 하이픈 없이 옵션을 한 덩어리로 묶어 사용한다. 하지만 유닉스계열의 표준 유틸리티들이 하이픈으로 옵션을 구분하므로 위 예문에서 tar는 표준적인 표기형식을 따르고 있다.
1.vi편집기란? vi는 visual의 약자로 유닉스의 표준 편집기이다. ex라는 editor를 바탕으로 만들어진 스크린 편집 기로, 프로그램의 사이즈도 작고 기능이 많다. 윈도우의 editor에 익숙한 사용자에겐 불편하게 느껴 지겠지만, 아주 편리한 환경과 막강한 기능을 제공하는 편집기이다. (참고) vi는 full screen editor이므로 정확한 단말기 특성이 /etc/termcap안에 있어야 하며, 환경 변수 $TERM이 정확히 정의되어 있어야 한다.
2.vi 편집기 시작하기 (1) 사용법 vi [option] [filename] (2) option -c : -c옵션은 시작하면서 어떠한 명령을 실행한다. -r : 손상된 파일을 복구할 때 쓴다. 파일을 편집하던 중 갑작스런 사고 등으로 인해 시스템이 다운되었을 경우 대개 이 명령으로 복구 할 수 있다. +n : 파일을 열면서 n번째 줄로 커서를 이동시킨다. + : 파일을 열면서 마지막 줄에 커서를 이동시킨다. -wn : 기본적인 윈도우 크기를 n라인으로 한다.(기본값은 20라인) (3) 사용예 1) vi => 빈문서로 시작한다. 2) vi index.html => 주어진 파일(index.html) 이름으로 편집을 시작한다. 만약 파일이 존재하지 않으면 새로 만들게 된다. 3) vi +15 index.html => index.html 파일을 열면서 커서를 15번째 줄로 보낸다. 4) vi -c 15 index.html => -c옵션은 시작하면서 어떠한 명령을 실행하라는 뜻이다. 따라서, -c 15 라고 쓰면 +15 옵션과 동일한 결과를 얻는다. 5) view index.html => index.html파일을 읽기 전용으로 파일을 연다. 참고로 저장할 때 ':wq!'형식으로 ! 표를 붙이면 읽기전용이라도 저장된다 6) vi + index.html => index.html파일을 열면서 커서의 위치를 마지막라인에 둔다. 7) vi +/posein /etc/passwd => /etc/passwd 라는 파일을 열면서 posein이라는 문자열이 있는 위치에 커서를 둔다.
3. vi 종료하기 (1) 설명: 모드에 대한 설명이 아래에 나오지만 미리 종료에 대해 설명하면 일단 [ESC]키를 눌러 명령모드로 전환한 후, 필요에 맞게 다음 중 하나의 키워드를 사용하면 된다. (2) 명령 :wq => 파일을 저장한 후 종료한다. 같은 명령으로는 ZZ 또는 :x 가 있다. :q! => 편집하여 변경된 내용을 저장하지 않고 강제 종료한다. :q => 편집중인 내용이 없는 경우, vi를 종료한다. :w => 편집중인 파일 내용을 저장한다. vi는 종료하지 않는다.
4. vi편집기의 모드 (1) 설명: vi편집기에는 크게 2가지모드로 구분된다. 첫번째는 명령모드(command mode)이고, 두번째 는 입력모드(input mode)또는 편집모드라고 한다. 또 명령모드는 다시 일반명령모드와 ex명령모드로 구분된다. 명령모드상태에서 입력명령(i,I,a,A,o,O)을 실행하면 입력모드로 전환된다. 입력모드에서 타이핑한 문자들이 문서에 삽입된다. 여기에서 다시 [ESC]키를 누르면 명령모드로 돌아온다. 명령 모드에서 ':'를 입력하면 화면 아래쪽에 ':'라는 프롬 프트가 나타나게 되는 데 이것이 ex명령모드이다. 참고)입력모드 키워드가 위 나열한 것외에 (c,C,s,S,R)등이 있다.
(2) 모드 1) 명령모드 : vi라고 입력한뒤 처음 접하는 모드 ㄱ. 커서 이동 명령 h : 왼쪽으로 이동 j : 아래로 이동 k : 위로 이동 l : 오른쪽으로 이동 w : 다음 단어의 처음으로 이동 - : 앞 라인의 첫문자로 이동 ^ : 라인의 첫 문자로 이동 $ : 라인의 맨 끝으로 이동 + : 다음 라인의 첫문자로 이동 0(zero) : 첫번째 열로 이동 G : 제일 끝줄로 이동 nG : n번째 행으로 이동 gg : 파일의 처음으로 이동 ( : 문장의 처음으로 이동 ) : 다음 문장의 처음으로 이동 { : 문단(paragraph)의 처음으로 이동 } : 다음 문단의 처음으로 이동 H : 화면의 첫 라인으로 이동 M : 화면의 중간으로 이동 L : 화면의 끝라인으로 이동 ctrl+b(back) : 한 화면 위로 이동 ctrl+f(forward) : 한 화면 아래로 이동 ctrl+u(up) : 반 화면 위로 이동 ctrl+d(down) : 반 화면 아래로 이동 e : 한 단어 뒤로 이동 b : 한 단어 앞으로 이동 :0(zero) : 줄의 제일 처음으로 이동 :$ : 줄의 제일 끝으로 이동 ㄴ. 편집상태로 진입 : 입력모드로 전환하는 키워드이고 하단에 'INSERT' 등과 같은 문자열이 표시된다. i : 현재 커서 위치에 삽입 a : 현재 커서 위치 다음에 삽입 o : 현재 커서가 위치한 줄의 아랫줄에 삽입 I : 현재 커서가 위치한 줄의 제일 앞에 삽입 A : 현재 커서가 위치한 줄의 제일 뒤에 삽입 O : 현재 커서가 위치한 줄 위에 삽입 ESC : 명령모드로 재전환 ㄷ. 복사하기와 붙이기 Y : 현재 커서가 위치한 줄을 버퍼에 복사한다. yy : Y와 같다. yw : 현재 커서가 위치한 단어를 버퍼에 복사한다. 'n'Y : 현재 커서가 위치한 줄에서 아래로 n개 만큼의 줄을 버퍼에 복사한다. 'n'yy : nY와 같다. 'n'yw : 현재 커서가 위치한 단어로 부터 뒤로 n개의 단어를 버퍼에 복사한다. yh : 커서의 왼쪽 문자를 복사한다. yl : 커서가 위치한 문자를 복사한다. yB : 커서의 왼쪽 비공백 단어를 복사한다. yW : 커서의 오른쪽 비공백 단어를 복사한다. y0 : 커서 왼쪽부터 라인의 처음까지 복사한다. p : 버퍼에 들어 있는 내용을 현재 커서가 위치한 줄의 아래에 붙인다. P : 버퍼에 들어 있는 내용을 현재 커서가 위치한 줄의 위에 붙인다. ㄹ. 지우기 x : 현재 커서 위치의 문자를 지운다.(dh와 동일) X : 커서 왼쪽의 문자를 지운다.(dl과 동일) dd : 현재 커서가 위치한 줄을 지운다. (단어 뒤의 스페이스 포함) 'n'dd : 현재 커서가 위치한 줄에서 아래로 n개 만큼의 줄을 지운다. dw : 현재 커서가 위치한 단어를 지운다. db : 현재 커서의 왼쪽 단어를 지운다. 'n'dw : 현재 커서가 위치한 단어로 부터 뒤로 n개 만큼의 단어를 지운다. dB : 현재 커서 왼쪽 비공백 단어를 지운다. dW : 현재 커서 오른쪽 비공백 단어를 지운다. d$ : 현재 커서가 있는 라인부터 끝까지 지운다.(D와 동일) - d0 : 커서 왼쪽부터 라인의 처음까지 지운다. ㅁ. 바꾸기 r : 현재 위치의 문자를 바꾼다. R : 현재 커서 위치부터 원하는 만큼 다른 문자로 바꾼다. cb : 현재 커서 왼쪽 단어를 바꾼다. cw : 현재 위치의 단어를 바꾼다. cc : 현재 커서가 위치한 줄을 바꾼다. c$ : 커서부터 라인의 끝까지 바꾼다.(C와 동일) c0 : 커서 왼쪽부터 라인의 처음까지 바꾼다. C : 현재 커서가 위치한 곳으로부터 줄의 끝까지 바꾼다. 'n'cw : 현재 위치로부터 'n'개의 단어를 바꾼다. 'n'cc : 현재 위치로부터 'n'개의 줄을 바꾼다. ㅂ. 기타 ctrl+g : 현재 편집하고 있는 파일의 정보를 보여준다. shift+v : 블록을 지정한다. u : 방금 한 명령을 취소한다. U : 현재 커서가 위치한 줄에 대한 편집 명령을 취소한다. . : 방금한 명령을 되풀이 한다. 'n'. : 방금한 명령을 n번만큼 되풀이 한다. J : 현재 줄과 다음 줄을 합한다. ZZ : 현재 내용을 저장하고 끝낸다. /exp : 'exp'와 같은 내용을 현재 위치 다음부터 찾는다. ?exp : 'exp'와 같은 내용을 현재 위치부터 위쪽으로 찾는다. n : 앞에서 찾은 내용을 현재 위치 다음부터 찾는다. N : 앞에서 찾은 내용을 반대 방향으로 계속 찾는다. >> : 현재 커서 위치 줄을 오른쪽으로 한 열씩 이동한다. << : 현재 커서 위치 줄을 왼쪽으로 한 열씩 이동한다. ~ : 현재 커서가 위치한 문자의 대소문자를 서로 변환한다. ctrl+l : 화면 다시 그린다. ! : vi편집중에 shell명령을 내린다. 3) ex명령모드 : ex란 초기 유닉스에서부터 쓰이던 line editor이다. vi는 자체 명령어외에 ex편집기 명령어를 지원한다. 명령모드에서 ':'누르면 화면 아래쪽에 ':'라는 프롬프트가 나타나면서 ex명령모드로 들어간다. ㄱ. 명령 :w => 현재 내용을 저장한다. :w filename => 현재 내용을 지정된 파일 이름으로 저장한다. :w! => 강제로 덮어쓰기를 한다. :q => 그냥 종료한다. 약간이라도 변경사항이 있으면 종료안된다. :wq => 현재 내용을 저장하고 종료한다. :wq filename => filename 으로 저장하고 종료한다. 새이름으로 저장할 때 쓴다. :q! => 현재 내용을 저장하지 않고 종료한다. :e filename => 새로운 파일을 편집한다. :r filename => 현재 커서 위치 다음에 파일을 읽어 삽입한다. :14 r filename => 14행 이후에 파일을 읽어 삽입한다. :10 => 10번째 줄로 커서를 이동시킨다. :10, 20d => 10번째 행에서 20번째 행까지 지운다.
(참고) 줄 번호를 쓸 때 '.'는 현재 줄을, '$'는 끝줄을 의미하므로 ':3,$d'는 3번째행에서 끝행까지 지운다는 의미가 된다. 또 첫줄부터 현재 커서가 위치한 줄까지를 지우려면 ':1,.d'라고 쓰면 된다.
ㄴ. 문자열의 치환 :s/문자열/새문자열 => 커서가 위치하고 있는 줄의 첫번째 해당문자열을 새문자열로 치환한다. :s/문자열/새문자열/g => 커서가 위치하고 있는 줄의 모든 해당문자열을 새 문자열로 치 환한다. :1,$ s/문자열/새문자열/g => 파일 전체에 대해 해당문자열을 새문자열로 치환한다. :%s/문자열/새문자열/g 와 같다.
5. vi편집기의 환경설정 (1) 설명 : vi환경설정을 위해서는 명령모드에서 :set을 사용한다. (2) 사용법 1) 설정 set [환경변수][=값] 2) 해제 set no환경변수 (3) 환경변수 1) ignorecase : 문자열을 검색할 때 대소문자에 관계없이 검색한다. 2) number : 행의 앞에 행번호를 붙여준다. 약자로 'nu'라고 해도 된다. 3) autoindent : 라인변경시 커서의 위치를 바로 위라인의 수준과 같이 해준다. 프로그램작성시에 용이하다. 약자로 'ai'라고 해도 된다. 4) showmatch : '}'또는 ')'를 입력하였을 경우 짝이되는 '{','('를 찾아 커서가 1초동안 머무르 다 돌아온다. 이 기능은 C등의 프로그램을 작성할 때 편리하다. 약자로 'sm'이라고 해도 된다. 5) showmode : 화면 아래쪽에 현재 모드를 표시한다. 즉 편집모드인 경우에 'INSERT'등의 값으 로 표시해준다. 기본값으로 설정되어 있다. 6) tabstop : 탭의크기를 표시한다. '=n'를 붙이면 탭의크기를 n값에 따라 부여할 수 있다. (4) 사용예 1) :set => 여러가지 환경 변수를 설정한다. set all하면 현재 설정되어 있는 환경변수를 보여준다. 2) :set nu => 행의 앞에 행번호를 표시한다. ':set number'와 같다. 3) :set nonu => 행의 앞에 붙은 행번호 표시를 없앤다. 4) :set ai => [Enter]키를 입력하면 행을 바꾸었을 경우 위 줄과 같은 열에 커서를 위치시킨다. 5) :set noai => 'ai'설정을 해제한다. ':set noautoindent'와 같다. 6) :set ignorecase => 명령모드에서 문자열을 검색시에 대소문자를 구분하지 않는다. 즉 '/linux'라고 입력하면 linux, Linux, LINUX 등의 모든 문자열을 찾아준다. 7) :set noignorecase => 검색시에 대소문자를 구분하도록 한다. 8) :set tabstop => 현재 설정된 탭의 크기(기본값은 4)를 보여준다. 9) :set tabstop=8 => 탭의 크기를 10으로 바꾼다. 10) :set noshowmode => 리눅스에서는 기본적으로 모드를 표시해준다. 즉 입력모드인 경우에는 화면하단에INSERT 등을 표시해준다. 위와 같이 명령을 내리면 모드전환을 해도 표시해주지 않는다. (5) 관련파일 : .exrc 1) 설명: set명령을 사용자의 홈 디렉토리의 .exrc(또는 .vimrc)안에 써 놓으면 vi가 시작될 때 디폴트로 설정되어 시작하게 된다. 2) 사용법 set [환경변수] [값] 3) 사용예 [posein@www posein]$ cat .exrc set nu set ai => vi편집기 실행할 때마다 각 행 앞에 행번호를 붙여주고 autoindent를 적용한다. ':'는 적지 않는다.
vsftpd는 UNIX 시스템에서 사용할 수 있는 free FTP 서버(라이센스는 GPL)이다. vsftpd가 내세우고 있는 것은 보안, 성능, 안정성이다. 지금까지 vsftpd의 자체 보안 문제가 있어 보안권고가 나온 적은 없다.(Redhat의 rpm 패키지중에 tcp_wrappers 지원없이 만들어져서 업데이트 rpm은 나온 적 있음)
* 지원 및 테스트된 OS
- Linux (Redhat, SuSE, Debian) - Solaris (버전에 따라 IPv6나 inet_aton함수때문에 설치가 잘 안될 수 있음) - FreeBSD, OpenBSD - HP-UX - IRIX
* 주요 기능
- 가상 IP별 별도의 환경 설정 기능 (설정파일의 listen_address= 이용) - 가상 사용자 설정 - 전송 대역폭 지정 - PAM 지원 (버전 1.2.0부터는 PAM을 통한 wtmp에 로긴 로그를 남김) - xferlog 표준 로그 파일보다 상세한 자체 로그 파일 형식 지원 - Standalone 방식과 inetd(xinetd)를 통한 운영 모두 지원 - IP별 다른 환경 파일 지정 기능 (tcp_wrappers와 함께 사용할 때) - ...
1. vsftpd 설치 ※ 설치는 Redhat 기준. 솔라리스의 PAM에 대한 것은 README.solaris 파일 참조한다.
한글로 된 파일명을 전송할 때 로그에 파일명이 ???? 로 남지 않도록 logging.c 파일을 연 후 140번째 줄의
str_replace_unprintable(p_str, '?');
를 다음처럼 주석 처리한다.
/* str_replace_unprintable(p_str, '?'); */
또한 tcp_wrappers를 통한 접속제어를 사용하려면 builddefs.h 에서
#undef VSF_BUILD_TCPWRAPPERS 를 #define VSF_BUILD_TCPWRAPPERS 로 바꾼다.
# make # make install (vsftpd 데몬, man page, xinetd 용 설정 파일 설치) # cp vsftpd.conf /etc (환경설정 파일 복사) # chmod 600 /etc/vsftpd.conf # cp RedHat/vsftpd.pam /etc/pam.d/vsftpd (PAM 설정 파일 복사)
즉, /etc/ftpusers 파일에 존재하는 ID는 접속할 수 없게된다.(sense=deny)
# FTP 접속을 허용하지 않을 ID를 등록한다. # /etc/passwd를 참조해서 설치할 서버의 환경에 맞게 등록 root bin daemon adm lp sync shutdown halt mail news uucp operator games nobody smmsp xfs gdm mysql
2. vsftpd.conf 의 주요 설정
# anonymous 사용자의 접속 허용 여부 (default = YES) # 공개된 형태의 FTP 서버로 운영할 것이 아니라면 NO로 한다. anonymous_enable=NO # 로컬 계정 사용자의 접속 허용 여부 (default = NO) local_enable=YES
# anonymous 사용자가 파일을 업로드 할 수 있는지 여부 (default = NO) # anon_upload_enable=YES # anonymous 사용자의 디렉토리 생성 허용 여부 (default = NO) # anon_mkdir_write_enable=YES
# 파일 전송 로그를 남길 것인지 여부 (default = YES) xferlog_enable=YES # xferlog 표준 포맷으로 로그를 남길지 여부 (기본 설정파일은 YES) # 아래에서 NO로 설정했을 때를 설명함 xferlog_std_format=YES # 파일 전송 로그 파일명 xferlog_file=/var/log/vsftpd.log
# FTP 서버 접속할 때 로긴 메시지 (default = vsFTPd 버전번호) # 한글 사용 가능 # ftpd_banner=Welcome to blah FTP service.
# ------------------------------------------------------------------- # 기본 설정 파일에는 없는 설정값으로 필요한 설정만 추가한다. # ※ 중요한 설정은 굵은 글씨로 표시 # -------------------------------------------------------------------
# PAM 파일명을 지정 (설치할 때 /etc/pam.d/vsftpd명으로 복사함) pam_service_name=vsftpd
# wtmp에 로그 남기기 (YES로 해야만 last 명령어로 접속 여부 확인 가능) session_support=YES
# 사용자가 자신의 home directory를 벗어나지 못하도록 설정 chroot_local_user=YES
# 새로운 디렉토리에 들어갔을 때 뿌려줄 환경 메시지를 저장한 파일명 # message_file=.message
# xferlog 형식으로 log를 남기려면 (위에서 이미 YES로 했음) # xferlog_std_format=NO # # - xferlog 표준 포맷은 로긴, 디렉토리 생성등의 로그를 남기지 않음 # 그러나 vsftpd 스타일 로그는 이를 포함한 보다 상세한 로그를 남김 # - vsftpd 스타일 로그 예 # # Sun Jul 12 01:38:32 2003 [pid 31200] CONNECT: Client 127.0.0.1 # Sun Jul 12 01:38:34 2003 [pid 31199] [truefeel] FAIL LOGIN: Client 127.0.0.1 # Sun Jul 12 01:38:38 2003 [pid 31199] [truefeel] OK LOGIN: Client 127.0.0.1 # Sun Jul 12 01:38:41 2003 [pid 31201] [truefeel] OK MKDIR: Client 127.0.0.1, /mp3 # Sun Jul 12 01:39:06 2003 [pid 31201] [truefeel] OK UPLOAD: Client 127.0.0.1, /델리 # 스파이스 5집 - [04]키치죠지의 검은 고양이.mp3, 6855473 bytes, 3857.39Kbyte/sec
# 전송속도 제한 (0은 제한없음, 단위는 초당 bytes) anon_max_rate=0 local_max_rate=0 trans_chunk_size=0
# 최대 접속 설정 (단 xinetd를 통하지 않고 standalone으로 동작할 때만 사용 가능) # standalone을 위해서는 listen=YES 추가하고 별도로 vsftpd를 띄워야 함 # # max_clients=최대 접속자 수, max_per_ip=IP당 접속 수 # max_clients=100 # max_per_ip=3
# Standalone 으로 운영할 때 listen=YES. 포트 변경을 원할 경우 listen_port 설정 # 디폴트 포트는 21번 포트이다. # listen=YES # listen_port=21
필요한 설정이 끝났으면 xinetd를 재실행한다.
# /etc/rc.d/init.d/xinetd restart
3. 문제 해결
1) ftpwho 같은 명령은 있나? 또한 last를 해도 접속된 걸 확인할 수가 없는데 방법이 없나?
ftpwho 형태의 명령은 없으며 임시적으로 다음 명령어 등으로 확인할 수 있다.
# ps -ef|grep vsftpd # fuser -v ftp/tcp
vsftpd v1.2.0이상부터 PAM을 통해 wtmp에 로그를 남기므로 last로 접속여부를 확인할 수 있다.
2) 한글 파일명이 전송될 때는 vsftpd.log 에 ???? 로 남는다. 해결책은?
vsftpd는 출력할 수 없다고 판단하는 ASCII 코드 31 이하, 128~159, 177 문자를 모두 ? 로 바꿔서 저장을 한다. 따라서 이 부분을 처리하지 않고 저장하도록 소스를 수정한 후 컴파일하면 해결된다.
3) 사용자가 홈디렉리를 못 벗어나게 하고 싶는데?
/etc/vsftpd.conf에 다음을 추가한다. standalone으로 FTP서버가 동작중이면 재실행 필요.
5) ID/비밀번호가 정확히 맞는데 로긴할 때 자꾸 530 Login incorrect. 라고 나온다.
/etc/ftpusers (또는 vsftpd.ftpusers)에 등록된 사용자인지 확인한다. 여기에 등록된 사용자는 로긴할 수 없다. 이럴 때 /var/log/messages에 다음과 같은 로그가 남는다.
Aug 16 22:21:52 truefeel vsftpd: PAM-listfile: Refused user xxxxxxxx for service vsftpd
6) standalone으로 운영하고 싶다. (즉, apache나 sendmail처럼 xinetd 통하지 않고 운영을 원한다.)
/etc/xinetd.d/vsftpd (vsftpd가 아닌 다른 파일명일 수 있음) 에서 disable = yes 로 변경하여 xinetd로 서비스 하지 않도록 설정한다. xinetd 를 재실행하면 이제 xinetd를 통한 ftp 서비스는 종료된다.
레드햇의 경우 /etc/rc.d/init.d/xinetd restart
이제 vsftpd 데몬를 실행한다. (소스로 설치시 기본 경로는 /usr/local/sbin)
# /usr/local/sbin/vsftpd &
7) 다른 포트(기본 21번)를 사용하고 싶다. (예를 들어 11121번 포트를 원할 때)
* xinetd를 이용하는 경우
/etc/service 에 'ftp2 11121/tcp' 한 줄을 추가한다. 그리고 /etc/xinetd.d/vsftpd (vsftpd가 아닌 ftp와 같은 다른 파일명일 수 있음) 에서 service ftp 를 service ftp2로 바꾸고, xinetd 를 재실행한다.
* standalone으로 운영하는 경우
/etc/vsftpd.conf 에서 listen_port=11121 을 추가하고 vsftpd 서버를 재실행한다.
바뀐 포트로 운영중인지 확인은 netstat -atnp(리눅스) 또는 netstat -an(그 이외 유닉스)
처음 Client가 Server로 21번 포트로 접속을 맺게 되는데 이 Session을 Command Session이라고 하며, 이 Command Session을 통해 사용자는 Server에게 사용자 ID와 Password를 전달해서 인증을 받는다. 인증을 거친 Client는 pwd, dir, get, put … 등의 원하는 작업에 해당하는 명령어를 전달한다.
FTP를 통해 실제 파일을 주고 받을 때는 새로운 Session이 하나 더 연결되는데 이를 Data Session이라고 한다. Data Session은 Server에서 자신의 출발지 포트를 20번으로 하고 Client로 1024 이상의 포트와 접속을 맺는다. 이 Data Session을 통해 Client는 Server로부터 파일을 다운로드 할 수 있고 Server로 업로드를 하게 된다.
그러나 이런 이유로 FTP Gateway설정을 해서 방화벽이 내부 사용자들의 FTP 접속을 대행하게 된다.
방화벽이 내부 사설 PC의 FTP접속 요구를 가로채서 방화벽이 대신 Server와 접속을 하게 된다. 방화벽이 Server와 Clinet 중간에서 Data의 흐름을 중개하게 된다.
1-2. Passive Mode
Port Mode (Active Mode)가 Client에서 Server로 Command Session 접속을 하고, Server에서 Client로의 Data Session을 연결하게 되는 반면, Passive Mode는 Client가 Server로 Command Session과 Data Session을 모두 연결하는 방식이다.
내부 사설 PC에서 Server로 Command와 Data Session을 모두 연결하기 때문에 내부에서 외부로 FTP 접속시 Passive Mode로만 접속한다면 방화벽에서는 FTP Gateway를 설정할 필요가 없다
2. vsFTP 구축하기
2-1. 패키지 설치
# rpm –qa vsftpd
# yum install vsftpd
# ls /var/ftp/
pub: pub 디렉토리가 생성되었는지 확인
2-2. 설정 확인
# telnet localhost 21
Trying 127.0.0.1…
Connected to localhost.localdomain (127.0.0.1)
Escpe character is ‘^]’
220 (vsFTPd 2.0.5)
user ftp
331 Please specify the password.
pass ftp@mail.net
230 Login successful.
quit
221 Goodbye.
Connection closed by foreign host.
3. 환경 설정 (Upload 설정 방법)
# vi /etc/vsftpd/vsftpd.conf
다음 행의 # 주석을 제거한다.
27행 : anon_upload_enable=YES
31행 : anon_mkdir_write_enable=YES
# cd /var/ftp
# ls –l
drwxr-xr-x2rootroot 4096 Aug 29 00:50 pub
# chown ftp.ftp pub/: 소유자.그룹 을 ftp로 바꾼다
# chmod –R 757 pub/: 일반유저도 write 할 수 있게 설정
4. ftp 명령어 (Client에서 사용)
help, ?: 도움말
cd {Directory}: 해당 디렉토리로 이동한다
chmod {File}: 원격의 FTP 서버에 있는 파일이나 디렉토리의 퍼미션을 조정한다
dir {Directory}: 디렉토리 리스트를 알아본다. ls와 동일하다
delete {File}: 파일을 삭제한다
mdelete {File}: 여러 개의 파일을 동시에 삭제한다
exit: 원격 FTP서버의 접속을 종료한다
quit: 접속을 종료한다
get {File}: 원격 FTP 서버에 있는 파일을 자신의 로컬 시스템으로 가져온다
put {File}: 로컬 시스템에 있는 파일을 원격의 FTP 서버로 업로드 한다
mget {File}: 원격 FTp 서버에 있는 여러 개의 파일을 동시에 다운로드 할 때 사용한다
mput {File}: 로컬 시스템에 있는 여러 개의 파일을 동시에 업로드 할 때 사용한다
size {File}: 원격 FTP 서버에 있는 파일의 크기를 출력한다
mkdir {Directory}: 원격의 FTP 서버에 새로운 디렉토리를 생성한다
rmdir {Directory}: 원격의 FTP 서버의 디렉토리를 삭제한다
pwd: 원격 FTP 서버의 현재 위치를 출력한다
status: 현재의 상태를 출력한다
nlist {Directory}: 원격의 FTP 서버에 있는 DIR 서브 디렉토리 리스트를 출력한다
open {FTP host}: 원격의 FTP host로 접속한다
rename{name1 name}: 원격의 FTP 서버에 있는 파일이나 디렉토리의 이름을 name1에서 name2
위와같이 설정합니다. 접속하면 /etc/vsftpd.chroot_list 파일이 없다고 에러가 나게 됩니다.
단순히 touch /etc/vsftpd.chroot_list 이렇게 파일을 만들어 주면 됩니다.
그리고 특정유저는 제외하려면 /etc/vsftpd.chroot_list 파일에 사용자 계정을 넣어줍니다.
4) "."으로 시작하는 숨김파일을 기본적으로 보이게 하려면?
리눅스에서 "."으로 시작하는 파일은 숨김 파일입니다. 하지만, 다른 os에서는 "."으로 시작해도 숨김파일으로 취급하지 않는 경우가 있습니다. 이런경우 항상 "."으로 시작하는 파일을 보여주려면 다음과 같이 설정합니다.
force_dot_files=YES
5) ftp 접속시 파일과 디렉토리의 소유권을 숨기려면?
특수한 목적으로 파일 및 디렉토리의 소유자를 숨길 경우가 있습니다. 이런 경우 다음과 같이 설정하면, ftp라는 사용자로 보이며, 본 ID는 보이지 않습니다.
hide_ids=YES
6) 하위디렉토리의 파일 및 디렉토리를 볼수 있는 ls -R 명령 허용하려면?
하위디렉토리 리스트를 보여주기 위해서 ls -R 명령어를 내릴때가 있습니다. 이런경우 대부분의 ftp 서버는 부하등의 이유로 막아 두게 됩니다. vsftpd또한 기본적으로 막아 놓은 상태이며, 허용하기 위해서는 다음 지시자를 입력하세요.
ls_recurse_enable=YES
7) openssh에 chroot 패치가 된 것을 사용하는데 정책을 같이 적용하려면?
openssh에 패치를 가하면, ssh 또한 자기 home 디렉토리를 벗어나지 못하게 설정가능합니다. 이 정책은 /etc/passwd파일의 홈디렉토리 부분에 /home/사용자/./ 와 같이 "/./"을 붙여 사용자를 홈디렉토리로 제한하게 됩니다. 이 정책에 따라 적용하려면, 다음 옵션을 적용하시기 바랍니다.
passwd_chroot_enable=YES
8) 파일을 올렸는데 시간이 이상하게 보인다면?
대부분의 ftp서버에서 시간 표현은 표준시각(GMT)을 보여주게 됩니다. 국내에서만 사용하는 ftp서버는 다음 옵션으로 국내 시간으로 보여줄 수 있습니다.
use_localtime=YES
9) 전송속도를 제한하고 싶다면?
다운로드 받는 한 사용자가 네트웍 트래픽을 모두 사용해 버리는 것을 방지하기 위해서 대역폭을 조정해야 하는 경우가 있습니다. 다음 옵션으로 가능합니다. 뒤에 나오는 숫자의 단위는(Bytes/Sec) 입니다.
local_max_rate=300000
위 설정은 300KByte/Sec의 대역폭을 제공합니다.
10) 동시 접속자수를 제한하려면?
ftp서버에 접속할 수 있는 최대 접속수를 제한하려면, 아래의 설정으로 제한 가능합니다.
max_clients=10
위 설정은 동시에 10개의 연결으로 제한합니다.
11) 한 IP당 접속할 수 있는 동시접속 수 제한하려면?
ftp서버의 한 사용자가 대역폭을 모두 사용해 버리는 것을 방지하기 위해, 전송 속도를 제한하면, flashget 등의 유틸리티로 몇개의 접속으로 나눠 받으면 대역폭 제한을 우회 할 수 있습니다. 이런경우 한 IP에서 접속 가능한 동시접속 수를 제한하므로 해결 가능합니다.
max_per_ip=2
위 설정은 한 IP에서 접속할 수 있는 연결을 2개로 제한합니다.
12) PASSIVE 모드 사용시 사용하는 포트 범위를 제한하려면?
FTP에서 데이터 전송을 위해서 20번 포트를 사용합니다. 이경우 서버에서 클라이언트 쪽으로 연결을 하기 때문에 중간에 방화벽 또는 공유기등을 사용한다면, 정상작동하지 않을 수 있습니다. 이런 문제를 해결하기위해서 PASSIVE모드라는 것이 있고, 이 모드에서는 서버의 1024이후 포트를 사용합니다. 이 포트의 범위를 제한하기 위해서는 다음과 같이 설정합니다.
pasv_min_port=40000
pasv_max_port=50000
위 설정은 PASSIVE에서 사용할 포트를 40000~50000로 합니다.
13) mp3, wmv 등의 확장자를 가진 파일의 업로드를 금지하려면?
ftp를 통해 인증된 사용자가 파일을 올리는 것을 막는 방법은 거의 없었습니다. 이 vsftpd는 특이하게 특정파일 패턴을 제한하는 기능이 있습니다.
deny_file={*.mp3,*.wmv}
위 설정은 mp3, wmv 파일을 전송하지 못하게 하는 방법입니다.
14) 특정파일 패턴을 숨기려면?
특정파일이 서버내에는 존재하지만, ftp접속시 보여지지 않게 설정할 수 있습니다. 다음예를 보시기 바랍니다.
hide_file={*.mp3,.hidden,hide*,h?}
위 설정은 mp3파일, .hidden 파일, hide로 시작하는 파일을 보여지지 않게 하는 옵션입니다.
=========================================================================== # Firewall configuration written by system-config-securitylevel # Manual customization of this file is not recommended.
*filter
###local -A INPUT -p ALL -i $LO_IFACE -j ACCEPT -A OUTPUT -p ALL -o $LO_IFACE -j ACCEPT
### ssh server -A INPUT -p TCP --destination-port 22 -j ACCEPT -A OUTPUT -p TCP --source-port 22 -j ACCEPT
### ftp server ### -A INPUT -p TCP --destination-port 21 -j ACCEPT -A OUTPUT -p TCP --source-port 21 -j ACCEPT
### POSTGRESQL server -A INPUT -p TCP --destination-port 5432 -j ACCEPT -A OUTPUT -p TCP --source-port 5432 -j ACCEPT
이번시간에는 Iptables사용법과 기본적인 firewall구성법에 대해서 알아보도록 하겠다.
Iptables에 대해 배워보기에 앞서서 여기서 테스트한 환경은 다음과 같다.
CPU : AMD Duron 800Mhz OS : RedHat Linux 7.1 (Kernel 2.4.x) HDD : 13G RAM : 128M
이제 Iptables를 사용하기 위한 기본적인 설정에 대해서 알아보자. Iptables는 Kernel 2.4.x 기반의 리눅스 설치시에 기본으로 설치되어있고 /sbin 디렉토리 아래에 있다. 그리고 iptables와 ipchains는 동시에 사용할 수 없으므로 우선 ipchains의 모듈을 내려줘야 한다.
아래의 그림처럼 lsmod를 해보고 만약 ipchains 모듈이 올라와 있다면 rmmod ipchains 명령으로 모듈을 내려줘야 iptables 사용이 가능하다.
이제 Iptables에 대해서 본격적으로 알아보도록 하자.
기본적으로 Iptables에는 세가지 chain이 있고 모든 패킷은 이 세가지 chain중 하나를 통과하게 된다. 이 세가지 chain은 INPUT, OUTPUT, FORWARD chain인데 우선 여러분의 컴퓨터로 들어가는 모든 패킷은 INPUT chain을 통과한다. 그리고 여러분의 컴퓨터에서 나가는 모든 패킷은 OUTPUT chain을 통과한다. 그리고 하나의 네트워크에서 다른 곳으로 보내는 모든 패킷은 FORWARD chain을 통과한다.
Iptables가 작동하는 방식은 이들 각각의 INPUT, OUTPUT, FORWARD chain에 당신이 어떠한 rule을 세우는 지에 따라 달라진다. 예를 들어 당신이 HTML 페이지를 요청하기 위해 www.yahoo.com에 패킷을 보낸다면 이 패킷은 우선 당신 컴퓨터의 OUTPUT chain을 통과하게 된다. 그러면 kernel에서 OUTPUT chain의 rule을 확인하고 rule과 match가 되는지 확인을 하게된다. rule중에서 최초로 match되는 것에 의해 당신이 보낸 패킷의 운명이 결정되는 것이다. 만약 어떤 rule과도 match되지 않는다면 전체 chain의 정책이 ACCEPT냐 DROP이냐에 따라 패킷의 운명이 결정될 것이다. 그러고 나서 Yahoo! 에서 응답하는 패킷은 당신의 INPUT chain을 통과하게 될 것이다.
IP 주소 막기
이제 기초적인 개념에 대해서 알아봤으니 실제로 사용해 보도록 하겠다.
Iptable을 사용할 때에는 기억해야 할 많은 옵션들이 있으므로 man 페이지(man iptables)를 잘 활용하는 것이 중요하다. 이제 특정 IP를 조종하는 법에 대해서 알아보자. 우선 당신이 200.200.200.1 이라는 IP로부터 오는 모든 패킷을 막고 싶어한다고 가정하자. 우선 -s 옵션이 사용되는데 여기에서 source IP나 DNS name을 지칭할 수 있다. 그러므로 다음과 같이 함으로써 이 IP를 지칭할 수 있다.
./iptables -s 200.200.200.1
하지만 위처럼만 명령을 내리면 kernel은 위의 주소에서 오는 패킷을 어떻게 처리해야 할 지를 알 수가 없다. 그러므로 -j 옵션으로 그 패킷을 어떻게 처리해야 하는지 결정해야 한다. 일반적으로 3가지 옵션이 있는데 ACCEPT, DENY, DROP이다.
ACCEPT는 대충 예상할 수 있듯이 패킷을 허용하는 옵션이다. DENY 옵션은 컴퓨터가 연결을 허용하지 않는다고 메시지를 돌려 보내는 옵션이다. 그리고 DROP 옵션은 패킷을 완전히 무시해 버린다. 만약 우리가 이 IP에 대해 확실히 의심이 간다면 우리는 DENY 대신에 DROP을 사용해야 할 것이다. 그러므로 결과적으론 다음과같이 옵션을 주면 된다.
./iptables -s 200.200.200.1 -j DROP
하지만 이 명령만으로는 아직 컴퓨터가 명령을 이해할 수가 없다. 우리는 한가지를 더 추가해야 되는데 바로 어떤 chain의 rule로 적용시킬지 결정해야 하는 것이다. 여러분은 -A 옵션을 사용해서 이를 결정할 수 있다. 즉 아까 위에서 본 INPUT, OUTPUT, FORWARD 옵션 중에서 하나를 선택해야 하는 것이다. 이 옵션을 줌으로써 당신이 선택한 chain의 맨 아래부분에 새로운 rule이 추가될 것이다. 따라서 우리는 우리에게 들어오는 패킷을 차단하고 싶으므로 INPUT 옵션을 주면 되는 것이다. 그러므로 전체 명령은 다음과 같다.
./iptables -A INPUT -s 200.200.200.1 -j DROP
이 한 줄의 명령으로 200.200.200.1로부터 오는 모든 패킷을 무시할 수 있다. 옵션의 순서는 바뀌어도 상관이 없다. 즉 -j DROP이 -s 200.200.200.1 보다 앞에 가도 상관이 없다. 만약 그 반대로 200.200.200.1로 패킷이 못가도록 하려면 INPUT 대신에 OUTPUT을, -s 대신에 -d(destination) 옵션을 주면된다.
Service 차단하기
만약 우리가 해당 컴퓨터로부터 telnet 요청만 무시하고싶다면 어떻게 해야 하는가? 이것도 그다지 어렵지 않다. 일단 큰 범주로 나누어 봤을 때 적어도 3가지의 프로토콜 - TCP, UDP, ICMP - 가 있다. 다른 대부분의 서비스와 마찬가지로 telnet은 TCP 프로토콜로 작동한다. -p 옵션으로 우리는 프로토콜을 결정할 수 있다. 하지만 TCP라고만 옵션을 줘서는 컴퓨터가 인식하지를 못한다. telnet은 TCP프로토콜로 작동하는 특정 서비스에 불과하기 때문이다. 우선 우리가 프로토콜을 TCP로 설정한 다음에는 --destination-port 옵션으로 해당하는 port를 설정해 줘야한다. 우선 telnet의 포트번호는 23번이다. 포트번호 대신에 telnet이라 써도 상관없다. 여기서 source port 와 destination port를 혼동하면 안된다. 즉 클라이언트는 어떤 포트로도 작동할 수 있는 반면에 서버는 23번 포트로 작동하기 때문이다. 즉 특정 서비스를 차단하기 위해서는 -destination-port를 이용하면 되고, 그 반대는 -source-port를 이용하면 된다. 이제 이들 옵션을 합쳐서 아래와 같이 명령을 주면 된다.
그리고 IP의 영역을 선택하고 싶다면 200.200.200.0/24 와 같이 설정하면 된다. 이것은 200.200.200.* 에 해당하는 모든 IP를 선택하는 것과 같다.
선택적인 차단
이제 좀더 심화된 내용에 대해서 알아보자. 우선 여러분의 컴퓨터가 local area network(LAN)에 있고, Internet에 접속 가능하다고 가정한다. 알다시피 LAN은 eth0으로 Internet 연결은 ppp0으로 구분할 수 있다. 이제 다시 다음과 같이 가정해 보자. 우리는 telnet 서비스를 LAN상의 컴퓨터에게는 서비스하고 보안상 Internet상에서는 접근하지 못하도록 하고 싶다. 이것 역시 쉽게 구성할 수 있다. 우리는 input interface에 대해서는 -i 옵션을 output interface에 대해서는 -o 옵션을 사용할 수 있다. 즉 다음처럼 명령을 주면 된다.
이렇게 함으로써 우리는 LAN상의 사용자는 telnet을 사용하고 그밖에 Internet상의 사용자는 telnet 을 사용하지 못하도록 할 수 있다.
Rule 순서에 관하여 이제 다음 단계로 들어가기에 앞서서 rule을 조종하는 다른 방법에 대해서 간단히 알아보자. Iptables의 chain에서는 먼저 등록 된 rule이 효력을 발생하기때문에 등록을 하는 순서가 중요하다. 모든 것을 거부하는 설정이 먼저오게 되면 그 이후에 포트를 열어주는 설정이 와도 효과가 없다. 그러므로 허용하는 정책이 먼저오고 나서 거부하는 정책이 와야한다.
–A 옵션을 줌으로써 우리는 새로운 규칙을 chain의 맨 아래에 추가하게 된다. 즉 chain상의 상위 rule이 먼저 작동하기 때문에, 만일 새로 추가하는 rule을 먼저 작동시키기 위해서는 -I 옵션을 줌으로써 새로운 rule을 원하는 위치에 놓을 수 있다. 예를 들어 INPUT chain의 가장 위에 어떤 rule을 놓고 싶다면 “-I INPUT 1” 이라 명령하면 된다. 그리고 다른 위치로 놓고 싶다면 1을 다른 숫자로 바꿔주면 된다.
그리고 이미 위치된 rule을 다른 위치로 바꾸고 싶다면 -R 옵션을 주면 된다. -I 옵션을 주는 것과 마찬가지로 사용할 수 있는데 다만 -I옵션을 사용해서 1의 위치에 놓으면 다른 rule들이 밑으로 한칸씩 내려가는 반면 -R옵션을 사용해서 1의 위치에 놓으면 그 위치의 rule은 삭제된다.
그리고 끝으로 rule을 삭제하고 싶다면 -D옵션과 숫자를 사용하면 되고, -L 옵션을 사용하면 작성된 모든 rule의 목록을 보여주고, -F 옵션을 주면 해당 chain의 모든 rule을 삭제한다. 그리고 만약 chain을 명시하지 않았다면 모든 것을 flush할 것이다.
SYN Packets
좀더 심화된 내용에 대해서 알아보자. 우선 패킷들은 특정 프로토콜을 사용한다. 그리고 프로토콜이 TCP라면 역시 특정 port를 사용한다. 그러므로 여러분 컴퓨터의 모든 포트를 막음으로써 보안을 할 수 있을 것이다. 하지만 당신이 다른 컴퓨터에 패킷을 보내면 그 컴퓨터는 당신에게 다시 응답을 해야한다. 그러므로 만약 당신에게 들어오는 모든 포트를 막아버린다면 당신에게 응답하는 패킷도 결국 못 들어오므로 connection을 하는 의미가 없을 것이다.
하지만 다른 방법이 있다. 두 컴퓨터가 TCP connection으로 패킷을 주고 받는다면 그 connection은 우선 초기화가 되어야 한다.
이것은 바로 SYN packet이 담당한다. SYN packet은 단순히 다른 컴퓨터에게 주고 받을 준비가 되었다는 것만 알려주는 초기화 기능만을 한다. 이제 서비스를 요청하는 컴퓨터는 우선적으로 SYN packet을 보낸다는 것을 알게 되었다. 그러므로 들어오는 SYN packet만 막기만 하면 다른 컴퓨터가 당신 컴퓨터의 서비스를 이용하지 못하게 할 수 있고, 하지만 당신은 그들과 통신할 수 있는 것이다.
즉 이와 같이 하면 당신이 먼저 패킷을 보내서 요청이 들어오는 것이 아니면 모두 무시해 버리게 된다. 이 옵션을 사용하기 위해서는 선택한 프로토콜 뒤에 --syn이라고 명령을 넣으면 된다. 이제 인터넷으로부터 오는 모든 연결을 막기위해서는 다음과 같이 rule을 정하면 된다.
./iptables –A INPUT –i ppp0 –p tcp --syn –j DROP
당신이 만약 웹 서비스를 운영하는 것이 아니라면 이것은 유용한 rule이 될 것이다.
만약 당신이 웹서비스를 위해 하나의 포트(예를들어 80번-HTTP)만 열어두고 싶다면 역시 한가지 방법이 있다. 바로 “!” 마크를 사용하면 되는데 많은 프로그래밍 언어에서처럼 “!”은 “not”을 의미한다.
예를들어 80번 포트만 제외하고 모든 SYN packet들을 막고싶다면 다음과 같이 하면 된다.
마지막으로 한가지 남은 것이 있다. 이것은 chain의 정책을 바꾸는 것으로 INPUT과 OUTPUT chain은 디폴트로 ACCEPT로 정해져 있고, FORWARD chain은 DENY로 정해져 있다. 만약 당신의 컴퓨터를 라우터로 사용하려면 당신은 FORWARD chain의 정책을 ACCEPT로 설정하고 싶을 것이다.
이럴때 어떻게 해야하는가? 이것은 매우 간단하다. -P 옵션을 사용하면 된다. 즉 FORWARD chain을 ACCEPT로 정하기 위해선 다음과 같이 명령을 내리면 된다.
./iptables -P FORWARD ACCEPT
iptables, 스크립트로 만들어 사용하기
이번에는 iptable 명령어를 편리하게 스크립트로 만들어서 사용해 보자 일단 iptables라는 파일을 다음처럼 작성해 보자. 파일의 위치는 /etc/sysconfig/ 아래에 두도록 하겠다.
--begin script-- #!/bin/sh
# 우선 모든 Rule을 정리한다.
/sbin/iptables -F
# 다음으로 각각에 대한 정책을 세운다.
/sbin/iptables -P INPUT DROP /sbin/iptables -P OUTPUT ACCEPT /sbin/iptables -P FORWARD DROP
위의 스크립트는 하나의 예에 불과하고 기타 ssh나 ftp, samba등을 이용하기 위한 설정사항을 직접 작성해야 한다. 파일 작성이 끝났으면 파일에 실행권한을 줘야한다. 보안상 root만 실행할 수 있도록 권한을 변경한 후 위의 스크립트를 실행하면 된다.
확인을 하려면 /sbin/iptables –L 이라고 하면 방금 실행시킨 스크립트가 나올 것이다.
그리고 부팅시마다 실행을 시키려면 /etc/rc.d/rc.local 파일 맨 아래 부분에 다음처럼 넣으면 된다.
if [ -f /etc/sysconfig/iptables ]; then /etc/sysconfig/iptables fi
이번 시간에는 Iptables의 기초만을 알아보았다. 여기 있는 정보를 통해서 당신은 기본적인 firewall을 설정할 수 있을 것이다. 하지만 아직 많은 것들이 남아있다. 더 많은 옵션에 대해서 알아보기 위해서 man 페이지를 활용하기 바라고 Iptables에 관련된 심화된 문서들을 참고하기 바란다.
패킷필터링은 지나가는 패킷의 해더를 보고 그 전체 패킷의 운명을 결정하는 것을 말한다. (iptables의 경우 많은 개발중인 기능에서 헤더에 그치지 않고 data의 내용을 검토하기도 한다. 가장 대표적인것이 string match기능이다.)
*:(일반적으로 패킷은 헤더와 데이타를 가진다. 헤더에 필터링할 정보인 출발지IP:PORT,도착지 IP:PORT, checksum,프로토콜 옵셋등을 가지며 데이터는 각각의 전송데이터가 들어간다.)
리눅스 박스의 패킷필터링의 역사
리눅스는 커널 1.1버젼 부터 패킷필터링을 포함하기 시작했다. 제 1세대는 BSD의 ipfw을 기본으로 하였고 2.0버젼에서 ipfwadm이 사용되었으며 1998년에 2.2기반 패킷필터링툴인 ipchains를 내놓았다. 그리고 이글에서 논의하고자 하는 제 4세대 필터링툴인 iptables이 2.4커널을 위해 만들어졌다.
netfilter?
일반 iptables사용자들이 가장간과하기 쉬운부분중 한 부분이다. iptables이 패킷을 필터링 하는것이 아니다. 패킷필터링은 커널에 탑제된 netfilter기능으로 하며 iptables은 단지 netfilter의 룰을 세워줄 뿐이다. 즉 다시 말하자면 iptables은 룰셋구축 툴이라는 말이다.
[ 패킷필터링 ]
iptables에 대해
iptable에 기본 Chain은 아래와 같다.
INPUT chain FORWARD chain OUTPUT chain
위의 3가지가 기본 체인이다. 체인들의 모식도는 아래와 같다.
------>INPUT------> Linux Box ------>OUTPUT---------> ---------↕------------------------------↕ ---------└--------- FORWARD ----------┘
여러분의 Linux box를 도착지로 삼는 모든패킷은 INPUT Chain을 통과하게 되며 여러분의 Linux box에서 생성되 외부로 보내지는 모든패킷은 OUTPUT Chain을 통과하게 된다.
Forward chain은 *엄밀히 말하자면 도착지가 여러분의 Linux box가 아닌 패킷이 통과하게 되는 체인이다.
*:(다음문서에 다루게 될 Masqurading시에 패킷의 destnationIP정보는 여러분의 Linux box이지만 패킷의 최종도착지는 내부네트워크의 어떠한 컴퓨터일것이다)
지금 커맨드라인에 아래와 같이 쳐보기 바란다.
# iptables -A INPUT -j DROP
엔터키를 누르는 즉시 여러분의 Linux box로 오는 패킷은 모두 거부당할것이다. 즉 모든 통신이 끊어진다.
위의 룰을 굳이 말로 옮기자면
-A:룰을 추가한다 INPUT: 패킷이 들어오는 체인에 -j:패킷의 운명을 결정한다. DROP: 패킷을 버려라.
즉, INPUT체인으로 들어오는 패킷을 모두 버리는 룰을 추가하는 명령이다.
적용시킨 룰을 보고 싶다면
# iptables -L
이라는 명령을 치면된다.
-A와 같은 위치에 있는 옵션은 아래와 같다.
체인에 새로운 규칙을 추가하기 (-A) 체인의 어떤 지점에 규칙을 삽입하기 (-I) 체인의 어떤 지점의 규칙을 교환하기 (-R) 체인의 어떤 지점의 규칙을 제거하기 (-D) 체인에서 일치하는 첫번째 규칙을 제거하기 (-D)
이제 위에서 내린 룰을 지워 통신이 되게 하자. 아래와 같이 명령을 내리면 된다. # iptables -D INPUT 1 또는 # iptables -D INPUT -j DROP 하면 될것이다.
첫번째 방법은 index(룰의 순서)를 지정해서 지우는 방법이고, 두번째는 룰의 내용으로 지우는것이다.
-I,-R은 첫번째 방법과 유사하게 쓸수있다.
룰을 다시 세우고 목록을 보자.
# iptables -A INPUT -j DROP # iptables -L
살펴보면
Chanin INPUT (policy ACCEPT)
위와 같은 줄을 볼수있을것이다. 저 줄 밑에는 여러분들이 세운 룰의 정보를 볼수있을것이다.
(policy ACCEPT)를 설명하자면 여러분들이 세운룰에 해당되지 않을때 마지막으로 기본정책을 따라 패킷의 운명을 결정하게 된다. 여기서는 ACCEPT이므로 패킷은 받아드려질것이다. 아지만 이것을 DROP으로하면 패킷은 버려질것이다.
그리고 패킷필터링을 알아가면서 여러룰들을 세울것이다. 기본적으로 룰은 세워진 순서대로 패킷을 검사한다.
이제 기본정책을 바꾸어 보자.
# iptables -P INPUT DROP
위의 명령을 내리고 다시 iptables -L을 하면
Chanin INPUT (policy DROP)으로 된걸 볼수있다.
-P와 동등 위치의 옵션은 아래와 같다.
새로운 체인 만들기 (-N). 비어있는 체인을 제거하기 (-X). ※ 이 두옵션은 직접체인을 만들었을경우와 제어할경우에 해당된다. 기본체인(INPUT,OUTPUT,FORWARD) 에는 해당되지 않는다.
미리 만들어진 체인의 정책을 바꾸기 (-P) 어떤 체인의 규칙들을 나열하기 (-L) 체인으로부터 규칙들을 지우기 (-F) 체인내의 모든 규칙들의 패킷과 바이트의 카운드를 0 으로 만들기 (-Z)
[ 패킷의 목적지또는 출처 제어 ]
패킷출처 제어옵션 -s
# iptables -A INPUT -s 192.168.10.10 -j DROP
위에 같은 명령을 내렸다면 192.168.10.10으로 부터 온 패킷은 모두 버려지게 된다.
-s(--source,--src와 같은 옵션이다.) : 패킷의 출처 IP 지정
목적지 제어옵션 -d
# iptables -A INPUt -d 192.168.10.12 -j DROP
위와 같은 명령을 내렸다면 192.168.10.12의 IP를 도착지로 가지고있는 패킷은 모두 버려지게된다.
-d(--destination,--dst와 같은 옵션이다.): 패킷의 도착지 IP지정
※ IP지정 이외에 몇 가지 방법이 더 존재한다. -s www.xxxx.com : 도메인으로 제어 -s 192.168.10.0/24 : 네트워크 또는 집단으로 제어 -s 192.168.10.0/255.255.255.0 :위와 동일
※ 보통 프로그래밍 약속기호처럼 !는 역('not')이라는 것을 표시한다. ex) -s ! 192.168.10.10 이라고 하면 "출발지가 192.168.10.10이 아닌" 이라는 뜻이된다.
[ 프로토콜 제어 ]
프로토콜제어 옵션은 -p이다
-p옵션의 인자는 TCP,UDP,ICMP가 될수있다.
# iptables -A INPUT -p TCP -j ACCEPT
라는 명령을 내렸다면 tcp프로토콜을 쓰는 모든 패킷은 ACCEPT에 의해 허락될것이다.
※ -p의 인자로 TCP,UDP,ICMP의 프로토콜번호를 알고있다면 번호를 써도 상관없다.
포트 제어
포트제어 옵션은 --sport와 --dport이다
--sport는 패킷의 출발지 포트이다.( --source-port와 같은 옵션이다.)
--dport는 패킷의 도착지 포트이다.( --destination-port와 같은 옵션이다.)
# iptables -A INPUT -p tcp --dport 80 -j DROP
위와 같은 명령은 tcp프로토콜의 80(www:웹서버포트)번 포트를 목적지로 하는 패킷을 버리는 것이다.
※ --dport나 --sport의 인자로 서비스이름을 적어도 된다. ex) --dport www
※ 여러 포트를 지정해야 된다면 --dport 1024:65535 와 같이 지정할수있다. 뜻은 1024 부터 65535번까지라는 뜻이다.
이제까지는 별 다른 지식이 없이도 이해할수있는 부분이었다. 하지만 지금부터 나오게될 내용은 tcp/ip의 기반적인 지식을 가지고있어야 이해하기 쉬울것이다. tcp/ip지식이 필요한 옵션에 대해서는 그에따른 자세한 설명을 하겠지만 이해가 되지 않는 부분은 다른 문서나 책을 찾아보길 바란다.
[ 패킷의 행동 유형에 따른 필터링(--tcp-flags,m state --state) ]
! 주의 : 밑에 나오는 모든옵션은 TCP프로토콜옵션(-p TCP)가 먼저 선행되어 있어야 적용되는 옵션이다.
1) --tcp-flags 옵션은 상태에 따라 유용하게 설정할수있다. 이 옵션을 설정하는 가장 큰 예는 한방향으로만 통신이 되게끔설정하기 위해 많이 사용한다. tcp/ip는 3핸드쉐이크의 접속방식이다. 즉. 접속요청패킷,접속허가 패킷,확인패킷
접속 단계를 좀더 자세하게 보면
C: Client S:Server
1) C --------- syn -------▷ S 2) C ◁------- syn ack ----- S 3) C --------- ack -------▷ S
이런식으로 접속절차가 이루어진다.
syn패킷은 접속요청 플래그(syn)가 설정된 패킷이므로 syn패킷만 막으면 상대편에서 접속을 할수 없다는 것이다.
※ Dos공격의 일종인 Syn Flooding이 서버에 위에서 말한 syn형패킷을 무수히 많이 보내는 것이다.
이제 본격적으로 --tcp-flags옵션으로 syn 접속형 패킷을 막는것을 하겠다.
# iptables -A INPUT -p TCP --tcp-flags SYN,RST,ACK SYN -j DROP
--tcp-flags에 첫번째 인자는 검사할 리스트 마스크이다. 두번째 인자는 설정되어있어야할 플래그다. 즉 syn,rst,ack플래그중 syn이 set이 1로 되어있으면 위의 --tcp-flags설정에 해당이 되므로 패킷은 DROP된다.
위의 옵션과 같은 뜻을 가진것이 있는데 그것은 --syn이다. --syn은 '--tcp-flags SYN,RST,ACK SYN'의 뜻을 가지고 있다.
2) --tcp-flags보다 더 간단하게 설정하는 방법이 있다. 바로 tcp의 상태천이 다이아그램을 축소시켜 놓은듯한 느낌을 받는 상태에 따른 패킷분류를 iptables은 지원한다.
이것은 확장기능이므로 -m 플래그로 설정은 한다.
사용옵선은 -m state --state 이다.
인자값으로 들어가야할 상태에따른 리스트는 아래와 같다.
NEW : 새로운 접속을 만드는 패킷
ESTABLISHED :존재하는 접속에 속하는 패킷 (즉, 응답 패킷을 가졌던 것) 즉 접속이 허가되고 통신하면서 발생되는 패킷이다.
RELATED :기존의 접속의 부분은 아니지만 연관성을 가진 패킷으로 . ICMP 에러 나 (FTP 모듈이 삽입 되어있으면) ftp 데이터 접속을 형성하는 패킷.
INVALID :어떤 이유로 확인할 수 없는 패킷. 알려진 접속과 부합하지 않는 ICMP 에러와 'out of memory' 등을 포함한다. 보통 이런 패킷은 DROP 된다.
이제 이 state 옵션을 사용해보자
위의 --tcp-flags옵션에서 예제와 같은 작용을 하는 룰을 만들어보겠다.
# iptables -A INPUT -p TCP -m state --state NEW -j DROP
왜 룰이 이렇게 되는지 차근차근 읽어보았다면 쉽게 이해가 될것이다.
일반적으로 서버는
# iptables -A INPUT -p TCP --dport 특정포트 -m state --state NEW,ESTABLISHED -j ACCEPT
이렇게 룰을 많이 세운다. 뜻은 tcp 특정 포트에 new:접속패킷과,established:통신패킷(정확히 쉽게 설명할 단어가 생각나지 않아 부적절하지만 통신패킷이라 부른다)을 허용하라.
그리고 클라이언트 측에서는 위의 state상태에서 NEW를 빼고 사용한다.
# iptables -A INPUT -p TCP --sport 특정포트 -m state --state ESTABLISHED -j ACCEPT
왜 NEW를 뺄까? 그 이유는 그 이유는 클라이언트입장에서 보면 접속을 허가해달라는 패킷이 필요없다는것이다. 더 쉽게 말하자면 클라이언트는 접속허가를 요청하는 위치이지 요청받는 위치가 아니라는 말이다. 그러므로 ESTABLISHED만 있으면 일반적으로 통신하는데 아무런 문제가 없다
그리고 주의깊게 본 사람이라면 위에 --sport가 쓰여진것을 볼수있을것이다.
왜 서버에서는 --dport로 제어를 하면서 클라이언트는 --sport로 제어를 할까?
지금 리눅스 박스라면 wget을 쓰던지 x-windows에서 브라우져를 쓰던지 아무런 웹사이트에 접속을 하고 바로 콘솔에서 'netstat -nat'라는 명령을 내려보자.
무슨말인지 알겠는가?
서비스를 한번이라도 해본적있는 사람이면 알겠지만 서버는 특정PORT를 열어놓고 접속을 기다린다. 클라이언트는 특정 서버에 접속을 하기 위해 별도로 포트를 생성하고 접속을 시도한다. 이때 클라이언트가 생성하는 포트번호는 1024이후의 랜덤값이다. 이런이유로 클라이언트입장에서는 --dport로 제어를 하지않는게 보통이다. 제어를 하더라도 상관없다. 하지만 그것은 상당한 비효율적인 룰이 될것이다.
[ftp를 위한 상태천이를 이용해 룰 설정]
ftp는 참 유별난 프로토콜이다. 특히 마스커레이드때 쓰이는 nat과 잘 맞지도 않을뿐더러. ftp서버에서 passive모드로 운영을 할시 iptables로 제어하고 싶다면 따로 모듈이 필요하다.
passive로 1025:65535까지 임이의 데이타 전송포트를 쓸때 상태천이로 제어를 하자면,보안상 NEW를 사용하지 않는다. 즉,새로운 접속을 허가하지 않고 RELATED로 기존접속에 관련된것만 접속을 허용한다.
즉 실제 룰을 보면 아래와 같다
# iptables -A INPUT -p tcp --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
※ 만약 NEW를 사용한다면 방화벽 구실을 못할것이다. 왜그런지는 직접 생각해보라 위에서 이미 충분히 설명하였다.
ftp에서 위처럼 RELATED로 방화벽룰을 설정했다면 ip_conntrack_ftp라는 모듈없이 연결이 제대로 되지 않을것이다.
ip_conntrack_ftp는 ftp서버의 ftp접속 추적 모듈이다.
[ 조각(Fragments) 처리하기 ]
때때로 하나의 패킷이 한 번에 한 회선을 통과하기에는 너무 큰 경우가 발생한다. 이 때는 패킷이 `조각'으로 나뉘어 여러 개의 패킷으로 전송된다. 받는 쪽에서는 이 조각을 모아 하나의 패킷으로 재구성한다.
패킷 필터링 HOWTO에서는 nat이나 접속추적을 할때에는 분절패킷이 하나의 패킷으로
재구성되어 필터링되기때문에 해당되지 않는다고 명시되어 있다.
하지만 위와 같은 상황이 아니라면 조각을 처리해야하나 안전성을 이유로 처리하지 않는 것을 권장하고 있다. 그 이유는 아래에 설명할것이다.
일반적으로 패킷이 분절(토막)될때 필터링을 할 정보인 특히 발신지 포트, 목적지 포트, ICMP 유형, ICMP 코드 또는 TCP SYN 플래그등은 첫번쩨 패킷의 헤더에 밖에 포함되지 않는다. 즉 두번째 분절패킷부터는 그 정보가 없다는 말이다. 이를 위해서 우리는 분절된 패킷을 처리하기 위해 -f 옵션을 사용한다.
하지만 -f옵션을 권장하지 않는다. 왜냐하면 첫번째 필터링정보가 담긴 헤더를 보고 필터링을 할때 그 패킷이 거부하는 룰에 적용되어 거부되면 분절된 패킷이 거부되지 않고 오더라도 그것은 하나의 패킷으로 재구성 되지 않고 버려지기 때문이다.
사용법은
# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
처럼 사용한다. 위의 뜻은 192.168.1.1을 항해 나가는 분절된 패킷은 모두 버린다 이다.
다시 한번 말하지만 꼭 필요한경우를 제외하고 이 옵션은 권정하지 않는다.
이정도로 iptables의 기본 사용법에 대해 마치고자 한다. 이문서에서는 방화벽설정에서 자주 사용하게 되는 옵션에 대해서만 언급했다. 아니 이정도 옵션들이면 어느정도 방화벽은 구성할수 있을것이다. 나머지 옵션들은 man패이지나 패킷필터링 HOWTO에서 찾아보기 바란다. 여기서 다루지 않은 forward체인과 nat구성,mangle테이블사용은 다음문서에서 다룰것이다.