Apache James 메일서버 – 운영

0. 서비스 시작

cd /usr/local/james
./bin/james start

1. 서비스 상태확인

./bin/james status
root@mail:/usr/local/james# ./bin/james status
Apache James :: Server :: Spring :: App is running (22938).

2. 중지하기, 재시작

./bin/james stop
./bin/james restart

3. 로그파일

tail -f log/wrapper.log

자세한 로그를 얻기위해서는 conf/log4j2.xml 파일을 수정하고 재시작하면 된다. status 속성을 변경한다.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">

4. 도메인 추가

conf/domainlist.xml 파일에서 도메인을 추가하지 않고 james-cli 명령을 이용해서 추가가 가능하다.

./bin/james-cli AddDomains domain.com

5. 사용자 추가

도메인을 추가하면 해당 도메인내에서 사용이 가능한 사용자를 추가할 수 있다. 사용자명은 도메인을 포함한 이메일주소여야 한다.
james-cli Adduser <username> <password>

./bin/james-cli AddUser me@jongwan.com 1234

비밀번호 변경하기

./bin/james-cli SetPassword me@jongwan.com abcd1234

사용자 삭제하기

./bin/james-cli RemoveUser me@jongwan.com

6. 사용가능한 CLI 명령어

root@mail:/usr/local/james# ./bin/james-cli.sh
You must specify a command.
usage: java org.apache.james.cli.ServerCmd --host <arg> <command>
 -h,--host <arg>   node hostname or ip address
 -p,--port <arg>   remote jmx agent port number
AddUser <username> <password>
RemoveUser <username>
ListUsers
AddDomain <domainName>
RemoveDomain <domainName>
ContainsDomain <domainName>
ListDomains
ListMappings
ListUserDomainMappings <user> <domain>
AddAddressMapping <fromUser> <fromDomain> <toAddress>
RemoveAddressMapping <fromUser> <fromDomain> <toAddress>
AddRegexMapping <user> <domain> <regex>
RemoveRegexMapping <user> <domain> <regex>
SetPassword <username> <password>
CopyMailbox <srcBean> <dstBean>
DeleteUserMailboxes <user>
CreateMailbox <namespace> <user> <name>
ListUserMailboxes <user>
DeleteMailbox <namespace> <user> <name>
ImportEml <namespace> <user> <name> <path>
GetStorageQuota <quotaroot>
GetMessageCountQuota <quotaroot>
GetQuotaroot <namespace> <user> <name>
GetMaxStorageQuota <quotaroot>
GetMaxMessageCountQuota <quotaroot>
SetMaxStorageQuota <quotaroot> <maxMessageCount>
SetMaxMessageCountQuota <quotaroot> <maxStorage>
SetGlobalMaxStorageQuota <maxStorage>
SetGlobalMaxMessageCountQuota <maxMessageCount>
GetGlobalMaxStorageQuota
GetGlobalMaxMessageCountQuota
ReindexMailbox <namespace> <user> <name>
ReindexAll
GetSieveQuota
SetSieveQuota <quota>
RemoveSieveQuota
GetSieveUserQuota <username>
SetSieveUserQuota <username> <quota>
RemoveSieveUserQuota <username>
AddActiveSieveScript <username> <scriptname> <path>

Apache James 메일서버 – 환경설정

0. conf/domainlist.xml

메일서버에서 사용하는 도메인을 지정해준다.
아래 설정에서는 두개의 도메인을 사용하는 것을 기준으로 했다.

  • jongwan.com
  • another-domain.com
<?xml version="1.0"?>
<domainlist class="org.apache.james.domainlist.jpa.JPADomainList">
  <autodetect>false</autodetect>
  <autodetectIP>false</autodetectIP>
  <defaultDomain>jongwan.com</defaultDomain>
    <domainnames>
      <domainname>jongwan.com</domainname>      
      <domainname>another-domain.com</domainname>
    </domainnames>
</domainlist>
  • defaultDomain : 기본 도메인을 지정한다. domainname 항목중에 하나를 지정한다.
  • domainnames.domainname : 사용할 도메인을 추가한다. domainname 항목을 추가해서 여러개의 도메인을 사용할 수 있다.

1. conf/dnsservice.xml

DNS 서버를 지정한다. 자동으로 했을 때 문제가 있어 강제로 지정했다.

<?xml version="1.0"?>
<dnsservice>
  <servers>
    <server>1.1.1.1</server>
  </servers>
  <autodiscover>false</autodiscover>
  <authoritative>false</authoritative>
  <maxcachesize>50000</maxcachesize>
</dnsservice>
  • autodiscover : 기본값은 true인데, 동작을 잘 안해서 변경했다.
  • servers.server : 1.1.1.1로 강제 지정했다.

