1๏ธโƒฃ ๋ฐฐ๊ฒฝ: ์™œ ๋ฉ”์ผ ์•Œ๋ฆผ์ด ํ•„์š”ํ–ˆ๋Š”๊ฐ€?

๋„๋ฉ”์ธ ์ธ์ฆ์„œ(SSL)๋Š” Let’s Encrypt๋กœ ๋ฌด๋ฃŒ ๋ฐœ๊ธ‰์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ,
์ด๋ฒˆ์— Wildcard ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค ์ˆ˜๋ฐ–์— ์—†์—ˆ๋‹ค.
ํŠนํžˆ *.๋„๋ฉ”์ธ ํ˜•ํƒœ์˜ Wildcard ์ธ์ฆ์„œ๋Š” DNS TXT ๋ ˆ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๋“ฑ๋กํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

(๐Ÿ’ก ๋ณด์ถฉ ์„ค๋ช…)
์ผ๋ฐ˜ ๋„๋ฉ”์ธ(example.com, www.example.com)์€ HTTP-01 ์ธ์ฆ ๋ฐฉ์‹์„ ์ด์šฉํ•ด ์ž๋™ ๊ฐฑ์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
์ฆ‰, certbot renew๋ฅผ ํฌ๋ก (cron)์— ๋“ฑ๋กํ•ด๋‘๋ฉด,
์„œ๋ฒ„๊ฐ€ ์ž๋™์œผ๋กœ /.well-known/acme-challenge/ ๊ฒฝ๋กœ์— ์ž„์‹œ ์ธ์ฆํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ 
Let’s Encrypt๊ฐ€ HTTP ์š”์ฒญ์œผ๋กœ ์ด๋ฅผ ํ™•์ธํ•ด ์ธ์ฆ์„ ๊ฐฑ์‹ ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ Wildcard(*.example.com)์˜ ๊ฒฝ์šฐ,
ํ•˜์œ„ ๋„๋ฉ”์ธ ์ „์ฒด(aaa.example.com, bbb.example.com ๋“ฑ)์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ์ฆ๋ช…ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
HTTP ๋ฐฉ์‹๋งŒ์œผ๋กœ๋Š” “๋„๋ฉ”์ธ ์ „์ฒด์˜ ์†Œ์œ ์ž์ž„”์„ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค.
๊ทธ๋ž˜์„œ Let’s Encrypt๋Š” DNS-01 ๋ฐฉ์‹, ์ฆ‰ “DNS์— TXT ๋ ˆ์ฝ”๋“œ๋กœ ์ธ์ฆ๊ฐ’์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•”๋งŒ ํ—ˆ์šฉํ•œ๋‹ค.


๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€๋น„์•„(Gabia) ๋Š” DNS API๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—,
Certbot์ด ์ž๋™์œผ๋กœ TXT ๋ ˆ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค.
(์ด ๋ถ€๋ถ„ ๋•Œ๋ฌธ์— ๊ฐ€๋น„์•„๋ฅผ ์“ฐ๋Š” ๊ฑธ ์กฐ๊ธˆ ํ›„ํšŒ ์ค‘... ๐Ÿ˜…
AWS Route 53, Cloudflare, Google Cloud DNS ๋“ฑ์€
API๋ฅผ ํ†ตํ•ด TXT ๋ ˆ์ฝ”๋“œ๋ฅผ ์ž๋™ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์–ด Wildcard ์ž๋™๊ฐฑ์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.)


์ฆ‰, ๋งค๋ฒˆ ์•„๋ž˜ ๋ช…๋ น์„ ์ง์ ‘ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค ๐Ÿ‘‡

sudo certbot certonly --manual --preferred-challenges dns \
  -d example.com -d '*.example.com'

๊ทธ๋ฆฌ๊ณ  DNS TXT ๋‘ ๊ฐœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.

