- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스) - Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포 - 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
155 lines
4.7 KiB
Python
155 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Postfix + Dovecot SMTP/IMAP 서버 설치
|
|
도메인: zioinfo.co.kr (IP 기반, DNS MX 없어도 로컬 발송 가능)
|
|
계정: info, admin, ythong, choyounbun, guardia / 비밀번호: 1q2w3e!Q
|
|
"""
|
|
import paramiko, time, sys
|
|
|
|
HOST='101.79.17.164'; USER='root'; PASS='1q2w3e!Q'
|
|
DOMAIN = 'zioinfo.co.kr'
|
|
ACCOUNTS = ['info', 'admin', 'ythong', 'choyounbun', 'guardia']
|
|
MAIL_PASS = '1q2w3e!Q'
|
|
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
client.connect(HOST, username=USER, password=PASS, timeout=15)
|
|
sftp = client.open_sftp()
|
|
|
|
def run(label, cmd, timeout=120):
|
|
print(f'\n[{label}]')
|
|
chan = client.get_transport().open_session()
|
|
chan.set_combine_stderr(True)
|
|
chan.exec_command(f'export DEBIAN_FRONTEND=noninteractive; {cmd}')
|
|
start = time.time()
|
|
while not chan.exit_status_ready():
|
|
if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush()
|
|
if time.time()-start > timeout: print('[TIMEOUT]'); break
|
|
time.sleep(0.3)
|
|
while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096))
|
|
sys.stdout.flush()
|
|
rc = chan.recv_exit_status()
|
|
print(f'exit={rc}'); return rc
|
|
|
|
# 1. Postfix + Dovecot 설치
|
|
run('Postfix + Dovecot 설치',
|
|
'apt-get install -y -q postfix dovecot-imapd dovecot-pop3d mailutils',
|
|
180)
|
|
|
|
# 2. Postfix 설정
|
|
postfix_main_cf = f"""# Postfix Main Configuration — {DOMAIN}
|
|
smtpd_banner = $myhostname ESMTP
|
|
biff = no
|
|
append_dot_mydomain = no
|
|
|
|
# 호스트명 설정
|
|
myhostname = mail.{DOMAIN}
|
|
myorigin = /etc/mailname
|
|
mydomain = {DOMAIN}
|
|
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
|
|
|
|
# 네트워크
|
|
inet_interfaces = all
|
|
inet_protocols = ipv4
|
|
mynetworks = 127.0.0.0/8
|
|
|
|
# 메일박스 (Maildir 형식)
|
|
home_mailbox = Maildir/
|
|
mailbox_size_limit = 0
|
|
|
|
# SMTP 인증 (Dovecot SASL)
|
|
smtpd_sasl_type = dovecot
|
|
smtpd_sasl_path = private/auth
|
|
smtpd_sasl_auth_enable = yes
|
|
smtpd_sasl_security_options = noanonymous
|
|
|
|
# TLS (자체서명 인증서 사용)
|
|
smtpd_tls_cert_file = /etc/ssl/guardia/server.crt
|
|
smtpd_tls_key_file = /etc/ssl/guardia/server.key
|
|
smtpd_use_tls = yes
|
|
smtpd_tls_session_cache_database = btree:${{data_directory}}/smtpd_scache
|
|
smtp_tls_session_cache_database = btree:${{data_directory}}/smtp_scache
|
|
|
|
# 보안
|
|
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
|
|
recipient_delimiter = +
|
|
"""
|
|
|
|
dovecot_conf = f"""# Dovecot Configuration — {DOMAIN}
|
|
protocols = imap pop3 lmtp
|
|
listen = *
|
|
|
|
# 인증 메커니즘
|
|
auth_mechanisms = plain login
|
|
|
|
# 메일 저장소 (Maildir)
|
|
mail_location = maildir:~/Maildir
|
|
|
|
# Postfix SASL 소켓
|
|
service auth {{
|
|
unix_listener /var/spool/postfix/private/auth {{
|
|
mode = 0660
|
|
user = postfix
|
|
group = postfix
|
|
}}
|
|
}}
|
|
|
|
# SSL/TLS
|
|
ssl = yes
|
|
ssl_cert = </etc/ssl/guardia/server.crt
|
|
ssl_key = </etc/ssl/guardia/server.key
|
|
|
|
# 인증 드라이버
|
|
passdb {{
|
|
driver = pam
|
|
}}
|
|
userdb {{
|
|
driver = passwd
|
|
}}
|
|
|
|
# 로그
|
|
log_path = /var/log/dovecot.log
|
|
"""
|
|
|
|
with sftp.open('/etc/postfix/main.cf', 'w') as f: f.write(postfix_main_cf)
|
|
with sftp.open('/etc/dovecot/dovecot.conf', 'w') as f: f.write(dovecot_conf)
|
|
with sftp.open('/etc/mailname', 'w') as f: f.write(DOMAIN + '\n')
|
|
print('설정 파일 생성 완료')
|
|
|
|
# 3. 메일 계정 생성 (시스템 사용자)
|
|
for acc in ACCOUNTS:
|
|
run(f'계정 생성 ({acc}@{DOMAIN})',
|
|
f'id {acc} 2>/dev/null || useradd -m -s /bin/false {acc} && '
|
|
f'echo \"{acc}:{MAIL_PASS}\" | chpasswd && '
|
|
f'mkdir -p /home/{acc}/Maildir/{{cur,new,tmp}} && '
|
|
f'chown -R {acc}:{acc} /home/{acc}/Maildir && '
|
|
f'echo \"{acc}@{DOMAIN} created\"',
|
|
15)
|
|
|
|
# 4. UFW 포트 오픈
|
|
run('UFW SMTP/IMAP 포트',
|
|
'ufw allow 25/tcp && ufw allow 587/tcp && '
|
|
'ufw allow 993/tcp && ufw allow 995/tcp && '
|
|
'ufw allow 143/tcp && ufw allow 110/tcp && echo ok')
|
|
|
|
# 5. Postfix master.cf에 submission 포트 추가
|
|
run('Postfix submission 포트 활성화',
|
|
'grep -q "^submission" /etc/postfix/master.cf || '
|
|
'echo "submission inet n - y - - smtpd" >> /etc/postfix/master.cf')
|
|
|
|
# 6. 서비스 시작
|
|
run('Postfix 시작', 'systemctl enable postfix && systemctl restart postfix && systemctl is-active postfix')
|
|
run('Dovecot 시작', 'systemctl enable dovecot && systemctl restart dovecot && systemctl is-active dovecot')
|
|
|
|
# 7. 로컬 메일 테스트
|
|
run('로컬 메일 발송 테스트',
|
|
f'echo "GUARDiA SMTP 테스트 메일" | mail -s "Test" info@{DOMAIN} 2>/dev/null && echo "메일 발송 OK" || echo "mail command 확인 필요"',
|
|
10)
|
|
|
|
sftp.close(); client.close()
|
|
print(f'\nSMTP 서버 구축 완료!')
|
|
print(f'도메인: @{DOMAIN}')
|
|
print(f'계정: {", ".join(ACCOUNTS)}')
|
|
print(f'SMTP: mail.{DOMAIN}:25 (로컬) / 587 (STARTTLS)')
|
|
print(f'IMAP: mail.{DOMAIN}:993 (SSL)')
|