2. keystore

TLS사용을 위해서 키를 생성한다.
smtpserver.xml, imapserver.xml에서 사용한다.

/usr/local/james 위치에 설치기준

keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /usr/local/james/conf/keystore
Enter keystore password: 
Re-enter new password:
What is your first and last name?
  [Unknown]:  Jongwan Kim
What is the name of your organizational unit?
  [Unknown]:  None
What is the name of your organization?
  [Unknown]:  None
What is the name of your City or Locality?
  [Unknown]:  Seoul
What is the name of your State or Province?
  [Unknown]:  Guro-gu
What is the two-letter country code for this unit?
  [Unknown]:  KR
Is CN=Jongwan Kim, OU=None, O=None, L=Seoul, ST=Guro-gu, C=KR correct?
  [no]:  y

3. conf/smtpserver.xml

메일 발송을 위한 SMTP 설정을 한다.
25번 포트와 465번 포트설정이 각각 smtpserver 항목으로 있다.

<?xml version="1.0"?>
<smtpservers>
  <smtpserver enabled="true">
    <jmxName>smtpserver</jmxName>
    <bind>0.0.0.0:25</bind>
    <connectionBacklog>200</connectionBacklog>
    <tls socketTLS="false" startTLS="false">
      <keystore>file://conf/keystore</keystore>
      <keystoreType>PKCS12</keystoreType>
      <secret>123456</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
      <algorithm>SunX509</algorithm>
    </tls>
    <connectiontimeout>360</connectiontimeout>
    <connectionLimit>0</connectionLimit>
    <connectionLimitPerIP>0</connectionLimitPerIP>
    <auth>
      <plainAuthEnabled>true</plainAuthEnabled>
    </auth>
    <authorizedAddresses>127.0.0.0/24, 192.168.0.0/24, 100.100.100.0/24</authorizedAddresses>
    <maxmessagesize>0</maxmessagesize>
    <addressBracketsEnforcement>true</addressBracketsEnforcement>
    <handlerchain>
      <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
      <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>       
    </handlerchain>           
  </smtpserver>
  <smtpserver enabled="true">
    <jmxName>smtpservertls</jmxName>
    <bind>0.0.0.0:465</bind>
    <connectionBacklog>200</connectionBacklog>
    <tls socketTLS="false" startTLS="true">
      <keystore>file://conf/keystore</keystore>
      <keystoreType>PKCS12</keystoreType>
      <secret>123456</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
      <algorithm>SunX509</algorithm>
    </tls>
    <connectiontimeout>360</connectiontimeout>
    <connectionLimit>0</connectionLimit>
    <connectionLimitPerIP>0</connectionLimitPerIP>
    <auth>
      <plainAuthEnabled>true</plainAuthEnabled>
    </auth>
    <authorizedAddresses>127.0.0.0/24, 192.168.0.0/24, 100.100.100.0/24</authorizedAddresses>
    <maxmessagesize>0</maxmessagesize>
    <addressBracketsEnforcement>true</addressBracketsEnforcement>
    <handlerchain>
      <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
      <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>       
    </handlerchain>           
  </smtpserver>
</smtpservers>
  • jmxName : smtpserver, smtpservertls 두가지 항목이 각각 smtpserver 항목에 있다. smtpserver 항목마다 jmxName이 달라야 오류가 발생하지 않는다.
  • bind : 각각 0.0.0.0:25, 0.0.0.0:465 을 설정한다.
  • tls : 465포트를 사용하는 0.0.0.0:465에 대해서 startTLS=”true” 를 변경
  • tls.keystore : /usr/local/james/ 폴더를 기준으로 이전에 생성한 keystore를 지정해준다.
  • tls.secret : keystore 생성시 사용한 비밀번호
  • authorizedAddresses : 인증없이 접속가능한 아이피 대역을 쉼표 기준으로 입력한다.

4. imapserver.xml

IMAP 사용을 위해서 143, 993 포트 설정을 한다.
imapserver 항목으로 추가가 가능하다.