์ด ๊ณผ์ • ์ž์ฒด๋Š” ์–ด๋ ต์ง€ ์•Š์ง€๋งŒ,
๐Ÿ‘‰ ์ธ์ฆ์„œ ์œ ํšจ๊ธฐ๊ฐ„(90์ผ)์„ ๊นœ๋นกํ•˜๋ฉด ์‚ฌ์ดํŠธ๊ฐ€ “๋ณด์•ˆ ์—ฐ๊ฒฐ ์‹คํŒจ”๋กœ ์ค‘๋‹จ๋œ๋‹ค.
๊ทธ๋ž˜์„œ ๋งŒ๋ฃŒ 30์ผ ์ „ ๋ฉ”์ผ๋กœ ์ž๋™ ์•Œ๋ฆผ์ด ์˜ค๋„๋ก ์„ค์ •ํ•ด๋‘์—ˆ๋‹ค.

 


2๏ธโƒฃ ํ™˜๊ฒฝ ์š”์•ฝ

ํ•ญ๋ชฉ ๋‚ด์šฉ

OS Rocky Linux 9
์ธ์ฆ์„œ Let’s Encrypt (Wildcard)
DNS ๊ฐ€๋น„์•„ (API ๋ฏธ์ง€์›)
๋ฉ”์ผ ์ „์†ก Postfix + s-nail + Naver SMTP (465 SSL)
์•Œ๋ฆผ ์Šคํฌ๋ฆฝํŠธ /root/check-ssl.sh (cron ์ž๋™ ์‹คํ–‰)

3๏ธโƒฃ ๋ฉ”์ผ ๋ฐœ์†ก ์‹คํŒจ ์ด์œ ์™€ ํ•ด๊ฒฐ

์ดˆ๊ธฐ์—” s-nail๋กœ ๋ฉ”์ผ์„ ๋ณด๋‚ด๋ ค ํ–ˆ์ง€๋งŒ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ ๋กœ๊ทธ

550 5.7.2 Your email has been blocked because the sender is unauthenticated.

์ด๋Š” Postfix๊ฐ€ ๋‹จ์ˆœ ๋กœ์ปฌ ์†ก์‹ (unauthenticated)์ด๋ผ์„œ
๋„ค์ด๋ฒ„ SMTP ์ธ์ฆ์ด ์•ˆ ๋œ ์ƒํƒœ์˜€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

โœ… ํ•ด๊ฒฐ ๊ณผ์ • ์š”์•ฝ

๊ฐ€๋น„์•„ DNS ํ™˜๊ฒฝ์—์„œ Let’s Encrypt Wildcard ์ธ์ฆ์„œ ๋งŒ๋ฃŒ ์•Œ๋ฆผ ๋ฉ”์ผ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด
๋กœ์ปฌ ์„œ๋ฒ„(Postfix)๊ฐ€ ๋„ค์ด๋ฒ„ SMTP ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ์ธ์ฆ ๋ฐœ์†กํ•˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.


1๏ธโƒฃ Postfix ๋ฐ ๋ฉ”์ผ ์œ ํ‹ธ ์„ค์น˜

sudo dnf install -y postfix s-nail
sudo systemctl enable --now postfix
  • postfix: ๋ฉ”์ผ ์ „์†ก(MTA) ์„œ๋ฒ„
  • s-nail: ๊ฐ„๋‹จํ•œ CLI ๋ฉ”์ผ ๋ฐœ์†ก ๋„๊ตฌ
  • enable --now: ๋ถ€ํŒ… ์‹œ ์ž๋™ ์‹คํ–‰ + ์ฆ‰์‹œ ์‹œ์ž‘

2๏ธโƒฃ SMTP ์ธ์ฆ ์„ค์ • (/etc/postfix/main.cf)

inet_interfaces = 127.0.0.1
inet_protocols = ipv4
relayhost = [smtp.naver.com]:465

smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_generic_maps = hash:/etc/postfix/generic

๐Ÿ“Œ

  • relayhost: ๋„ค์ด๋ฒ„ SMTP ์„œ๋ฒ„ ์ง€์ •
  • smtp_sasl_password_maps: ๊ณ„์ •/๋น„๋ฐ€๋ฒˆํ˜ธ ์ €์žฅ ์œ„์น˜
  • smtp_generic_maps: ๋กœ์ปฌ root ์ฃผ์†Œ๋ฅผ ๋„ค์ด๋ฒ„ ๋ฉ”์ผ ์ฃผ์†Œ๋กœ ๋ณ€ํ™˜

