ubuntu에서 letsencrypt ssl 인증서 사용하기 (with cloudflare dns)

let’s encrypt를 이용하면 무료로 SSL 인증서를 받을 수 있고, 특히나 v2 api를 이용하면 와일드카드 인증서까지 받을 수 있기 때문에 개인들은 구지 돈내고 유료 SSL 인증서를 발급 받을 필요는 없을것 같다.

내 경우는 DNS를 cloudflare로 모두 옮겼기 때문에 certbot-dns-cloudflare를 이용해서 인증서를 발급/갱신하도록 설정했다.

Continue reading ubuntu에서 letsencrypt ssl 인증서 사용하기 (with cloudflare dns)

exim 으로 메일 서버 구성하기…

왠지 모르게 점점 마이너 한 것들만 사용하게 되네요. postfix 나 exim 을 사용해보니 여러가지 장점이 눈에 보이는데 막상 how to 문서같은게 그리 잘 나와있질 않다보니 사람들이 사용하기를 꺼리는 것 같아 처음으로 howto 문서를 하나 작성해려 합니다.
이 문서는 젠투에서 exim 을 사용하는 방법을 기준으로 설명하고 있습니다.

Table of Contents

  1. 기본 구성
  2. 필요한 소프트웨어 설치하기
  3. 가상호스트 설정하기
  4. 바이러스 필터 설정
  5. 스팸 필터 설정
  6. dovecot 설정하기
  7. smtp 인증 설정하기
  8. 다른 배포판을 사용할 때 유의점

기본 구성

Mail Transfer Agent 로는 exim, 스팸 필터로는 bogofilter, 바이러스 필터는 clamav, pop3/imap server 로는 dovecot 을 사용하기로 하겠습니다. dovecot 이나 exim 이나 기본 적으로 실행하는 프로세스들이 많지 않기 때문에 프로세스 리스트를 확인할 때 깔끔해서 좋더군요.

필요한 소프트웨어 설치하기

저 같은 경우는 대강 다음과 같은 USE 플래그를 이용해서 설치를 진행했습니다.

domainkeys 는 야후나 구글에서 사용하고 있는 domain key 를 제대로 검증하기 위한 USE 플래그가 되겠구요, dovecot-sasl 은 smtp 인증에 dovecot 을 이용하기 위한 플래그입니다.
spf, srs, domainkey 같은 플래그는 해당 기능을 사용하지 않겠다면 빼주셔도 무방합니다. CentOS 등에서는 dovecot-sasl 도 기본으로 지원이 안되더라구요. 하튼 관련해서 자세한 건 뒤에서 설명하도록 하겠습니다.
살펴보니 별로 특이한 플래그를 사용하지는 않네요. -_;; 젠투 유져라면 다들 아시겠지만 실제 설치는 위의 예제에서 -pv 를 제거하고 실행시키시면 됩니다.

가상호스트 설정하기

설치가 무사히 끝났다면 가상호스트를 설정해봅시다. 젠투에서는 기본으로 설정파일을 만들어주지 않습니다. 그렇기 때문에 우선 /etc/exim/exim.conf.dist 를 복사해서 exim.conf 를 만들어줍니다.
# cp /etc/exim/exim.conf.dist /etc/exim/exim.conf
그런 다음 자신이 좋아하는 편집기를 이용해서 exim.conf 파일을 열고, 아래와 같은 부분을 찾아서 자신의 환경에 맞게 수정을 한 뒤

router 부분에서 system_alias 바로 아래에 다음 코드를 추가해줍니다.

주 도메인이 있는 경우 localhost 대신 unfix.net 같은 도메인을 사용해도 무방합니다. 만약 위의 예제에서 localhost 대신 unfix.net 을 설정해주면 로컬에 있는 모든 계정은 id@unfix.net 형태의 메일계정으로 사용이 가능해집니다. 주 도메인이 여러개라면 @ : localhost : mydomain1 : mydomain2 식으로 콜론(:) 을 이용해서 여러 개를 모두 적어주면 되겠습니다.
이젠 가상 호스트를 설정해봅시다. 만약 test.com 과 test.net 을 위한 가상호스트를 설정하려 한다면 다음과 같이 하면 됩니다.

위에서 dsearch; … 으로 설정해놓은 디렉토리 안에다가 호스트 이름을 이용해서 alias 파일을 만들어주면 되니까 간단하죠? 각 파일에 들어가는 내용은 다음과 같습니다.

# test.com
test: aqua@localhost
melong: test@gmail.com

# test.net
aqua: test@localhost

