Rocky Linux - 메일서버(Postfix) DKIM 정책 적용

    ◆ DKIM이란?

    DKIM(DomainKeys Identified Mail)은 피싱 및 스팸메일(이메일 스푸핑)에서 위조된 발신자 주소를 검사하기 위해 [무결성 검증] 개발된 이메일 인증 방법 중 하나입니다. DKIM을 사용하면 수신자가 특정 도메인에서 온 이메일이 해당 도메인 소유자가 실제로 발송 승인을 했는지 확인할 수 있습니다. OpenDKIM 설치를 진행하다 보면 헤더에 직접 디지털 서명(공개키)을 추가하는 것을 말합니다. 수신자는 네임서버(DNS)에 게시된 보낸 사람의 공개 키를 조회하여 일치하는지를 확인합니다.  

    ■ 설치환경 및 준비물

    메일서버 구축 : https://foxydog.tistory.com/104
    이후 Postfix에 SPF 정책을 적용합니다.

     

    Linux에서 DKIM서명 및 확인을 수행할 수 있는 두 가지 일반적인 소프트웨어는 OpenDKIMAmavis가 있습니다.

    하지만 Amavis 경우는 OpenDMARC와 연동할 수 없기 때문에 OpenDKIM 설치를 진행합니다.

    공식 사이트[OpenDKIM] : http://www.opendkim.org/


    STEP01 → OpenDKIM 설치하기

    [root@ ~]# dnf install opendkim perl-Getopt-Long

     

    ◇ perl-Getopt-Long은 특정 명령 줄 옵션을 처리하기 위한 모듈, 특히 긴 옵션 이름을 처리하기 위해 지원하는 Perl모듈이라고 합니다. 나중에 DKIM TXT레코드 값 특성상 KEY길이가 매우 길기 때문에 같이 사용하는 것으로 보입니다.


    STEP02 → OpenDKIM 구성 설정[opendkim.conf]

    [root@ ~]# vim /etc/opendkim.conf    [구성파일 편집]

     

    ※ 다음과 같이 구성을 변경

    Mode    sv    [변경]

    SendReports     yes    [기본 설정, NO로 되어 있다면 YES로 변경]

    #KeyFile        /etc/opendkim/keys/default.private    [#주석 처리, 사용하지 않음]

    KeyTable        /etc/opendkim/KeyTable    [#주석 제거]

    SigningTable  refile:/etc/opendkim/SigningTable    [#주석 제거]

    ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts    [#주석 제거]

    InternalHosts   refile:/etc/opendkim/TrustedHosts    [#주석 제거]

    참고

    □ Mode

    [ Mode    v ] = DKIM검사를 수신 이메일 메시지에 대해서만 서명을 확인 합니다.

    [ Mode   sv ] = DKIM검사를 수신 및 보내는 이메일 헤더 메시지에도 서명을 포함하여 발송합니다.

     

     SendReports

    수신 측에서 DKIM 정책을 이용하고 있으며 발송 서명 확인이 실패하여 메일을 거부하였을 경우 최초 발송자에게 리포트를 발송합니다. 정상 발송자에게 혼동을 주지 않기 위해 사용[YES]하는 게 좋습니다. 대체로 실패하면 "Example.com Postmaster" <postmaster@example.com>와 같은 형태의 리턴 메일을 받습니다.

     

     #KeyFile /etc/opendkim/keys/default.private

    OpenDKIM 기본 서명은 사용하지 않으므로 #주석 처리합니다.

     

     KeyTable - OpenDKIM에게 키를 찾을 위치를 알려줍니다.

     SigningTable - OpenDKIM 키 사용 방법을 정의합니다. KeyTable을 활성화해야 합니다.

     ExternalIgnoreList - OpenDKIM이 외부 호스트에 대한 DKIM확인을 식별하기 위한 리스트

     InternalHosts - OpenDKIM이 내부 호스트에 대한 DKIM확인을 식별하기 위한 리스트


    STEP03 → DKIM 서명 테이블, 키 테이블, 신뢰 호스트 설정

    순차적으로 진행, [mydomain] 부분을 개인 또는 기업에서 사용하는 도메인을 입력하시면 됩니다.

    ① SigningTable 서명 테이블 설정

    [root@ ~]# vim /etc/opendkim/SigningTable    [구성파일 편집]

     

    #*@mydomain.com default._domainkey.mydomain.com    [예시]

    *@foxydog.co.kr main0622._domainkey.foxydog.co.kr    [추가]

     

     발신자의 메일 메시지에 하나 이상의 서명을 적용하는 방식을 제어합니다.

     domainkey 앞부분은 일종의 DKIM 식별 코드라고 생각하시면 됩니다. 이름은 무엇이든 사용할 수 있지만 앞으로 설정할 키를 구분할 수 있는 편한 이름으로 등록하는 게 좋습니다. 

     *@mydomain.com은 도메인에서 발송되는 모든 계정[WILDCARD]에 대하여 서명 체크를 합니다. 이 말의 뜻은 사용자 계정별로 또는 도메인별[NON-WILDCARD]로 서명을 식별할 수 있도록 설정을 할 수 있다는 뜻입니다.

     

    ② KeyTable 키 테이블 설정

    [root@ ~]# vim /etc/opendkim/KeyTable    [구성파일 편집]

     

    #default._domainkey.mydomain.com mydomain.com:default:/etc/opendkim/keys/default.private    [예시]

    main0622._domainkey.foxydog.co.kr foxydog.co.kr:main0622:/etc/opendkim/keys/foxydog.co.kr/main0622.private    [추가, 전체 한 줄]

     

     SigningTable 서명 테이블에서 정한 이름을 그대로 사용

     

    ③ TrustedHosts 신뢰할 수 있는 호스트 설정

    [root@ ~]#  vim /etc/opendkim/TrustedHosts    [구성파일 편집]

     

    127.0.0.1    [IP4 로컬, 기본 설정]
    ::1    [IP6 로컬, 기본 설정]
    #host.example.com    [예시]
    #192.168.1.0/24    [예시, 대역대로 등록 가능]
    mail.foxydog.co.kr    [본인 메일서버 호스트 또는 IP 등록]

     

    ◇ 일반적으로 로컬 처리에 대해서는 기본적으로 신뢰할 수 있으므로 본인 메일서버의 호스트 또는 IP를 입력합니다. 즉 본인 도메인으로 오는 이메일 주소의 경우 OpenDKIM이 DKIM 확인을 수행하지 않음을 알려주는 역할을 합니다.


    STEP04 → 개인 및 공개 키 생성

    ◇ 진행하기 전 도메인에 대한 별도의 폴더를 생성합니다.

    [root@ ~]# mkdir /etc/opendkim/keys/foxydog.co.kr

    ◇ 공개키를 만들기 위해서는 Tool도구를 설치할 필요가 있습니다.

    [root@ ~]# dnf install opendkim-tools

     

    □ opendkim-genkey 도구를 이용하여 키를 생성

    [root@ ~]# opendkim-genkey -b 2048 -d foxydog.co.kr -D /etc/opendkim/keys/foxydog.co.kr -s main0622 -v    [전체 한 줄]

     

    ◇ -b 2048 은 암호화 길이 RSA-2048비트로 설정한다는 뜻입니다. 이전만 해도 1024비트를 이용했으나 최근에는 보안정책으로 대부분이 2048비트로 변경하는 추세입니다.

    ◇ -d (Domain) 도메인을 지정합니다.

    ◇ -D (Directory) 키가 저장될 디렉토리를 지정합니다.

    ◇ -s (DKIM) -v 서명 및 키 테이블에서 만들었던 DKIM(main0622) 명을 선택합니다.

    ◇ 권한 설정 및 생성 확인

    [root@ ~]# chown opendkim:opendkim -R /etc/opendkim/keys/    [권한 설정]

    [root@ ~]# chmod 700 /etc/opendkim/keys    [권한 설정]

     

    [root@ ~]# ls -al /etc/opendkim/keys/foxydog.co.kr/    [확인]

    -rw------- 1 opendkim opendkim 1679  6월 23 01:49 main0622.private    [개인 키]
    -rw------- 1 opendkim opendkim  501  6월 23 01:49 main0622.txt    [공개 키]

     

    ◇ 키 파일은 기본적으로 600으로 생성이 됩니다.

    ◇ 기본적으로 루트(Root)만 키 파일을 읽고 쓸 수 있으므로 opendkim 계정으로 소유자로 변경합니다. 


    STEP05 → DNS레코드에 공개 키 등록

    ◇ DNS레코드에 등록할 공개 키 확인 [스크린샷 참고]

    [root@ ~]# cat /etc/opendkim/keys/foxydog.co.kr/20220621.txt

    ① DNS 관리에서 TXT 레코드를 생성합니다.

    ◇ 네임서버[DNS]의 경우는 관리하는 업체마다 천차만별입니다. 필자는 개인적인 테스트를 위해 구축한 PowerDNS를 통한 레코드 등록 방식입니다. OpenDKIM에서 생성한 공개키. TXT 파일은 Bind9 네임서버 형식을 기준으로 설명하다 보니 콤마["  "]로 띄어쓰기 구분을 해놓았습니다만 [Content] 값을 연결을 할 때는 전체 한 줄입니다.

    [예시]

    글자 수 길이[약 400자가 넘어감]

    "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5iCQchVwQIUEry48m2RstfzC18sd28A94ZreIiq0pDH5on5+gkEi+vnoX124ZCiGrQ1ov6AJiJUvwcAft7suKpEMRVN983Uo29eQcxot9K/sf3UGczsr/4UhzqIfMSwGl4I3hDvb6QxqqD/rVeT3nLy6HaAqlq4gJw5LAQaHnHOxFwd4+jSMf+Xk8hHKZlOY3yorm5v0mHeEpgGTmtfl90SLbUeZF8ipJOH/4QOf7wYqHZQiJVnSL2Yp7MbZZguMYPpLc3XFDGsgcmNGFU1IAxsH+K38JEHloc2fI9iXGoOY8ae1RC5kWSbWEIkl1KptkSpogbAGqRyJYyJL6ycU5QIDAQAB"

     

    ②[예외상황]

    그래서 글자 수 길이가 길다 보니 발생하는 변수가 생깁니다. 대부분의 호스팅 업체가 도메인 상품을 판매하고 있으며 네임서버를 직접 관리할 수 있는 툴을 제공하고 있습니다. 하지만 TXT값이 DB에 들어갈 수 있는 길이를 250~255로 제한하기 때문에 암호화 길이의 RSA-2048비트의 공개키를 넣지 못하는 상황이 발생합니다.

    ③[해결방법]

    방법은 TXT레코드 값을 넣는 DB 저장 길이 크기가 제한이 없는 제공 업체의 네임서버를 변경하여 이용하거나 DKIM공개키를 짧게 할 수밖에 없습니다. 즉, 키를 생성 할시에 -b 2048 옵션을 제외하여 기본적인 RSA-1024비트를 사용해야 합니다. DKIM정책만 적용하실 목적이라면 아래와 같이 키를 발급받으시면 됩니다.

     

    [root@ ~]# opendkim-genkey -d foxydog.co.kr -D /etc/opendkim/keys -s test0622 -v

    [root@ ~]# cat /etc/opendkim/keys/test0622.txt

    글자 수 길이[약 236자]

    "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDs6/cx5gOJgfD1X6wEI/bl3J4UaLCggm/pB8hsldyyIfIc5uwpbCGcsa3sMSl47N46MqlzBUK5eFjy2Toje49h+UUNXUx6XnC50Om1h6bh+2MDZuIiTkHpiQ4K2ri6Yc6K5YiV+CqJMoqQkETZQcfoGKzKohnQLnQXsVTYDB7ASwIDAQAB"

    해당 내용은 구글이나 아마존[AWS] 서포트에서도 확인할 수 있습니다.

    구글 : https://support.google.com/a/answer/11613097

    아마존[AWS] : https://aws.amazon.com/ko/premiumsupport/knowledge-center/route53-resolve-dkim-text-record-error/

     

    ※ 네임서버에 DKIM TXT레코드를 등록하고 인터넷에 전파되는 데는 시간이 필요할 수 있습니다.

    사용하는 도메인 등록 기관에 따라 DNS 레코드가 최소[1시간] ~ 최대[24시간]가 걸릴 수 있습니다.


    STEP06 → DKIM키 테스트

    ①서버 내 opendkim-testkey 도구를 이용한 테스트

    ◇ 내 서버에서 네임서버를 질의하실 경우는 방화벽 TCP/UDP 53번 포트를 오픈해야 합니다.

    [root@ ~]# firewall-cmd --permanent --add-port=53/tcp --add-port=53/udp    [방화벽 추가]

    success

    [root@ ~]# firewall-cmd --reload    [적용]

    success

    ◇ DKIM 응답 테스트

    [root@mail foxydog.co.kr]# opendkim-testkey -d foxydog.co.kr -s main0622 -vvv

    opendkim-testkey: using default configfile /etc/opendkim.conf

    opendkim-testkey: checking key 'main0622._domainkey.foxydog.co.kr'

    opendkim-testkey: key not secure

    opendkim-testkey: key OK    [정상 패턴]

    [참고]

    key not secure가 신경이 쓰이실 텐데, 이 내용을 이해하기 위해서는 네임서버의 DNSSEC정책을 알아야 합니다. 아직까지 대부분의 네임서버가 DNSSEC로 구성되어 있지 않습니다.

    DNSSEC (Domain Name System Security Extension)는 DNS를 대체하는 게 아닌 기존의 DNS에 DKIM 같은 공개키를 암호화 방식의 보안 기능을 추가하여 DNS의 보안성을 강화하는 역할을 합니다. 체크 툴이 DNSSEC 구성이 되어 있지 않을 경우 무조건 "key not secure" 메시지가 떨어집니다. 일반적인 구성에서는 뜨는 게 정상입니다. 우리는 Key OK만 나오면 됩니다.

    ②사이트를 이용한 DKIM 체크

    네임서버 체크 사이트 : https://mxtoolbox.com/SuperTool.aspx?action

    해당 사이트는 해외에서도 유명하며, 여러 가지 체크 툴이 많아서 알아두시면 유용합니다.

    DKIM Lookup을 선택을 하고

    DKIM 호스트를 생성한 이름을 입력합니다 : [main0622]._domainkey.[mydomain.com]


    STEP07 → OpenDKIM 서비스 시작

    [root@ ~]# systemctl start opendkim    [서비스 시작]

    [root@ ~]# systemctl enable opendkim    [서비스 자동 시작 등록]

    Created symlink /etc/systemd/system/multi-user.target.wants/opendkim.service → /usr/lib/systemd/system/opendkim.service.

     

    [root@ ~]# ps -ef |grep opendkim    [실행 프로세스 확인]

    opendkim /usr/sbin/opendkim -x /etc/opendkim.conf -P /run/opendkim/opendkim.pid


    STEP08 → Postfix에 OpenDKIM Socket 연결

    [root@ ~]# vim /etc/postfix/main.cf   [구성 파일 편집]

     

    ◇ milter 프로토콜을 이용한 OpenDKIM 호출하는 방식을 이용한다고 합니다.

    # Milter configuration
    milter_default_action = accept
    milter_protocol = 6
    smtpd_milters = inet:127.0.0.1:8891
    non_smtpd_milters = $smtpd_milters

    ◇ opendkim그룹에 postfix 사용자를 등록합니다.

    [root@ ~]# gpasswd -a postfix opendkim

    사용자 postfix을(를) opendkim 그룹에 등록 중

     

    [root@ ~]# cat /etc/group | grep opendkim [등록 확인]
    mail:x:12:postfix,opendkim
    opendkim:x:982:postfix

    ◇ Postfix 서비스 재시작

    [root@ ~]# systemctl restart postfix


    STEP09 → Postfix Maillog에서 수신,발신 이메일 헤더 DKIM값 확인

    ◇ 서버 로그에서 직접 확인

    [root@ ~]# tail -f /var/log/maillog    [실시간 로그 확인]

    ⓛ DKIM값이 있는 포탈에서 수신[네이버 예시] : Successful [통과]

    mail opendkim[90364]: 3DA58800A1: cvsmtppost032.nm.naver.com [발송IP] not internal
    mail opendkim[90364]: 3DA58800A1: not authenticated
    mail opendkim[90364]: 3DA58800A1: DKIM verification successful

    ② DKIM값이 없는 일반 기업 메일 수신 : No signature data [통과는 되었지만 의심 필요]

    mail opendkim[90364]: E5CF1800A1: [발송IP] not internal
    mail opendkim[90364]: E5CF1800A1: not authenticated
    mail opendkim[90364]: E5CF1800A1: no signature data

    ③ 메일 발송시 헤더 DKIM 필드 추가 : Signature field added [발송]

    mail opendkim[90364]: E1820800BC: DKIM-Signature field added (s=main0622, d=foxydog.co.kr)

     

    ④ 웹메일 수신 헤더에서 직접 확인[스크린샷 참고]

     

    ⑤ 발송한 메일을 Gmail에서 수신 DKIM 확인


    ■ 트러블슈팅(troubleshooting)

    ◇ Postfix 메일 발송 시 에러 발생

    ① can't load key : No such file or directory

    mail opendkim[88396]: can't load key from /etc/opendkim/keys/foxydog.co.kr/20200308.private: No such file or directory

    mail opendkim[88396]: 9A2EF800F5: error loading key '20220621._domainkey.foxydog.co.kr'

    → /etc/opendkim/KeyTable 테이블 설정 잘못되어 있는지 확인

    ② key data is not secure

    mail opendkim[89388]: 20220621._domainkey.foxydog.co.kr: key data is not secure:

    /etc/opendkim/keys/foxydog.co.kr/20220621.private is in group 982 which has multiple users (e.g., "postfix")

    mail opendkim[89388]: 04651800BC: error loading key '20220621._domainkey.foxydog.co.kr'

    → 공개키와 Key가 일치하지 않을 경우

    ③ can't load key from : Permission denied

    mail opendkim[89388]: can't load key from /etc/opendkim/keys/foxydog.co.kr/20220621.private: Permission denied
    mail opendkim[89388]: 7DBFD800F5: error loading key '20220621._domainkey.foxydog.co.kr'

    → /etc/opendkim/keys/ 경로의 권한 문제로 발생, /key 폴더는 700 권한으로 설정


    마치며

    처음 포스팅 구성을 생각했을 때는 이렇게 길지 않았지만 자료를 모으고 테스트하는 과정에서 예상외 변수가 많이 발생하다 보니 내용이 많이 길어졌습니다. 원리는 단순하지만 DKIM의 경우 공개키와 그것을 해독하는 KEY를 일치하는 과정에서 네임서버[DNS]의 역할도 중요하기 때문에 최대한 상세히 남겨두었습니다. 다음은 마지막으로 DMARC 정책을 알아보도록 하겠습니다.

    Designed by JB FACTORY