<?xml version="1.0"?>
<imapservers>
  <imapserver enabled="true">
    <jmxName>imapserver</jmxName>
    <bind>0.0.0.0:143</bind>
    <connectionBacklog>200</connectionBacklog>
    <tls socketTLS="false" startTLS="false">
      <keystore>file://conf/keystore</keystore>
      <keystoreType>PKCS12</keystoreType>
      <secret>123456</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
    </tls>
    <connectionLimit>0</connectionLimit>
    <connectionLimitPerIP>0</connectionLimitPerIP>
    <plainAuthDisallowed>false</plainAuthDisallowed>
    <auth>
      <plainAuthEnabled>true</plainAuthEnabled>
    </auth>
  </imapserver>
  <imapserver enabled="true">
    <jmxName>imapservertls</jmxName>
    <bind>0.0.0.0:993</bind>
    <connectionBacklog>200</connectionBacklog>
    <tls socketTLS="false" startTLS="true">
      <keystore>file://conf/keystore</keystore>
      <keystoreType>PKCS12</keystoreType>
      <secret>123456</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
    </tls>
    <connectionLimit>0</connectionLimit>
    <connectionLimitPerIP>0</connectionLimitPerIP>
    <plainAuthDisallowed>false</plainAuthDisallowed>
    <auth>
      <plainAuthEnabled>true</plainAuthEnabled>
    </auth>
  </imapserver>
</imapservers>
  • imapserver.jmxName : 143, 993 두가지 항목에 대해서 이름을 다르게 지정한다.
  • tls : 993 포트 지정시 startTLS=”true” 로 변경
  • tls.keystore : 위에서 생성한 keystore를 지정해준다.
  • plainAuthDisallowed : 기본값은 true 이고, 외부에서 접속시 암호화 없는 비밀번호를 사용하려고 false로 변경했다.

5. pop3server.xml

POP3는 사용하지 않는다.

<?xml version="1.0"?>
<pop3servers>
  <pop3server enabled="false"
</pop3servers>
  • pop3server : 사용하지 않으려고 enabled=”false”로 변경

6. mailetcontainer.xml

메일 송/수신관련된 복잡한 설정이 있다.

<?xml version="1.0"?>
<mailetcontainer enableJmx="true">
  <context>
    <postmaster>me@jongwan.com</postmaster>
  </context>
  <spooler>
    <threads>20</threads>
    <errorRepository>file://var/mail/error/</errorRepository>
  </spooler>
  <processors>
    <processor state="root" enableJmx="true">
      <mailet match="All" class="PostmasterAlias"/>
      <mailet match="RelayLimit=30" class="Null"/>
      <mailet match="HasMailAttribute=spamChecked" class="ToProcessor">
        <processor>transport</processor>
      </mailet>
      <mailet match="All" class="SetMailAttribute">
        <spamChecked>true</spamChecked>
      </mailet>
      <mailet match="SMTPAuthSuccessful" class="ToProcessor">
        <processor>transport</processor>
      </mailet>
      <mailet match="All" class="ToProcessor">
        <processor>transport</processor>
      </mailet>
    </processor>
    <processor state="error" enableJmx="true">
      <mailet match="All" class="ToRepository">
        <repositoryPath>file://var/mail/error/</repositoryPath>
      </mailet>
    </processor>
    <processor state="transport" enableJmx="true">
      <mailet match="SenderIsRegex=(.*)@jongwan\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
        <signatureTemplate>v=1; s=mail; d=jongwan.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
        <privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
        </privateKey>
      </mailet>
      <mailet match="SenderIsRegex=(.*)@another-domain\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
        <signatureTemplate>v=1; s=mail; d=another-domain.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
          <privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
        </privateKey>
      </mailet>
      <mailet match="SMTPAuthSuccessful" class="SetMimeHeader">
        <name>X-UserIsAuth</name>
        <value>true</value>
        <onMailetException>ignore</onMailetException>
      </mailet>
      <mailet match="HasMailAttribute=org.apache.james.SMIMECheckSignature" class="SetMimeHeader">
        <name>X-WasSigned</name>
        <value>true</value>
        <onMailetException>ignore</onMailetException>
      </mailet>
      <mailet match="All" class="RecipientRewriteTable" />
      <mailet match="RecipientIsLocal" class="Sieve"/>
      <mailet match="RecipientIsLocal" class="AddDeliveredToHeader"/>
      <mailet match="RecipientIsLocal" class="LocalDelivery"/>
      <mailet match="HostIsLocal" class="ToProcessor">
        <processor>local-address-error</processor>
        <notice>550 - Requested action not taken: no such user here</notice>
      </mailet>
      <mailet match="All" class="RemoteDelivery">
        <outgoing>outgoing</outgoing>
        <startTLS>true</startTLS>
        <mail.smtp.ssl.trust>*</mail.smtp.ssl.trust>
        <delayTime>5000, 100000, 500000</delayTime>
        <maxRetries>3</maxRetries>
        <maxDnsProblemRetries>0</maxDnsProblemRetries>
        <deliveryThreads>10</deliveryThreads>
        <sendpartial>true</sendpartial>
        <bounceProcessor>bounces</bounceProcessor>
      </mailet>
    </processor>
    <processor state="over-quota" enableJmx="true">
      <mailet match="All" class="MetricsMailet">
        <metricName>mailet-over-quota-error</metricName>
      </mailet>
      <mailet match="All" class="Bounce">
        <message>The following recipients do not have enough space for storing the email you sent them.</message>
        <attachment>none</attachment>
      </mailet>
      <mailet match="All" class="ToRepository">
        <repositoryPath>file://var/mail/over-quota-error/</repositoryPath>
      </mailet>
    </processor>
    <processor state="spam" enableJmx="true">
      <mailet match="All" class="ToRepository">
        <repositoryPath>file://var/mail/spam/</repositoryPath>
      </mailet>
    </processor>
    <processor state="virus" enableJmx="true">
      <mailet match="All" class="SetMailAttribute">
        <org.apache.james.infected>true, bouncing</org.apache.james.infected>
      </mailet>
      <mailet match="SMTPAuthSuccessful" class="Bounce">
        <inline>heads</inline>
        <attachment>none</attachment>
        <notice>Warning: We were unable to deliver the message below because it was found infected by virus(es).</notice>
      </mailet>
      <mailet match="All" class="Null" />
    </processor>
    <processor state="local-address-error" enableJmx="true">
      <mailet match="All" class="ToRepository">
        <repositoryPath>file://var/mail/address-error/</repositoryPath>
      </mailet>
    </processor>
    <processor state="relay-denied" enableJmx="true">
      <mailet match="All" class="ToRepository">
        <repositoryPath>file://var/mail/relay-denied/</repositoryPath>
      </mailet>
    </processor>
    <processor state="bounces" enableJmx="true">
      <mailet match="All" class="DSNBounce">
        <passThrough>false</passThrough>
      </mailet>
    </processor>
  </processors>
