J-한솔넷

기록 보관 : Postfix 메일 서버에 OpenDkim을 이용하여 DKIM 설정 본문

웹 개발관련/서버

기록 보관 : Postfix 메일 서버에 OpenDkim을 이용하여 DKIM 설정

jhansol 2024. 1. 22. 22:13

저의 개인 홈페이지에 있던 내용을 옮겨 기록하고자 합니다. 제가 게으른 탓에 활용하기 힘들고 유지를 하기에 금전적으로도 낭비다 생각되어 님길 것은 남기고, 버릴 것은 버리고 사이트를 없에기 위함입니다. 기존 내용 그대로 아래와 같이 옮겼습니다.


iRedMail을 설치하면 기본으로 DKIM 키를 성성해준다. 이 키를 적용하기에는 몇가지 문제가 있다. 우선 키 길이가 2048비트로 DNSZI에서는 1024비트만 지원하여 사용할 수 없고, iRedMail 설치시 기본으로 설치되는 amavisd는 2048비트의 키만을 지원한다. 그리고 도메인 단위로 DKIM 설정을 하기에도 애매한 상황이라 이것을 사용하지 않고 OpenDkim을 이용하여 1024비트의 도메인 단위로 DKIM 설정을 하기로 했다.

여기서 나의 목표는 iRedMail을 이용하여 여러 도메인을 대상으로 매일 서비스를 제공하고, 스팸매일 판정을 통과하여 정상적인 매일 서비스가 가능하도록 하는 것이 목표다. 그래서 각 도메인별 DKIM 설정과 SPF 설정을 하고자 한다. 이 글은 DKIM 부분만 기록한다.

OpenDkim 설치

우선 아래와 같이 입력하여 서버의 각종 패키지를 업그레이드하고, OpenDkim과 관련 툴을 설치한다.

$ apt update
$ apt upgrade
$ apt install opendkim opendkim-tools

OpenDkim 설정

멀티 도메인 DKIM 설정을 위해서는 아래의 작업이 필요하다.

  • "/etc/opendkim.conf" 수정
  • TrustedHosts (신뢰할 수 있는 호스트 도메인 정보) 파일 생성
  • SignTable (메일 도메인 별 개인키 정보) 파일 생성
  • KeyTable (도메인키 별 도메인, 선택기, 개인키 파일정보) 파일 생성

"/etc/opendkim.conf" 수정

멀티 도메인을 위해서는 "/etc/opendkim.conf" 파일을 아래와 같이 수정한다. 아래 내용은 주석 해제 및 변경, 추가한 내용만 표시하였다. 나머지 내용은 기본으로 사용하거나 문서를 보고 처리하길 권장한다.

Mode                    sv
ExternalIgnoreList      /etc/mail/TrustedHosts
InternalHosts           /etc/mail/TrustedHosts
KeyTable                /etc/mail/KeyTable
SigningTable            /etc/mail/SignTable
Socket                  inet:8891@localhost

각 항목 설명 및 파일 생성

Mode (운영모드)

모드는 서명, 확인 모드 두 가지가 있으며, 여기서는 두 운영모드를 모두 사용한다. 이 중 서명 모드를 이용할 경우 아래의 3가지 유형 중 하나를 만드시 지켜야 한다. 나는 여기서 두 번째 경우로 설정했다.

  • Domain(매일도메인) 항목 설정, KeyFile(매일도메인 카파일 위치정보) 항목 설정 및 파일 생성, Selector (선택기) 항목 설정
  • KeyTable(도메인 키, 도메인, 선택기, 키파일의 위치정) 항목 설정 및 파일 생성, SigningTable (각 도메인별 매일, 도매인 키 정보) 항목 설정 및 파일 생성
  • KeyTable(도메인 키, 도메인, 선택기, 키파일의 위치정) 항목 설정 및 파일 생성, SetupPolicyScript (매일 필터링 스크립트 파일 위치정보) 항목 설정 및 파일 생성

ExternalIgnoreList

자격증명 없이 서명된 도메인으로 서버를 통해 매일을 보낼 수 있는 외부 호스트 정보를 가지고 있는 파일의 위치를 기록한다. 지정 위치의 파일은 도메인주소, IP 등을 줄단위로 구분하여 기록한다. 나는 아래와 같이 "/etc/mail/TrustedHosts" 파일을 생성하였다.