3๏ธโƒฃ SMTP ๋น„๋ฐ€๋ฒˆํ˜ธ ํŒŒ์ผ ์„ค์ •

sudo nano /etc/postfix/sasl_passwd
[smtp.naver.com]:465 example@naver.com:์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋น„๋ฐ€๋ฒˆํ˜ธ

 

sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

๐Ÿ’ก

  • ์ผ๋ฐ˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์‚ฌ์šฉ ๋ถˆ๊ฐ€
    ๋„ค์ด๋ฒ„ 2๋‹จ๊ณ„ ์ธ์ฆ ํ™œ์„ฑํ™” ํ›„ ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•จ. (์ค‘์š”!!)
  • postmap: Postfix๊ฐ€ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ํ•ด์‹œ DB๋กœ ๋ณ€ํ™˜.
  • chmod 600: ํŒŒ์ผ ๊ถŒํ•œ ์ œํ•œ(๋ณด์•ˆ ๋•Œ๋ฌธ์—!)

4๏ธโƒฃ ๋ฉ”์ผ ์ฃผ์†Œ ๋ณ€ํ™˜ ์„ค์ •

sudo nano /etc/postfix/generic
root@xxx-web-01.example.kr  example@naver.com
sudo postmap /etc/postfix/generic

๐Ÿ“Œ
๋กœ์ปฌ์—์„œ root@xxx.example.kr ๋กœ ๋ฐœ์†ก๋˜๋Š” ๋ฉ”์ผ์„
์™ธ๋ถ€์—์„œ๋Š” example@naver.com ์œผ๋กœ ๋ณด์ด๊ฒŒ ๋ณ€ํ™˜.


5๏ธโƒฃ Postfix ์žฌ์‹œ์ž‘

sudo systemctl restart postfix

6๏ธโƒฃ ํ…Œ์ŠคํŠธ ๋ฉ”์ผ ๋ฐœ์†ก

echo "ํ…Œ์ŠคํŠธ ๋ฉ”์ผ์ž…๋‹ˆ๋‹ค." | s-nail -s "Postfix → Naver OK?" -r example@naver.com example@naver.com

์ดํ›„ ๋กœ๊ทธ ํ™•์ธ ๐Ÿ‘‡

sudo tail -n 50 /var/log/maillog

์ •์ƒ์ด๋ผ๋ฉด ๋‹ค์Œ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค:

250 2.0.0 OK ... - nsmtp

๐ŸŽ‰ SMTP ์ธ์ฆ ์„ฑ๊ณต!
์ด์ œ ์„œ๋ฒ„๊ฐ€ ๋„ค์ด๋ฒ„ SMTP๋ฅผ ํ†ตํ•ด ์ •์ƒ์ ์œผ๋กœ ์ธ์ฆ๋œ ๋ฉ”์ผ์„ ๋ฐœ์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ ํ…Œ์ŠคํŠธ ์„ฑ๊ณตํ–ˆ์œผ๋‹ˆ ํ•ด๋‹น ๊ด€๋ จํ•ด์„œ ํฌ๋ก ์—์„œ ์‹คํ–‰ ๋˜๋„๋ก ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž!


4๏ธโƒฃ SSL ๋งŒ๋ฃŒ ์•Œ๋ฆผ ์Šคํฌ๋ฆฝํŠธ

/root/check-ssl.sh

#!/usr/bin/env bash
EMAIL="example@naver.com"
CERT="/etc/letsencrypt/live/example.kr/fullchain.pem"
THRESHOLD=30  # ๋งŒ๋ฃŒ 30์ผ ์ดํ•˜๋ถ€ํ„ฐ ์•Œ๋ฆผ