</mailetcontainer>

기본설정에서 변경된 부분만 설명한다.

<mailet match="SenderIsRegex=(.*)@jongwan\.com" class="org.apache.james.jdkim.mailets.DKIMSign">
  <signatureTemplate>v=1; s=mail; d=jongwan.com ; h=from : reply-to : subject : date : to : cc : resent-date : resent-from : resent-sender : resent-to : resent-cc : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; a=rsa-sha256; bh=; b=;</signatureTemplate>
  <privateKey>
-----BEGIN RSA PRIVATE KEY-----
# 여기에 Private Key 입력
-----END RSA PRIVATE KEY-----
  </privateKey>
</mailet>

DKIM 설정을 위해서 <processor state=”transport”> 항목의 가장위에 추가한다.
도메인별로 키가 다르므로 match=”SenderIsRegex=…” 를 사용해서 발송시 도메인별로 헤더를 다르게 추가해준다.

<mailet match="All" class="RemoteDelivery">
  ...
  <startTLS>true</startTLS>
  <mail.smtp.ssl.trust>*</mail.smtp.ssl.trust>
  ...
</mailet>
구글메일에서 위와같이 나올경우

위처럼 암호화관련 경고나 나오면 <startTLS>true</startTLS>를 추가한다.

직접 생성한 인증서를 사용해서 경고가 나올 경우 <mail.smpt.ssl.trust>*</mail.smpt.ssl.trust> 항목을 추가한다.

외부로 메일발송 허용

<mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
  <processor>relay-denied</processor>
  <notice>550 - Requested action not taken: relaying denied</notice>
</mailet>

이 규칙이 있으면 외부로 메일이 발송되지 않는다.
내부메일서버로만 사용한다면 놔두고, 외부로 메일발송이 필요하다면 주석처리해야한다.

Apache James 메일서버 – 설치하기

https://james.apache.org/

Java로 만들어진 메일서버로 아파치의 지원을 받는다.
기존에 시스템은 Postfix로 구축했었는데,
다른 오픈소스를 찾다보니 James를 테스트 해보기로 했다.

0. 설치환경

최신버전인 James 3.7.0은 OIpenJDK 11버전이 필요하다.
서버는 Ubuntu 20.04.4 LTS 를 VM으로 생성 (CPU*4, 2Gb Memory)

설치요구사항 확인
https://james.apache.org/server/install.html

1. OpenJDK 설치

apt update
apt install openjdk-11-jdk

2. 설치파일 다운로드

https://james.apache.org/download.cgi#Apache_James_Server

Spring wiring 바이너리를 다운로드한다https://dlcdn.apache.org/james/server/3.7.0/james-server-app-3.7.0-app.zip

cd /usr/local/
wget https://dlcdn.apache.org/james/server/3.7.0/james-server-app-3.7.0-app.zip

3. 압축해제

# unzip 설치
apt install unzip

# 압축해제
unzip james-server-app-3.7.0-ap.zip