127.0.0.1
175.199.254.0/24
jhansol.com
mai.jhansol.net
cafefallin.com
shsuri.com

이렇게 적용해야 각종 보안 위험을 줄일 수 있을 것이다. 그러나 나는 스마트폰이나 기타 매일 클라이언트를 이용해 매일을 송수신하기를 원한다. 그래서 아래와 같이 모든 호스트를 신뢰하는 것으로 설정하여 서명하도록 하고자한다.

0.0.0.0/0

InternalHosts

내부호스트, 즉 매일 확인 작업을 거치지 않고 서명되어야 하는 호스트 정보를 담은 파일 위치를 기록한다. 저정 파일은 "ExternalIgnoreList" 와 동일 형식을 작성하면 되고, 확인 및 서명 조건은 "ExternalIgnoreList" 와 동일하기 때문에 같은 파일을 이용한다. 이 항목을 지정하지 않으면 localhost(127.0.0.1)만 적용되므로 명시를 해주는 것이 좋다.

KeyTable

도메인 키, 도메인, 선택기, 개인키 파일의 위치를 한 쌍으로 가지는 키 테이블 정보들을 가진 파일의 위치를 설정한다. 각 정보는 줄단위로 구분하여 파일에 기록한다. 여기에서 도메인 키는 "선택기._domainkey.도메인" 형태로 작성한다. 꼭 이 규칙으로 작성할 필요는 없으나 아래와 같이 앞의 규칙의 DNS TXT 레코드를 요구하고 있기 때문에 되도록이면 앞의 규칙을 따라 작성하는 것이 좋을 듯 하다.

그리고 두 번째 필드는 도메인, 선택기, 개인키 파일 위치가 콜론(:)으로 구분하여 순서대로 입력한다.

mail._domainkey.jhansol.net jhansol.net:mail:/etc/mail/Keys/jhansol.net/mail.private
mail._domainkey.cafefallin.com cafefallin.net:mail:/etc/mail/Keys/cafefallin.com/mail.private
mail._domainkey.shsuri.com shsuri.com:mail:/etc/mail/Keys/shsuri.com/mail.private

SignTable

도메인 이메일과 도메인 키 상으로 이루어진 정보를 가진 파일의 위치를 지정한다. 도메인 이메일과 도메인 키는 공백으로 구분하여 각 정보를 기록한다. 각 도메인 이메일 주소를 이용하여 도메인키를 찾고, 도메인 키를 잉ㅇ하여 KeyTable에서 개인키를 찾아 확인하는데 사용된다. 도메인 이메일은 "*@도메인" 형태로 기록한다.

*@jhansol.net mail._domainkey.jhansol.net
*@cafefallin.com mail._domainkey.cafefallin.com
*@shsuri.com mail._domainkey.shsuri.com

Key 생성

이재 위에 설정한 각 도메인의 DKIM 키를 생성하면 된다. 키의 생성 위치는 "/etc/mail/Keys/도메인명" 폴더 아래 생성한다. 키를 생성하기 편하게 아래와 같이 스크립트를 만들었다. 키를 생설할 때 1024비트의 키를 생성하도록 한다.

#!/bin/bash

if ! [ -z $1 ]
then
        echo "create dkim key for $1"
        if ! [ -d "/etc/mail/Keys/$1" ]
        then
                mkdir -p "/etc/mail/Keys/$1"
        fi

        cd "/etc/mail/Keys/$1"
        opendkim-genkey -b 1024 -t -s mail -d "$1"
else
        echo "Usage : mk-dkim-key <domain>"
fi

위 스크립트를 나의 경우 "/usr/local/sbin/mk-dkim-key" 으로 저장하고 실행권한을 지정한 후 아래와 같이 각 도매인별 키를 생성한다.

$ chmod a+x /usr/local/sbin/mk-dkim-key
$ mk-dkim-key jhansol.net
$ mk-dkim-key cafefallin.com
$ mk-dkim-key shsuri.com

아래와 같이 폴더가 생성되고 파일이 생성되었다면 opendkim 부분에서는 설정이 마무리되었다.