test.com 파일에 들어가 있는 test: aqua@localhost 는 test@test.com 으로 온 메일을 aqua@localhost 로 포워드를 시키라는 거에요. 워낙 간단하니 다른 것들은 따로 설명 안해도 될 것 같네요. 단 위에서 localhost 대신 myhost.net 을 사용했다면 aqua@myhost.net 처럼 설정해줘야 합니다.
여기까지 따라하셨다면 가상 호스트 설정은 끝! 가상 호스트 파일을 수정했을 때는 alias 를 수정했을 때와 달리 newalias 를 실행시키실 필요가 없습니다.

바이러스 필터 설정

바이러스 필터로는 clamav 를 사용할 건데, USE 플래그로 exiscan 과 exiscan-acl 을 사용해서 설치했다면 clamd 와 연동하는건 아주 간단합니다.
exim.conf 에서 다음과 같은 줄을 찾아서 주석을 해제시키세요.

끝! clamd.sock 위치는 배포판에 따라 다를 수 있습니다. 자세한건 /etc/clamd.conf 를 참조하세요.

스팸 필터 설정

SPF

Exim에는 기본으로 SPF와 관련된 코드가 있으므로 SPF를 사용하기 위해선 EXPERIMENTAL_SPF=yes 환경변수와 함께 exim을 빌드하면 됩니다.
설정은 global 섹션에서 acl_smtp_rcpt 로 등록되어 있는 것에 다음과 같은 설정을 넣어주면 됩니다.

젠투에선 acl_smtp_rcpt가 acl_check_rcpt로 되어 있기 떄문에 acl_check_rcpt 부분에 위 설정을 추가해줬습니다.
만약 warn message = $spf_received 를 넣어주지 않으면 헤더에 SPF결과를 출력하지 않게됩니다. SPF헤더를 붙일 경우에는 SMTP Auth를 이용해서 메일을 보내는 경우에도 SPF헤더가 붙는 문제가 있습니다. 이를 피하기 위해 설정을 아래처럼 수정해주도록 합시다.

SRS

SRS를 설정하기 위해 우선 global 섹션에 다음과 같은 내용을 추가해줍니다.

여기서 somesecretkey는 본인이 원하는 임의의 문자열을 넣으면 되겠습니다. 그 후 다음과 같이 userforward에 ‘srs=forward’를 넣어주면 됩니다. 간단하죠.

Bogofilter

스팸 필터로는 베이시안 룰 기반의 스팸 필터인 bogofilter를 사용해봅시다.
bogofilter를 MTA와 연동시키는 데는 procmail을 이용할 수도 있지만, procmail은 로컬 유져에 한해서만 사용이 가능하고, alias 나 .forward 를 사용하게 되는 경우에는 사용할 수 없으므로 exim의 transport와 router를 이용해보겠습니다.
우선 transport를 다음과 같이 설정합니다.

그리고 이 transport 를 이용하는 router를 만들어야 합니다. 참고로 router 는 순서에 민감하므로 삽입할 위치를 잘 선택해야 합니다. 저같은 경우는 system_alias 다음에다가 넣어두었습니다.

여기까지만 하게 되면 bogofilter가 각각의 메일 헤더에 ‘이 메일이 스팸/햄이다.’ 라는 정보만을 넣어줄 뿐 스팸/햄을 다른 메일박스로 분류해주는 동작은 하질 않습니다.
그러므로 자동 분류를 위한 transport 와 router 를 또 추가해주도록 합니다.
transport 먼저…

이렇게 하면 자신의 홈 디렉토리의 .maildir 아래 .Spam 이란 디렉토리를 만들고, 그 디렉토리에 스팸 메일을 저장하게 됩니다.
IMAP 으로 접속하면 Spam 메일들을 확인할 수 있기 때문에 이렇게 했는데, POP3 만 사용하는 거라면 그냥 제목에 [Spam] prefix 를 붙이게 하는 것도 나쁘지 않을 것 같습니다.
그 다음엔 이 transport 를 이용하는 router를 설정해야하는데, 이 때도 위치를 잘 생각해야 합니다. 저같은 경우엔 bogofilter router 바로 아래에 위치시켜 놓았습니다..

스팸 메일은 bogofilter 에 의해 X-Bogosity: Spam, test=bogofilter … 식의 헤더가 추가되기 때문에 이렇게 할 경우 스팸을 쉽게 분류해낼 수 있습니다.

dovecot 설정하기