# 폴더이름변경
mv james-server-spring-app-3.7.0 james
압축해제후 폴더내용

GitLab – HTTPS 적용하기

메뉴얼을 보면 기본적으로 Let’s Encrypt 를 사용해서 HTTPS을 지원해주지만 직접 받급받은 인증서가 있으면 따로 지정해줄 수 있습니다.

그리고 Sectigo에서 인증서를 발급 받은 경우 CRT파일을 바로 사용하면 SourceTree에서 원격저장소에 로그인 할 때 SSL관련 오류가 뜨니 변경해서 적용해야 합니다.

인증서 합치기

mkdir /etc/gitlab/ssl
cat _wildcard_jongwan_com.crt SectigoRSAAddTrustCA.crt SectigoRSADomainValidationSecureServerCA.crt AAACertificateServices.crt > /etc/gitlab/ssl/jongwan_com_ssl.crt

인증서 적용하기

vim /etc/gitlab/gitlab.rb
################################################################################
## GitLab NGINX
##! Docs: https://docs.gitlab.com/omnibus/settings/nginx.html
################################################################################

nginx['redirect_http_to_https'] = true
nginx['ssl_verify_client'] = "off"
nginx['ssl_certificate'] = "/etc/gitlab/ssl/jongwan_com_ssl.crt"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/_wildcard_jongwan_com_SHA256WITHRSA.key"
nginx['ssl_ciphers'] = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
nginx['ssl_prefer_server_ciphers'] = "on"

nginx['ssl_protocols'] = "TLSv1.2 TLSv1.3"

GitLab-CE 설치 / 우분투20.04

우분투 20.04에서 GitLab-CE 를 설치하는 방법

sudo apt update
sudo apt install -y curl openssh-server ca-certificates 

Postfix 설치

sudo apt install postfix

GitLab 패키지 레퍼지토리를 추가

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

설치진행

sudo EXTERNAL_URL="http://git.jongwan.com/" apt install gitlab-ce

8코어로도 시간이 꽤나 소요된다.

설치완료화면
로그인 화면

초기 비밀번호

cat /etc/gitlab/initial_root_password
초기비밀번호가 들어있는 파일은 24시간후 삭제됩니다

마지막줄쯤에 Password : 이 다음부분이 비밀번호입니다.

설정파일

vim /etc/gitlab/gitlab.rb

변경내용 적용하기

sudo gitlab-ctl reconfigure

재시작하기

sudo gitlab-ctl restart

Ubuntu 20.04LTS + mariadb 10.5 (replication)

문자메시지 발송서비스 서버 구축을 위해서 mariadb (replication) 를 사용
1,000,000건/일 + @ 처리가 가능해야 한다

서버스펙

Xeon (16core)
samsung 860 pro 1Tb * 2 (RAID0)
32Gb memory

구성

L4 : Active – Standby
mariadb : Master – Slave

서버설치

http://mirror.kakao.com/ubuntu-releases/focal/

mariadb 설치

sudo apt-get install software-properties-common dirmngr apt-transport-https
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] https://mirror.yongbok.net/mariadb/repo/10.5/ubuntu focal main'

sudo apt update
sudo apt install mariadb-server

mysql 사용자 설정

mysql -uroot -p
# create user username@localhost identified by 'password';
create user my@'%' identified by '1234';
# grant select on database.table to username@localhost;
grant select on *.* to my@'%';
# grant all privileges on database.table to username@localhost;
grant all privileges on *.* to my@'%';
flush privileges;

replication

master