$ tree .
.
├── Keys
│   ├── cafefallin.com
│   │   ├── mail.private
│   │   └── mail.txt
│   ├── jhansol.net
│   │   ├── mail.private
│   │   └── mail.txt
│   └── shsuri.com
│        ├── mail.private
│        └── mail.txt
├── KeyTable
├── m4
│   └── opendkim.m4
├── SignTable
├── spamassassin -> ../spamassassin
└── TrustedHosts

Postfix 설정

iRedMail 솔루션을 설치하면 Postfix를 기본으로 설치하고 환경설정을 한다. 그리고 이 솔루션은 DKIM 서명을 위해 "amavis" 를 이용한다. 이 것의 문제점은 서두에 언급하였으므로 생락한다. 암튼 이 서명 도구를 비활성화하고 이재까지 지정한 설정을 상ㅇ할 것이다. 그래서 아래와 같이 기존 "amavis" 부분을 주석처리하고 opendkim 관련 설정을 추가한다.

#
# Amavisd + SpamAssassin + ClamAV
#
#content_filter = smtp-amavis:[127.0.0.1]:10024

# Concurrency per recipient limit.
#smtp-amavis_destination_recipient_limit = 1

# DKIM
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

설정 적용

아래와 같이 기존의 "amavis" 서비스를 중지하고 비활성화한 후 "opendkim"과 "Postfix" 서비스를 재실행한다.

$ systemctl stop amavis
$ systemctl disable amavis
$ systemctl restart opendkim
$ systemctl restart postfix

적용 후 "/var/log/mail.log" 파일을 열어 "milter" 관련 키워드를 검색하여 연결오류가 발생하지 않은지 확인한다. 연결오류가 없어야 키를 이용하여 발신되는 이매일 내용에 서명을 하게된다.

구성 검사

이재 위에서 구성한 DKIM 이 정상 실행 가능성이 있는지 검사한다. 아래와 같이 테스트 명령을 입력하여 위에서 설정한 모든 키의 정상 실행 가능성을 점검한다.

$ opendkim-testkey -v -v

그러면 아래와 같이 각 키를 테스트하여 그 결과를 출력한다. 아래 내용을 보면 하나만 통과 나머지는 실페했다고 나와 있다. 사실 두 도메인은 회사 도메인과 고객사 도메인이라 DNS 레코드를 추가하지 않았다. 이로 인해 해당 도메인 키 레코드를 찾지 못해서 발생한 것이다.

$ opendkim-testkey -v -v
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: record 0 for 'mail._domainkey.jhansol.net' retrieved
opendkim-testkey: checking key 'mail._domainkey.jhansol.net'
opendkim-testkey: key mail._domainkey.jhansol.net not secure
opendkim-testkey: record 1 for 'mail._domainkey.cafefallin.com' retrieved
opendkim-testkey: checking key 'mail._domainkey.cafefallin.com'
opendkim-testkey: key mail._domainkey.cafefallin.com: 'mail._domainkey.cafefallin.net' record not found
opendkim-testkey: record 2 for 'mail._domainkey.shsuri.com' retrieved
opendkim-testkey: checking key 'mail._domainkey.shsuri.com'
opendkim-testkey: key mail._domainkey.shsuri.com: 'mail._domainkey.shsuri.com' record not found
opendkim-testkey: 3 keys checked; 1 pass, 2 fail

서명 및 확인 테스트

이부분은 위키를 보니 "opendkim-testmsg" 명령을 이용하라고 나와서 아래와 같이 입력했더니 에러가 발생한다. 이 명령의 사용법에 대해서는 자세하게 나와 있지 않아 여기까지만 기록한다. 추 후 알게되면 이부분은 갱신할 것이다.

$ echo "this is test" | opendkim-testmsg -C -d jhansol.net -k /etc/mail/Keys/jhansol.net/mail.private -s mail
opendkim-testmsg: dkim_chunk(): Syntax error

이매일 테스트

