[Linux]쉽게 따라하는 Linux 서버에서 메일 보내기(postfix 사용)
리눅스 서버에서 postfix 패키지를 이용해서 메일 보내기 기능을 설정해 보겠습니다. 메일 보내기 기능을 설치해 놓으면 Daily Health Check Report 등을 이메일로 보낼 수 있으며, crontab과 연결해서 예약 메일 보내기 기능도 구현할 수 있습니다. 여기는 naver 메일의 smtp 서버(smtp.naver.com)과 포트(465)를 이용하겠습니다. 네이버 메일 > 환경설정 > POP3/SMTP 사용함으로 저장해야 합니다.
- 메일 서비스 관련 패키지 설치 및 확인
- 메일 서버 환경 설정 및 확인
- 메일 보내기 테스트
- 예약 메일 보내기
1. 메일 서버시 관련 패키지 설치 및 데몬 실행
- postfix, mailx, cyrus-sasl-plain 패키지를 설치합니다.
$ yum -y install postfix mailx cyrus-sasl-plain Last metadata expiration check: 0:01:33 ago on Wed 26 Jul 2023 02:39:35 AM KST. Package postfix-2:3.5.8-6.el8.x86_64 is already installed. Package mailx-12.5-29.el8.x86_64 is already installed. Package cyrus-sasl-plain-2.1.27-6.el8_5.x86_64 is already installed. Dependencies resolved. Nothing to do. Complete!
`rpm -ql postfix` 명령어로 패키지에서 설치한 파일들을 확인합니다. /etc/postfix/ 디렉토리에 환경설정 파일이 있으며, postfix.service 데몬을 실행시켜야 합니다.$ systemctl enable --now postfix.service Created symlink /etc/systemd/system/multi-user.target.wants/postfix.service /usr/lib/systemd/system/postfix.service.
2. 메일 서버 환경 설정 및 확인
- /etc/postfix/main.cf이 환경설정 파일입니다. 아래에 있는 지시자들을 등록해야 합니다. 붉은 색 지시자만 수정 또는 추가 등록하면 됩니다. 주석처리(#)된 지시자는 주석처리를 삭제하세요. 설정 완료 후
postconf -n 명령어또는postfix check 명령어로 점검하면 잘못되었거나 누락된 설정사항을 확인할 수 있습니다.alias_database = hash:/etc/aliases alias_maps = hash:/etc/aliases command_directory = /usr/sbin compatibility_level = 2 daemon_directory = /usr/libexec/postfix data_directory = /var/lib/postfix debug_peer_level = 2 debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5 html_directory = no inet_interfaces = loopback-only inet_protocols = all mail_owner = postfix mailq_path = /usr/bin/mailq.postfix manpage_directory = /usr/share/man meta_directory = /etc/postfix mydestination = $myhostname, localhost.$mydomain, localhost mydomain = centos8 myhostname = centos8 myorigin = $mydomain newaliases_path = /usr/bin/newaliases.postfix queue_directory = /var/spool/postfix readme_directory = /usr/share/doc/postfix/README_FILES relayhost = [smtp.naver.com]:465 sample_directory = /usr/share/doc/postfix/samples sendmail_path = /usr/sbin/sendmail.postfix setgid_group = postdrop shlib_directory = /usr/lib64/postfix smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt smtp_tls_CApath = /etc/pki/tls/certs smtp_tls_security_level = encrypt smtp_tls_wrappermode = yes smtp_use_tls = yes smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem smtpd_tls_key_file = /etc/pki/tls/private/postfix.key smtpd_tls_security_level = encrypt unknown_local_recipient_reject_code = 550
- SMTP 서버의 사용자 등록 및 해시 파일 생성
$ vi sasl_passwd [smtp.naver.com]:465 your_id@naver.com:your_passwd $ postmap ./sasl_passwd $ chown root:root ./sasl_passwd* $ chmod 0600 ./sasl_passwd* $ ll | grep sasl_passwd -rw-------. 1 root root 51 Jul 26 03:13 sasl_passwd -rw-------. 1 root root 12288 Jul 26 03:15 sasl_passwd.db
- 종합 권장 /etc/postfix/main.cf 보안 스니펫
# 1. Information Hiding & Anti-Reconnaissance ## Postfix 버전 정보 숨기기 (기본값인 버전 표기를 제거하고 호스트명만 응답, ESMTP: Extended SMTP) smtpd_banner = $myhostname ESMTP ## VRFY 명령어는 외부에서 VRFY user@domain.com과 같이 메일을 직접 보내지 않고도 특정 계정이 이 서버에 실제 존재하는지 확인할 수 있는 명령어로 ## 해커나 스패머가 사전 공격(Dictionary Attack)으로 서버 내 존재 계정 목록을 수집(User Enumeration)하는 데 악용하는 것을 차단합니다. disable_vrfy_command = yes ## HELO/EHLO 호스트명 필수 요구 (올바르지 않은 접근 차단) smtpd_helo_required = yes # 2. Access Control & Anti-Open Relay ## 릴레이 허용 네트워크 (자기 자신 및 신뢰할 수 있는 내부 IP만 지정) mynetworks = 127.0.0.0/8 [::1]/128 192.168.0.0/16 ## 릴레이 제한 (Postfix 2.10 이상 권장 분리 설정) smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination ## 수신자 제한 (순서가 중요합니다) ## reject_unauth_destination: 앞 두 조건에 해당하지 않는 사용자가 외부 도메인으로 메일을 발송하려고 하면 거부합니다. smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_invalid_hostname, reject_non_fqdn_recipient, reject_unknown_recipient_domain ## 스패머들이 자주 사용하는 가짜 도메인이나 잘못된 형식의 호스트명 접근을 1차적으로 필터링합니다. smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname # 3. TLS & SASL Authentication ## 외부와 메일을 주고받을 때 TLS 사용 (가능한 경우 적용) smtpd_tls_security_level = may smtp_tls_security_level = may ## 서버 인증서 및 개인키 경로 smtpd_tls_cert_file = /etc/letsencrypt/live/yourdomain.com/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/yourdomain.com/privkey.pem ## 취약한 구형 프로토콜(SSLv2, SSLv3, TLSv1, TLSv1.1) 차단 (TLS 1.2 / 1.3만 허용) smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 ## SASL 사용자 인증 보안 smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth ## 핵심: TLS 암호화 연결(HTTPS/SMTPS) 상태가 아닐 때는 SASL 로그인 자체를 금지 smtpd_tls_auth_only = yes ## 익명 로그인 및 평문 인증 거부 smtpd_sasl_security_options = noanonymous, noplaintext smtpd_sasl_tls_security_options = noanonymous # 4. Resource Limits (DoS Protection) ## 1회 전송 최대 메일 크기 제한 (예: 20MB) message_size_limit = 20971520 ## 클라이언트당 동시에 연결 가능한 최대 세션 수 smtpd_client_connection_count_limit = 10 ## 동일 클라이언트에서 일정 시간 내 생성 가능한 연결 빈도 제한 smtpd_client_connection_rate_limit = 30 ## 잘못된 바이트 입력 및 에러 발생 시 세션 즉시 강제 종료 세기 smtpd_hard_error_limit = 5
3. 메일 보내기 테스트
- postfix 데몬 재시작 및 상태 확인
$ systemctl restart postfix $ systemctl status postfix [0m postfix.service - Postfix Mail Transport Agent Loaded: loaded (/usr/lib/systemd/system/postfix.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2023-07-26 03:20:03 KST; 36s ago
- 이메일 보내기 테스트 및 확인
$ echo "This is the body of the email" | mail -s "This is the subject line" -r your_id@naver.com receiver_email $ mailq Mail queue is empty
- 메일이 전송되지 않는다면 전송오류로 쌓인 메일큐를 삭제, 설정 재확인 후 postfix 데몬 재시작
$ mailq | awk '$7~/@/{print$1}' | while read qid; do postsuper -d $qid; done $ vi main.cf $ postfix check $ systemctl restart postfix.service
4. 예약 메일 보내기
- crontab 명령어를 사용해서 보낼 메일을 등록해 놓는다
$ vi /root/sendmail.sh TITLE="subject" FR_ADDR="your_id@naver.com" TO_ADDR="email1 email2" ATTACH="/path/attachment_file" BODY="/path/content_file" mail -s ${TITLE} -a ${ATTACH} -r ${FR_ADDR} ${TO_ADDR} < ${BODY} $ chmod 755 /root/sendmail.sh $ crontab -e 분 시 일 월 주 /root/sendmail.sh