[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log

vim /etc/mysql/mariadb.conf.d/50-server.cnf

systemctl restart mariadb

Welcome to the MariaDB monitor.  Commands end with ; or \g.
 Your MariaDB connection id is 37
 Server version: 10.5.9-MariaDB-1:10.5.9+maria~focal-log mariadb.org binary distribution
 Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 MariaDB [(none)]> show master status;
 +------------------+----------+--------------+------------------+
 | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
 +------------------+----------+--------------+------------------+
 | mysql-bin.000001 |     2098 |              |                  |
 +------------------+----------+--------------+------------------+
 1 row in set (0.000 sec)
 MariaDB [(none)]>
show master status;

slave

[mysqld]
server-id = 2
relay_log=mysql-relay-bin
log_slave_updates = 1
read_only = 1

vim /etc/mysql/mariadb.conf.d/50-server.cnf

systemctl restart mariadb

Welcome to the MariaDB monitor.  Commands end with ; or \g.
 Your MariaDB connection id is 36
 Server version: 10.5.9-MariaDB-1:10.5.9+maria~focal mariadb.org binary distribution
 Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 MariaDB [(none)]> stop slave;
 MariaDB [(none)]> CHANGE MASTER TO
     -> MASTER_HOST='###.###.###.###',
     -> MASTER_PORT=3306,
     -> MASTER_USER='repl',
     -> MASTER_PASSWORD='1234',
     -> MASTER_LOG_FILE='mysql-bin.000001',
     -> MASTER_LOG_POS=2098;
 MariaDB [(none)]> start slave;
 MariaDB [(none)]> show slave status \G;
 * 1. row *
                 Slave_IO_State: Waiting for master to send event
                    Master_Host: ###.###.###.###
                    Master_User: repl
                    Master_Port: 3306
                  Connect_Retry: 60
                Master_Log_File: mysql-bin.000001
            Read_Master_Log_Pos: 2098
                 Relay_Log_File: mysql-relay-bin.000002
                  Relay_Log_Pos: 906
          Relay_Master_Log_File: mysql-bin.000001
               Slave_IO_Running: Yes
              Slave_SQL_Running: Yes
                Replicate_Do_DB:
            Replicate_Ignore_DB:
             Replicate_Do_Table:
         Replicate_Ignore_Table:
        Replicate_Wild_Do_Table:
    Replicate_Wild_Ignore_Table:
                     Last_Errno: 0
                     Last_Error:
                   Skip_Counter: 0
            Exec_Master_Log_Pos: 2098
                Relay_Log_Space: 1215
                Until_Condition: None
                 Until_Log_File:
                  Until_Log_Pos: 0
             Master_SSL_Allowed: No
             Master_SSL_CA_File:
             Master_SSL_CA_Path:
                Master_SSL_Cert:
              Master_SSL_Cipher:
                 Master_SSL_Key:
          Seconds_Behind_Master: 0
  Master_SSL_Verify_Server_Cert: No
                  Last_IO_Errno: 0
                  Last_IO_Error:
                 Last_SQL_Errno: 0
                 Last_SQL_Error:
    Replicate_Ignore_Server_Ids:
               Master_Server_Id: 1
                 Master_SSL_Crl:
             Master_SSL_Crlpath:
                     Using_Gtid: No
                    Gtid_IO_Pos:
        Replicate_Do_Domain_Ids:
    Replicate_Ignore_Domain_Ids:
                  Parallel_Mode: optimistic
                      SQL_Delay: 0
            SQL_Remaining_Delay: NULL
        Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
               Slave_DDL_Groups: 3
 Slave_Non_Transactional_Groups: 0
     Slave_Transactional_Groups: 0
 1 row in set (0.000 sec)
 ERROR: No query specified
 MariaDB [(none)]>
show slave status \G;

Dante – Socks5 Proxy

패키지 설치

# apt update && apt upgrade -y
# apt install dante-server dante-client

환경설정

logoutput: syslog stdout /var/log/dante.log
internal: eth0 port = 1080
external: eth1
clientmethod: none
socksmethod: none
user.privileged: proxy
user.unprivileged: nobody
user.libwrap: nobody
client pass {
        from: 0.0.0.0/0 to: 0.0.0.0/0
        log: error connect disconnect
}
socks pass {
        from: 0.0.0.0/0 to: 0.0.0.0/0
        log: connect error disconnect
}

/etc/danted.conf

프록시 서버는 eth0에서 LISTEN, 트래픽은 eth1으로 나가게 한다.
eth0와 eth1은 각각 공인아이피를 셋팅했다.

테스트

# curl -x socks5://{프록시아이피}:{프록시포트} https://www.google.com

socksify

route {
        from: 0.0.0.0/0 to: 0.0.0.0/0 via: {프록시아이피} port = {프록시포트}
        protocol: tcp udp
        proxyprotocol: socks_v4 socks_v5
        method: none
}

/etc/dante.conf

dante-client 패키지를 설치하면 socksify를 사용할 수 있다.
위에처럼 설정하고 아래 명령을 사용하는 방법도 있다.

이 경우에는 socksify를 사용하는 프로세스는 모두 지정한 프록시를 통해서 통신이 된다.

# socksify wget -O- -q https://google.com

CentOS 7 – 오라클 18c XE 설치

패키지 업데이트

# yum update
# yum install wget

패키지 업데이트를 먼저한다

다운로드

# cd /usr/local/src
# wget https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm
# wget https://download.oracle.com/otn-pub/otn_software/db-express/oracle-database-xe-18c-1.0-1.x86_64.rpm

설치파일 다운로드는 아래 링크에서 한다.
https://www.oracle.com/database/technologies/xe-downloads.html

설치 진행

# yum -y localinstall oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm
# yum -y localinstall oracle-database-xe-18c-1.0-1.x86_64.rpm

설치 사이즈가 커서 오래걸린다

초기설정

# /etc/init.d/oracle-xe-18c configure

Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
 Confirm the password:
 Configuring Oracle Listener.
 Listener configuration succeeded.
 Configuring Oracle Database XE.
 Enter SYS user password:                                                                                                           
 Enter SYSTEM user password:
 
 Enter PDBADMIN User Password:
 
 Prepare for db operation
 7% complete
 Copying database files
 29% complete
 Creating and starting Oracle instance
 30% complete
 31% complete
 34% complete
 38% complete
 41% complete
 43% complete
 Completing Database Creation
 47% complete
 50% complete
 Creating Pluggable Databases
 54% complete
 71% complete
 Executing Post Configuration Actions
 93% complete
 Running Custom Scripts
 100% complete
 Database creation complete. For details check the logfiles at:
  /opt/oracle/cfgtoollogs/dbca/XE.
 Database Information:
 Global Database Name:XE
 System Identifier(SID):XE
 Look at the log file "/opt/oracle/cfgtoollogs/dbca/XE/XE1.log" for further details.
 Connect to Oracle Database using one of the connect strings:
      Pluggable database: localhost.localdomain/XEPDB1
      Multitenant container database: localhost.localdomain
 Use https://localhost:5500/em to access Oracle Enterprise Manager for Oracle Database XE

비밀번호는 최소 1개의 대문자와 소문자, 숫자를 조합해서 8자이상 입력해야 한다.

환경설정 추가

# vi ~/.bash_profile

export ORACLE_HOME=/opt/oracle/product/18c/dbhomeXE
export TNS_ADMIN=$ORACLE_HOME/network/admin
export ORACLE_SID=XE
export ORAENV_ASK=NO
export PATH=$PATH:$ORACLE_HOME/bin

.bash_profile 파일 하단에 환경설정을 추가

리스너 확인

# lsnrctl status

LSNRCTL for Linux: Version 18.0.0.0.0 - Production on 01-FEB-2021 11:02:03
 Copyright (c) 1991, 2018, Oracle.  All rights reserved.
 Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))
 STATUS of the LISTENER
 Alias                     LISTENER
 Version                   TNSLSNR for Linux: Version 18.0.0.0.0 - Production
 Start Date                01-FEB-2021 11:01:04
 Uptime                    0 days 0 hr. 0 min. 58 sec
 Trace Level               off
 Security                  ON: Local OS Authentication
 SNMP                      OFF
 Default Service           XE
 Listener Parameter File   /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
 Listener Log File         /opt/oracle/diag/tnslsnr/localhost/listener/alert/log.xml
 Listening Endpoints Summary…
   (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521)))
   (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
   (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=localhost)(PORT=5500))(Security=(my_wallet_directory=/opt/oracle/product/18c/dbhomeXE/admin/XE/xdb_wallet))(Presentation=HTTP)(Session=RAW))
 Services Summary…
 Service "XE" has 1 instance(s).
   Instance "XE", status READY, has 1 handler(s) for this service…
 Service "XEXDB" has 1 instance(s).
   Instance "XE", status READY, has 1 handler(s) for this service…
 Service "ba3db2e4206012dde055000000000001" has 1 instance(s).
   Instance "XE", status READY, has 1 handler(s) for this service…
 Service "xepdb1" has 1 instance(s).
   Instance "XE", status READY, has 1 handler(s) for this service…
 The command completed successfully