우선 /etc/dovecot.conf 파일을 열어서 서비스할 프로토콜 리스트를 적어주세요. 그 다음에 plaintext 로 로그인할 수 있도록 설정해주고, pop3 나 imaps 를 위해 ssl 을 사용할거라고 명시해주고, 마지막으로 dovecot-sasl 을 사용할 수 있도록 auth-client 를 활성화시켜주세요.
이를 종합해보면 다음과 같은 설정파일이 만들어집니다. 볼드로 표시한 부분이 제가 수정한 부분이에요. 주석을 제거하고 보니 정말 간단하네요. -_-;

그리고 /etc/pam.d 로 가서 smtp 파일이 있는지를 체크해보시고 만약 없다면 system-login 이나 pop 등을 복사해서 smtp 파일을 만들어주세요. 이것 때문에 어제 혈압이 올랐던걸 생각하면 …!!!
여기까지 설정하셨음 90% 는 끝난겁니다.

smtp 인증 설정하기

자 다시 exim.conf 로 돌아와서 smtp 인증을 설정해봅시다. exim.conf 에서 authenticators 파트를 찾아서 아래와 같은 내용을 추가해줍시다.

이걸로 설정은 끝! 다음엔 데몬들을 띄워서 제대로 되나 확인을 해보세요.

다른 배포판을 사용할 때 유의점

제가 이것저것 확인해본 건 아니라 정확하게 알려드릴 순 없지만 CentOS 에서는 spf, srs, dovecot-sasl, domainkeys 등을 사용할 수가 없습니다. 그렇기 때문에 dovecot-auth 대신 saslauthd 를 사용해야 해요. saslauthd 를 사용할 때의 authenticator 파트는 다음과 같습니다.

server_condition 을 다음처럼 하면 pam 만으로도 인증을 할 수 있습니다. 하지만 pam_auth 모듈에서 auth request를 보낸 사용자의 uid와 username을 가지고 확인하는 절차가 있기 때문에 exim을 root 권한으로 실행시키지 않으면 제대로 인증이 되지 않습니다.

참고로 인증을 saslauthd 를 통해서 하려는 경우 saslauthd 가 실행 중에 있어야 합니다.

Sender Rewrite Scheme

spf 는 예전에 써놨던 글에서 충분히 설명해놨듯이 메일의 도메인값과 발송지 값을 이용해 스팸을 필터링해내기 위한 기술입니다. 예를 들어 From address 에 nospam@mytears.org 가 있을 경우 mytears.org 도메인의 txt 정보를 읽어오고, 거기에 적혀있는 61.109.245.78 에서 온 메일만을 정상적인 메일로 판단하게 되는데, 이렇게 spf 가 적용되어 있는 경우 .forward 나 alias 등을 이용해서 메일을 포워딩 시킬 경우 문제가 있을 수 있습니다.
.forwards 를 통해 nospam@mytears.org 를 nospam@gmail.com 으로 리다이렉션을 시킨 경우를 생각해봅시다.

  1. sender@somedomain 에서 nospam@mytears.org 로 메일을 보냄
  2. mytears 메일 서버에서 nospam@mytears.org 사용자에 대한 .forward 파일을 읽어서 거기 적혀있는 nospam@gmail.com 으로 메일을 포워딩 시킴
  3. gmail 메일 서버에서 from address 인 somedomain 의 txt 에서 spf 정보를 읽어옴
  4. spf 로 지정된 아이피와 메일을 포워딩시킨 서버의 아이피가 동일하지 않으므로 spf 정보가 맞지 않다고 판단함
  5. spf 정책에 따라 다르겠지만 대부분 스팸이라고 판단하게 됨
  6. 결국 제대로 메일이 전해지지 않음

이걸 해결하기 위한 방법으로 srs 라는 게 있습니다. 이걸 적극적으로 적용한 예로는 구글이 있습니다.
exim 의 경우 기본적으로 spf, srs 를 지원하기 때문에 빌드할 때 옵션을 잘 조절해주면 쉽게 적용할 수 있습니다. sendmail 의 경우 milter 를 이용하면 srs 를 적용할 수 있구요. 하지만 postfix 에서는 이를 사용할 수 없는 방법이 없습니다. (구버젼의 postfix 라면 패치를 통해 사용할 수 있지만 이 패치가 계속 유지되질 않고 있습니다.)
참고
spf: http://www.openspf.org/
srs: http://www.openspf.org/SRS
p.s) 그나저나 spf 가 나온지 꽤 오랜 시간이 흘렀음에도 대학 메일 서버들 중에 spf 를 지원하는 곳은 별로 없군요.

bogofilter