데비안 위키에서는 두 가지 방법을 재시하고 있다. 그 중 하나는 테스트 이매일 주소(check-auth@verifier.port25.com)로 빈 매일을 발생하여 얼마 후 응답을 받아보는 방법과 나머지 하나는 웹사이트(https://www.mail-tester.com/)접속해%EC%A0%91%EC%86%8D%ED%95%B4) 이메일을 보내고 피드백을 받는 방법이 있다고 한다. 그런데 이 두 옵션을 현재로서는 상용할 수 없다. 다른 플렛폼에서 다시 한번 테스트해봐야겠다.

위 매일 테스트 웹사이트에서 테스트를 했는데, DKIM 부분 설정이 안되어 있다고 나온다. 분명 서명되고 있는데 이부분이 해결되면 거의 9.8 정도의 점수가 되는데 안된다. 그런데 Naver의 개인매일 계정으로 매일을 보내 원문을 확인하니 아래와 같은 해더 정보를 확인했다.

ARC-Seal: i=1; a=rsa-sha256; d=naver.com; s=arc-20180730; t=1662373054;
    cv=none; b=LHYo+uvFGR8J/bKT5z9D5DeClIrirA4o2tppBdchKuKJlP3a4TM/+pnguKx3
     0zR5eZ/EU2T9kYw33PZUL02e9DBnRHrKCWiUqGcpVB/zA7xlgSIsN1IiRCKerpKhA+Q3Iw
     uFJhGq3rmf4ReaI/xIndssL34mhSenW2LWWEXB7icXSM4UUpMKiu4b4/8/AjN4opDsuGHN
     eq8o2p9oYh5mdwHo+HtxeDi/AxzOEM3yZNFLYXtwj2RZgNG93Orr1Nzf5gzYSo0n8QSMnX
     lFOzrE/m7ViGjeZmdCzwg7mINixZWMBdwZu1+Z+acUlVnLs7Bkd4VXCOI2T5rX/gKTGaHv
     Ow==
ARC-Message-Signature: i=1; a=rsa-sha256; d=naver.com; s=arc-20180730;
    t=1662373054; c=relaxed/relaxed;
    bh=CBgqIVE6Ui0kLgPxfnYifALuF+1L7naSJTBAESuaYxs=;
    h=date:from:to:subject:message-id; b=EvOQYwVCtJOG5rocTjhfncwEq9Z4Vy0NJE
     o+lRJYQDbFqXMZ3QcYjPPOzjkjwI1nv9sXTfMlpZU2VU+a0SPeXPMAobvUCLb4QEXDgWPj
     bOhUzaMwlwlTiizSi1bFTOX1sHV0JioDhFt16GAVc7UZhIcyv7Qyznq3CYqIAhO0NZJNXD
     2tDbeCckolN5emR3ptklPtddaZ1WAcLXMFgOpE0w6geOGCqck4lt80WVe8sJK3SbuI9b/I
     f2HSto3O3VA7hZTPxAHKJs72SOkrfXNzT4kG2k42u3PDu+aEkSzSn/xHSnb3OqqdtqAl0x
     suqLR94d1ZGVUuTH3kUNHS/LaecA==
ARC-Authentication-Results: i=1; mx.naver.com; 

위 내용을 보면 서명이 되어 있기는 한데, "DKIM-Signature"라는 해더가 아니라 "ARC-Message-Signature"라고 되어 있다. 이 해더 역시 DKIM과 유사하기는 하나 DMARC 정보도 함께 포함하는 개선된 서명 방식으로 이 서명이 적용되면 DMARC 설정이 필요하지 않다.(개인적인 생각이지만)

추가 사항 - DNSSEC 문제

DNSSEC라는 용어는 익이 봐왔던 것이기는 한데 그냥 DNS 보안과 관련된 것이겠지라고만 생각했다. 그런데 이 작업을 진행하면서 좀 더 구체적으로 알게되었다. 이 부분은 추 후 다시 공부하는 시간을 가져봐야겠다. 아래 내용은 "구성 검사" 부분의 일부다. 아래 내용의 맨 아래부분에 "key .... not secure" 부분이 있다. 이렇게 출력되는 원인은 DNSSEC기능이 활성화되어 있지 않아 위변조의 위험이 있다는 것이다. 오류는 아니다.

opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: record 0 for 'mail._domainkey.jhansol.net' retrieved
opendkim-testkey: checking key 'mail._domainkey.jhansol.net'
opendkim-testkey: key mail._domainkey.jhansol.net not secure