listener.ora

[root@localhost admin]# cat listener.ora
 listener.ora Network Configuration File: /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
 Generated by Oracle configuration tools.
 DEFAULT_SERVICE_LISTENER = XE
 LISTENER =
   (DESCRIPTION_LIST =
     (DESCRIPTION =
       (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
       (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
     )
   )

tnsnames.ora

[root@localhost admin]# cat tnsnames.ora
 tnsnames.ora Network Configuration File: /opt/oracle/product/18c/dbhomeXE/network/admin/tnsnames.ora
 Generated by Oracle configuration tools.
 XE =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
     (CONNECT_DATA =
       (SERVER = DEDICATED)
       (SERVICE_NAME = XE)
     )
   )
 LISTENER_XE =
   (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))

포트번호가 바뀐경우가 있었는데, 그럴경우에 1521로 변경해서 저장하고 재시작 해준다

데이터베이스 접속확인

# sqlplus
SQL*Plus: Release 18.0.0.0.0 - Production on Mon Feb 1 12:59:38 2021
Version 18.4.0.0.0
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
Enter user-name: system
Enter password:
Last Successful login time: Mon Feb 01 2021 11:23:03 +09:00
Connected to:
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0
SQL>

데이터베이스 Start/Stop

# /etc/init.d/oracle-xe-18c start
# /etc/init.d/oracle-xe-18c stop