요 근래 늘어가는 스팸에 이마에 주름이 하나 둘 늘어가고 있던 찰나에 bsdforum 을 구경갔다가 방준영 님이 쓰신 bogofilter 관련 글을 보게 되었습니다. 사용법을 보니 자동으로 스팸 훈련을 시키는 것이 아닌 듯 싶어 왠지 모르게 호감이 가더군요. 🙂
http://bogofilter.sourceforge.net/
참고로 bogofilter는 베이시안 룰 기반의 스팸 필터입니다.
사용을 위해선 우선 스팸 메일들을 .Spam에 몰아두고, 스팸이 아닌 메일을 .Ham폴더에 몰아둔 뒤 아래와 같은 명령어를 이용해서 학습을 시켜야 합니다.

-S옵션은 이 메일이 스팸 메일이라는 것을 의미하고, -N은 이 메일이 스팸이 아니라는 것을 의미합니다.
만약 A라는 스팸 메일을 햄이라고 잘못 학습시킨 경우 아래와 같은 명령을 이용해서 결과를 바로 잡을 수 있습니다. (A는 메일 파일 이름)

거꾸로 A라는 햄 메일을 스팸이라고 잘못 학습 시켰다면 아래와 같은 명령어를 이용해야합니다.

제 메일함에 쌓여있던 이메일(햄: 약300통, 스팸: 약1,000통)을 기준으로 스팸/햄 확률을 업데이트한 뒤 3일째 테스트 중입니다. 3일동안 온 30개의 메일 중에 스팸 26통을 정확하게 걸러주었네요.
아래는 나중에 시스템에 적용시켰을 때 사용자들이 Spam 폴더를 지우지 않더라도 알아서 정리해주기 위해 사용하게 될 스크립트 초안입니다~

제가 참고한 bsdforum 의 방준영 님의 글은 아래 링크에서 볼 수 있습니다 😉
http://bsdforum.or.kr/viewtopic.php?t=33
그리고 bogofilter 없는 상태에서 스팸을 걸러낸 결과는 아래와 같습니다.

# 전체 받은 메일 수
unfix aqua # cat /var/log/procmail|grep ^[\\[F]|wc -l
5077
# Spf 에 걸린 메일
unfix aqua # cat /var/log/procmail|grep ^\\[Spf|wc -l
2482
# Broken Multipart
unfix aqua # cat /var/log/procmail|grep ^\\[Fake|wc -l
1499
# Bad-mailer
unfix aqua # cat /var/log/procmail|grep ^\\[BadMailer|wc -l
315
# Spam-word 를 포함한 경우
unfix aqua # cat /var/log/procmail|grep ^\\[Spam|wc -l
141
# Bad-library
unfix aqua # cat /var/log/procmail|grep ^\\[BadLibrary|wc -l
21
# 내용, 제목이 모두 없는 메일
unfix aqua # cat /var/log/procmail|grep ^\\[EmptyMail|wc -l
# 바이러스 메일
unfix aqua # cat /var/log/procmail|grep ^\\[Virus|wc -l
2

6일부터 12일까지의 5077 개의 메일 중에 Spf 에 2482 개, Fake/NoHTML + Fake/NoPlain 에 걸린게 1499 개, BadMailer 에 315개, SpamWord 에 141 개, BadLibrary 에 21개, Virus 가 2개 되겠습니다.
결과적으로 4460/5077 개로 87.8% 가 스팸으로 판정되었습니다.
그리고 bogoutil 을 통해 확인해본 결과 나름 인코딩 관련된 처리를 알아서 처리하고 있는 듯 싶길래 BadMailer, SpamWord, BadLibrary 에서 처리하던 부분을 bogofilter 로 대체시킬까 싶어서 관련된 rule 은 주석처리를 해 놓았습니다.

backup script 도 작성 완료 -_-v

SCSI HDD 같은 경우야 뭐 오래써도 별 문제가 안생기니까… 이제 겨우 일년 정도밖에 안 쓴 제 서버 하드를 걱정할 일은 아니지만… 그래도 세상일은 어떻게 될 지 모르기 때문에… 귀찮다고 미루고 미루던 백업 스크립트를 작성하게 됐습니다.
shell script 의 고수 분들이야 find 등 도 뭔가 멋지게 쓰고 하는 거 같지만! 전 초보 이기 때문에… 그냥 3일 이상 지난 파일의 경우엔 tmpwatch 가 정리하도록 처리를 해버렸네요… 흐흐
혹시나 제 백업 스크립트가 궁금하신 분들은 more 버튼을 클릭하시길…
Continue reading backup script 도 작성 완료 -_-v

