하나의 호스트에 연결된 도메인 nobreak.com 과 kr.freebsd.org 에 대해,
일반적으로 nobreak@nobreak.com 과 nobreak@kr.freebsd.org 의 수신자는 같다.
여기에서는 각각의 도메인별로 aliases 테이블을 갖는 것과 같이, 도메인에 따라
수신되는 편지를 다르게 처리하는 방법에 대해 알아본다. 본 글이 Sendmail을
주제로 하지는 않기에, Sendmail을 어느 정도 알고 있다는 가정으로 골자내용만을
다루도록 하겠다. Sendmail에 익숙치 않다면 내용을 이해하기 위해 RuleSet, m4,
aliases, dbm/btree/hash 등에 대한 사전학습이 필요할 수도 있다.
설명하고자 하는 방법은 Sendmail 8.8 이상에서 가능하므로,먼저 다음과
같이 설치된 버젼을 확인한다.
$ telnet localhost smtp Trying 127.0.0.1... 220 kfug2.kr.freebsd.org ESMTP Sendmail 8.9.3/8.9.3 |
버젼이 8.8보다 낮다면,
ftp://ftp.sendmail.org/pub/sendmail/
에서 최신버젼을 구하기 바란다. Sendmail 8.2 이상에서는 domaintable
Feature를 사용해 구현될 수 있지만, 여기서 제시하는 Sendmail 8.8 이상의
virtusertable Feature로 대체되는 추세이므로 여기에서는 다루지 않겠다.
먼저 sendmail-VERSION/cf/cf/에서 시스템에 적절한
mc 파일을 복사한 후, Virtual Domain 설정에 필요한 virtusertable,
genericstable Feature를 추가한다. 작성된 mc 파일은 일반적으로 다음과 같이
보인다.
* generic-bsd4.4.mc 파일을 사용해 작성한 freebsd.mc 파일 divert(0)dnl VERSIONID(`@(#)generic-bsd4.4.mc 8.7 (Berkeley) 5/19/1998') OSTYPE(bsd4.4)dnl DOMAIN(generic)dnl MAILER(local)dnl MAILER(smtp)dnl FEATURE(virtusertable, btree /etc/domainaliases.db)dnl FEATURE(genericstable, btree /etc/useraliases.db)dnl |
virtusertable Feature는 수신(in-bound)되는 편지를 로컬 사용자로
매핑하는 RuleSet을 생성하고, genericstable Feature는 반대로
송신(out-bound)되는 편지에 대해 로컬 유저에 대한 메일주소(메일 헤더상의
From: 필드)를 매핑하는 RuleSet을 생성한다. DNS의 Forward Zone과 Reverse
Zone을 생각하면 되겠다.
btree 는 해당 테이블(domainaliases.db)이 B-Tree(Berkeley DB)
데이터베이스 형태로 저장됨을 의미한다. 가능한 다른 유형으로는
hash(Berkeley DB)와 dbm(NDBM)이 있는데, 테이블이 방대할 경우 효율은
btree(Berkeley DB) > hash(Berkeley DB) > dbm(NDBM) 순이다. 속도가 빠른
btree와 hash를 사용하기 위해서는 Berkeley DB(FreeBSD를 비롯해 몇몇 Unix에는
기본으로 포함된다)가 설치되어 있어야 하며, sendmail과
makemap 컴파일시 -DNEWDB 플래그(Berkeley DB가 설치되어
있다면 자동으로 -DNEWDB 플래그가 사용된다)를 사용해야 한다.
Berkeley DB가 설치되어 있지 않을 경우엔
-DNDBM 플래그(NDBM 라이브러리는 대부분의 Unix에 기본으로 포함된다)로 컴파일
되는데 이때에는 DBM을 사용하여야 한다. 리눅스와 같이 Berkeley DB의 GNU판인
GDBM이 사용되는 경우엔 별도의 노력없이 세 종류의 DB를 모두 이용할 수 있다.
작성된 freebsd.mc 파일은 다음과 같이 m4(Macro
Language Processor)를 통해 sendmail.cf로 변환한다.
# cd sendmail-VERSION/cf/cf # m4 ../m4/cf.m4 freebsd.mc > freebsd.cf # cp freebsd.cf /etc/sendmail.cf |
만약 기존의 sendmail.cf가 유지되어야 하는
상황이라면, 실제 본 두 Feature가 생성하는 다음의 RuleSet을 참고하여
sendmail.cf를 직접 수정하여도 좋다. (RuleSet이 삽입되는
위치를 파악하기 위해 m4로 sendmail.cf를 생성하여
비교하기 바란다)
* FEATURE(virtusertable, btree /etc/domainaliases.db)dnl # Virtual user table (maps incoming users) Kvirtuser btree /etc/domainaliases.db
# handle virtual users (RuleSet 0의 Parse1 아래에 위치) R$+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . > R<@> $+ + $* < @ $* . > $: < $(virtuser $1 + * @ $3 $@ $1 $: @ $) > $1 + $2 < @ $3 . > R<@> $+ + $* < @ $* . > $: < $(virtuser $1 @ $3 $@ $1 $: @ $) > $1 + $2 < @ $3 . > R<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . > R<@> $+ $: $1 R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 R< $+ > $+ < @ $+ > $: $>97 $1 |
* FEATURE(genericstable, btree /etc/useraliases.db)dnl # Generics table (mapping outgoing addresses) Kgenerics btree /etc/useraliases.db
# handle generics database (RuleSet 93 아래에 위치) R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark R< $+ > $+ < $* > @ $: < $(generics $1 $: $) > $2 < $3 > R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 > R< $* @ $* > $* < $* > $@ $>3 $1 @ $2 found qualified R< $+ > $* < $* > $: $>3 $1 @ *LOCAL* found unqualified R< > $* $: $1 not found |
먼저, 해당 호스트가 수신하는 도메인을 클래스 w(sendmail.cw)에
나열하여야 한다.
* /etc/sendmail.cw 파일 nobreak.com kr.freebsd.org |
domainaliases 파일을 편집기로 열어 다음과 같이 Virtual User Table을
작성한다.
* /etc/domainaliases 파일 webmaster@nobreak.com dipper moonhunt@nobreak.com moonhunt@ieee.org cjh@nobreak.com error:nouser Unknown User @nobreak.com nobreak @kr.freebsd.org %1@xfree86.org |
메일주소 webmaster@nobreak.com 는 로컬 사용자 dipper로 매핑되고,
moonhunt@nobreak.com 로 배달되는 편지는 moonhunt@ieee.org 로 포워딩 된다.
cjh@nobreak.com 으로 배달되는 편지에 대해서는 에러메시지 'Unknown User'로
답하며, 그외 nobreak.com 으로 수신되는 모든 편지는 로컬 사용자 nobreak로
전달된다. 또한, kr.freebsd.org 로 수신되는 모든 편지는 xfree86.org 의
같은 사용자에게 포워딩된다. 다음과 같이 aliases 파일과 연동하여 다수의
사용자를 매핑하는것 또한 가능하다.
* /etc/domainaliases 파일 announce@kr.freebsd.org announce.ml admin@kr.freebsd.org admin.ml |
* /etc/aliases 파일 announce.ml: :include:/var/ml/announce.ml admin.ml: nobreak, moonhunt@ieee.org |
호스트명이 kfug2.kr.freebsd.org 일때, 시스템에서 out-bound되는 편지는
기본적으로 user@kfug2.kr.freebsd.org 를 From으로 갖는다. 다음의
Reverse-map 테이블은 로컬 사용자의 메일주소를 변경한다.
* /etc/useraliases 파일 nobreak nobreak@nobreak.com cjh cjh@kr.freebsd.org |
작성된 테이블은 makemap을 사용해 dbm/btree/hash 형태로 변환되어야
한다. 여기서는 btree를 사용하였으므로 다음과 같이한다.
# makemap btree /etc/domainaliases.db < /etc/domainaliases # makemap btree /etc/useraliases.db < /etc/useraliases # ls /etc/domainaliases* /etc/useraliases* /etc/domainaliases /etc/useraliases /etc/domainaliases.db /etc/useraliases.db |
이제 Sendmail을 행업하고 동작을 확인하자.
# kill -HUP `cat /var/run/sendmail.pid`
# sendmail -bv webmaster@nobreak.com webmaster@nobreak.com... deliverable: mailer local, user dipper
# sendmail -bv cjh@nobreak.com cjh@nobreak.com... Unknown User
# sendmail -bv anybody@kr.freebsd.org anybody@kr.freebsd.org... deliverable: mailer esmtp, host xfree86.org., user anybody@xfree86.org |