Let’s Encrypt (Certbot)으로 SSL 인증서 발급

Let’s Encrypt

Let’s Encrypt 에서 발급하는 90일짜리 무료 인증서입니다. 3개월에 한번씩 인증을 해야하지만 자동업데이트를 이용하면 쉽게 사용할 수 있습니다.

Certbot 설치

$ snap install --classic certbot

우분투 18.04 기준 snap로 certbot를 설치합니다.

SSL 인증서 발급 받기

// 아파치
$ certbot --apache

// nginx
$ certbot --nginx

certbot 명령을 이용해서 SSL인증서를 발급받습니다. 옵션을 이용해서 웹서버를 지정합니다.

$ certbot --nginx --nginx-server-root /usr/local/nginx/conf/ --nginx-ctl /usr/local/nginx/sbin/nginx

nginx 설치위치를 직접지정할 경우

Plugins selected: Authenticator apache, Installer apache
 Enter email address (used for urgent renewal and security notices)
  (Enter 'c' to cancel):

이메일주소를 입력합니다. 인증서 만료전에 이메일로 알려줍니다.

Please read the Terms of Service at
 https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
 agree in order to register with the ACME server. Do you agree?
 
 (Y)es/(N)o: Y
 
 Would you be willing, once your first certificate is successfully issued, to
 share your email address with the Electronic Frontier Foundation, a founding
 partner of the Let's Encrypt project and the non-profit organization that
 develops Certbot? We'd like to send you email about our work encrypting the web,
 EFF news, campaigns, and ways to support digital freedom.
 
 (Y)es/(N)o: Y
 Account registered.

이용약관에 동의합니다.

Which names would you like to activate HTTPS for?
 
 1: jongwan.com
 2: www.jongwan.com
 
 Select the appropriate numbers separated by commas and/or spaces, or leave input
 blank to select all options shown (Enter 'c' to cancel):

인증서를 발급받을 도메인을 선택합니다. 공백으로 엔터를 누르면 모두 발급합니다. jongwan.com, www.jongwan.com을 모두 받으므로 그냥 엔터를 입력합니다.

Requesting a certificate for jongwan.com and www.jongwan.com
 Performing the following challenges:
 http-01 challenge for jongwan
 http-01 challenge for www.jongwan
 Waiting for verification…
 Cleaning up challenges
 Created an SSL vhost at /etc/apache2/sites-available/jongwan_com-le-ssl.conf
 Deploying Certificate to VirtualHost /etc/apache2/sites-available/jongwan_com-le-ssl.conf
 Enabling available site: /etc/apache2/sites-available/jongwan_com-le-ssl.conf
 Deploying Certificate to VirtualHost /etc/apache2/sites-available/jongwan_com-le-ssl.conf
 Redirecting vhost in /etc/apache2/sites-enabled/jongwan_com.conf to ssl vhost in /etc/apache2/sites-available/jongwan_com-le-ssl.conf
 
 Congratulations! You have successfully enabled https://jongwan.com and
 https://www.jongwan.com
 
 Subscribe to the EFF mailing list (email: me@jongwan.com).
 IMPORTANT NOTES:
 Congratulations! Your certificate and chain have been saved at:
 /etc/letsencrypt/live/jongwan.com/fullchain.pem
 Your key file has been saved at:
 /etc/letsencrypt/live/jongwan.com/privkey.pem
 Your certificate will expire on 2021-04-15. To obtain a new or
 tweaked version of this certificate in the future, simply run
 certbot again with the "certonly" option. To non-interactively
 renew all of your certificates, run "certbot renew"
 If you like Certbot, please consider supporting our work by:
 Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 Donating to EFF:                    https://eff.org/donate-le 

인증서를 발급중입니다.

인증서 자동갱신하기

$ certbot renew

renew 옵션을 이용해서 인증서를 자동갱신할 수 있습니다.
–dry-run 옵션을 추가하면 발급 테스트도 가능합니다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
 
 Processing /etc/letsencrypt/renewal/jongwan.com.conf
 
 Cert not yet due for renewal
 
 The following certificates are not due for renewal yet:
   /etc/letsencrypt/live/jongwan.com/fullchain.pem expires on 2021-04-15 (skipped)
 No renewals were attempted. 

실행해보면 아래처럼 나옵니다. 방금 인증서를 받았기 때문에 갱신이 되지는 않고 메시지만 출력됩니다.

$ crontab -e
// 매일 0시 업데이트 진행
0 0 * * * sudo certbot renew

crontab에 등록해서 자동으로 갱신하도록 합니다.