느린 SFTP 는 이제 안녕~

얼마 전 proftpd 패치를 한 김에 … [wikipedia:SFTP] (ftp over ssh) 대신 [wikipedia:FTPS] (ftp over ssl) 를 사용하기 위해 이래저래 삽질을 조금 해봤다… 뭐 결론은 파일질라에서 -_-;; passive 로 안하면 디렉토리 리스트를 못얻어오고 에러가 나는게 문제였지만… 하튼!!
[wikipedia:SFTP] 의 경우엔 라인이 꽤 좋음에도 불구하고 200~300K 정도가 나올가 말까 하는 극악한 속도를 자랑했었는데… proftpd + mod_tls 조합으로 ftps 를 사용해보니 무선랜 환경에서도 500~600K 정도는 나오는게 데스크탑에서는 훨씬 빠를 듯 싶다… (테스트해보니 1.6MB 이상도 나오는거 보면 [wikipedia:SFTP] 랑 속도비교는 무의미 할 듯)
[wikipedia:FTPS] 의 경우엔 이어받기 라던지… 예전 ftp 에서 지원하던 모든 것들을 지원하기 때문에 굳이 다시 [wikipedia:SFTP] 를 쓸 일은 없을 듯… 하튼 이제 느린 [wikipedia:SFTP] 는 안녕~
proftpd 의 옵션 중 TLSrequired 가 on 이면 data 채널과 control 채널 모두 암호화를 해서 전송을 하고 ctrl 이면 data 는 암호화 되지 않은 상태로 전송이 된다고 하는데… off 인 경우는 tls 를 사용하는지 마는지 궁금해졌다 -_-; sniffit 을 이용해서 21 번 포트로 들어오는 데이타를 스니핑 해보니… off 여도 확실히 암호화 되서 전송되는 거 같기는 해서 안심!

proftpd: codeconv module

사실 unfix 는 나 혼자 쓰는 서버가 아니고… 파일이름등을 unicode 로 관리할 경우 ms 윈도우와의 궁합이 그다지 좋지 않기 때문에… utf-8 환경을 갖추는 게 망설여지는게 사실이었다.
얼마 전 젠투 한국 사용자그룹의 유리님의 개인 portage-overlay 리스트를 보다가 proftpd 의 charset conversion 패치를 발견했다. 원 출처는 일본 쪽인 듯 싶은데, 이 패치를 적용하면 client 에서 사용하는 charset 과 server에서 사용하는 charset 을 설정하는게 가능해진다.

만약 중간에 charset conversion 에 실패했다거나 한 경우 어떻게 처리를 하나 봤더니, 변환에 실패한 글자를 ‘?’ 로 바꿔버리고 있었다. out_buffer size 를 in_buffer size 의 세 배 크기로 할당하고 중간에 에러가 발생하면 무조건 변환이 실패한 것으로 생각하기 때문에 한 글자를 표현하는데 3바이트보다 더 많은 바이트 수가 필요하다면 (ucs2 로는 표현 못하는 글자를 사용하는 경우), 버퍼 오버플로의 희생양이 될 수도 있을 듯 싶다. 그래도 원하는 코드를 삽입하는 건 힘들고 그저 segmentation error 를 부를 뿐이겠지만 찝찝한 건 사실이므로 에러가 발생할 경우 errno 를 참고하도록 패치를 해야겠다.

근데 실제 적용을 해보니 Directory 나 .ftpaccess 를 통한 지역 설정이 허용되지 않는다. 내가 사용하는 폴더들에 한해서 저 패치의 영향을 받게 하는게 목적이었기 때문에 결국 패치를 해버렸다. proftpd 개발자 문서는 서버가 다운되었었는지 참고를 할 수가 없었고, 그나마 미러링 된 곳도 찾을 수가 없어서 한참 헤매긴 했지만!! 결국!! 내가 원하는 데로 패치 성공 -_-v

mod_autoindex 도 몇 일전에 charset 을 설정해줄 수 있도록 패치했고, 그 외에는 이미 다 준비가 되어 있었기 때문에 누군가 mod_autoindex 의 새로운 테마만 만들어준다면 바로 utf-8 환경으로 넘어갈 수 있을 듯 싶다.

FTP 관련해선 RFC2640 에 있는 것을 구현하는 것이 옳다고 생각하지만 중간 단계로써 mod_codeconv 도 나름의 의미가 있을 듯 싶다.

p.s) 위의 사이트에 나와있는 메일 주소로 패치파일을 보내주려 했지만 메일주소가 죽어있네요.