if [[ ! -f "$CERT" ]]; then
  echo "โš ๏ธ ์ธ์ฆ์„œ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: $CERT" |
  s-nail -s "[SSL ๊ฒฝ๊ณ ] example.kr ์ธ์ฆ์„œ ํŒŒ์ผ ์—†์Œ" "$EMAIL"
  exit 1
fi

EXPIRE_RAW=$(openssl x509 -in "$CERT" -noout -enddate | cut -d= -f2)
EXPIRE_TS=$(date -d "$EXPIRE_RAW" +%s)
NOW_TS=$(date +%s)
DAYS_LEFT=$(( (EXPIRE_TS - NOW_TS) / 86400 ))

if (( DAYS_LEFT <= THRESHOLD )); then
  SUBJECT="โš ๏ธ example.kr SSL ${DAYS_LEFT}์ผ ํ›„ ๋งŒ๋ฃŒ ์˜ˆ์ •"
  BODY=$(cat <<EOF
๋„๋ฉ”์ธ: example.kr (*.enhasys.kr)
์ธ์ฆ์„œ ๊ฒฝ๋กœ: $CERT
๋งŒ๋ฃŒ์ผ: $EXPIRE_RAW (D-${DAYS_LEFT})

โœ… ์กฐ์น˜ ๋ฐฉ๋ฒ•:
1. ๊ฐ€๋น„์•„ DNS์— TXT 2๊ฐœ ์ถ”๊ฐ€
2. ์•„๋ž˜ ๋ช…๋ น์œผ๋กœ ๊ฐฑ์‹  ์‹คํ–‰

sudo certbot certonly --manual --preferred-challenges dns \
  -d example.kr -d '*.example.kr'

EOF
)
  echo "$BODY" | s-nail -s "$SUBJECT" "$EMAIL"
fi

5๏ธโƒฃ ํฌ๋ก  ์„ค์ •

crontab -e
0 3 * * * certbot renew --quiet
0 9 * * * /root/check-ssl.sh
  • ์˜ค์ „ 3์‹œ: ์ž๋™ ๊ฐฑ์‹  ์‹œ๋„ (์ผ๋ฐ˜ ๋„๋ฉ”์ธ์šฉ) (์™€์ผ๋“œ ์นด๋“œ๊ฐ€ ์•„๋‹Œ ๋„๋ฉ”์ธ๋“ค์€ ์ด๋ ‡๊ฒŒ ์ง์ ‘ ์ž๋™ ๊ฐฑ์‹ ์ด ๋˜๋„๋ก ํ•ด๋†จ๋‹ค.)
  • ์˜ค์ „ 9์‹œ: example.kr ๋งŒ๋ฃŒ์ผ ์ฒดํฌ ํ›„ ๋ฉ”์ผ ๋ฐœ์†ก

โœ… ๊ฒฐ๊ณผ

  • ์ด์ œ example.kr ์™€์ผ๋“œ์นด๋“œ ์ธ์ฆ์„œ๋งŒ ์ˆ˜๋™ ๊ฐฑ์‹ ํ•˜๋ฉด ๋จ
  • ๋‚˜๋จธ์ง€ ๋„๋ฉ”์ธ(example1.co.kr, example2.co.kr)์€ ์ž๋™ ๊ฐฑ์‹ ๋จ
  • ๋งŒ๋ฃŒ 30์ผ ์ „ ์ž๋™ ๋ฉ”์ผ ๋„์ฐฉ์œผ๋กœ ๊นœ๋นกํ•  ์ผ์ด ์—†์Œ

๐Ÿ“Ž ๊ฒฐ๋ก 

  • Postfix ์„ค์ •
  • SASL ์ธ์ฆ
  • ๊ฐ€๋น„์•„ API ๋ถ€์žฌ ๋Œ€์‘
  • crontab ์ž๋™ํ™”
    ๊นŒ์ง€ ํ•ด์•ผํ•˜๋Š” ๊ณผ์ •์ด์—ˆ๋‹ค.
  • (์ฆ‰ DNS๋Š” ๊ผญ API ์žˆ๋Š”๊ฑธ๋กœ ์‚ฌ์šฉํ•˜์‹œ๊ธธ  @@)