메뉴 닫기

DB SSL

DB SSL

클라이언트와 데이터베이스 서버 간의 통신을 TLS로 암호화하여, 네트워크 구간에서 데이터가 노출되는 것을 방지하는 기술입니다.

SSL이 적용되지 않은 경우 쿼리나 결과 데이터가 평문으로 전송되어 패킷 캡처 시 그대로 확인될 수 있습니다.

반면 SSL을 적용하면 동일한 트래픽도 암호화되어 외부에서는 내용을 해석할 수 없습니다.

데이터 유출 방지와 보안 강화를 위해 DB 통신에 SSL 적용을 권장합니다.

 

 

 

[테스트 환경]

Server A : Ubuntu 24.04 / Mariadb Server 10.11 / Let’s encrypt SSL (Apache 2.4)

Client B : Ubuntu 22.04 / Mariadb Client 10.6 / Tshark 3.6.2

 

[SSL 적용 전]
Client B에서 Server A로 접근 후 쿼리문 입력

MariaDB [testdb]> SELECT 'password=MySecret123!';
+-----------------------+
| password=MySecret123! |
+-----------------------+
| password=MySecret123! |
+-----------------------+
1 row in set (0.003 sec)
Client B에서 tshark -i ens3 -f "tcp port 3306" -V 명령어로 캡쳐

[SSL 미적용시 평문 노출]
MySQL Protocol
    Request Command Query
        Command: Query (3)
        Statement: SELECT 'password=MySecret123!'
-> 쿼리 내용이 그대로 보이며 사람이 읽을 수 있음

MySQL Protocol
    text
        text: password=MySecret123!
-> DB 결과값까지 평문 노출됨

[Protocols in frame: eth:ethertype:ip:tcp:mysql]
-> MySQL 프로토콜 해석 가능하며 내부 구조까지 분석 가능

 

[DB SSL 적용 흐름]

1. Server B: 인증서 발급

2. Server B: MySQL SSL 설정

3. Client A: CA 신뢰 설정 (또는 OS trust 사용)

4. MySQL: SSL 강제 + 계정 생성

5. 네트워크: IP 직접 접근 차단

6. 클라이언트: VERIFY_IDENTITY접속 (mysql만 지원, mariadb 지원안됨)

 

[Server B]

1. Let’s Encrypt 인증서 발급
   ex. /etc/letsencrypt/live/test.com/

2. DB 데몬에서 사용을 위해 인증서파일 권한 및 그룹권한 변경 필요

3. /etc/letsencrypt/archive/test.com 원본 경로 하단의 파일들을 복사
   ex. # cp -arp /etc/letsencrypt/archive/test.com/fullchain1.pem /etc/mysql/ssl/
       # cp -arp /etc/letsencrypt/archive/test.com/privkey1.pem /etc/mysql/ssl/

4. 인증서 파일 권한 변경
   # chown mysql:mysql /etc/mysql/ssl/fullchain1.pem
   # chown mysql:mysql /etc/mysql/ssl/privkey1.pem
   # chmod 600 /etc/mysql/ssl/fullchain1.pem
   # chmod 600 /etc/mysql/ssl/privkey1.pem

5. DB 설정파일 수정
   # vi /etc/mysql/mariadb.conf.d/50-server.cnf 
        [mysqld]
        ssl-ca=/etc/letsencrypt/live/test.com/fullchain.pem
        ssl-cert=/etc/letsencrypt/live/test.com/fullchain.pem
        ssl-key=/etc/letsencrypt/live/test.com/privkey.pem
        require_secure_transport=ON
   # systemctl restart mysqld

5. Mysql 계정 생성 및 SSL 강제
   MariaDB [(none)]> CREATE USER 'appuser'@'%' IDENTIFIED BY 'Pass!1234';
   MariaDB [(none)]> ALTER USER 'appuser'@'%' REQUIRE SSL;
   MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'appuser'@'%';
   MariaDB [(none)]> FLUSH PRIVILEGES;

6. 네트워크: IP 직접 접근 차단 (필요시)
   생략해도 IP로도 접속 시도 가능 (TLS 실패하더라도 접근 시도 자체는 됨)
   # iptables -A INPUT -p tcp --dport 3306 -s <WAS_IP> -j ACCEPT
   # iptables -A INPUT -p tcp --dport 3306 -j DROP

[Client B]
7. DB 원격 접속 (OS 자체 ca 파일 사용, /etc/ssl/certs/ca-certificates.crt)
   # mysql -h test.com -u appuser -p --ssl --ssl-ca=/etc/ssl/certs/ca-certificates.crt

   # mysql -h test.com -u appuser -p --ssl-mode=VERIFY_IDENTITY
     -> MySQL 5.7.11 이상 또는 MySQL 8.X 클라이언트에서만 --ssl-mode=VERIFY_IDENTITY 옵션 지원
[SSL 적용 후]
Client B에서 Server A로 접근 후 쿼리문 입력

MariaDB [testdb]> SELECT 'password=MySecret123!';
+-----------------------+
| password=MySecret123! |
+-----------------------+
| password=MySecret123! |
+-----------------------+
1 row in set (0.003 sec)
Client B에서 tshark -i ens3 -f "tcp port 3306" -V 명령어로 캡쳐

[SSL 적용시 암호화]
Transmission Control Protocol
    TCP payload (57 bytes)
    TCP segment data (57 bytes)
-> 쿼리 내용 보이지 않고, 단순 데이터 길이만 보임

TCP payload (120 bytes)
TCP segment data (120 bytes)
-> 실제 데이터 내용 확인 불가, 암호화된 바이너리 형태

[Protocols in frame: eth:ethertype:ip:tcp]
-> MySQL 프로토콜 자체가 숨겨지며 TLS 내부데이터로 숨겨짐

 

[SSL 적용 테스트 방법]

# mysql h 서버IP u 계정 p ssl=0
접속 실패하면 → REQUIRE SSL 적용됨
접속 되면 → SSL “옵션”일 (강제 아님)

 

MariaDB [(none)]> SELECT user, host, ssl_type FROM mysql.user;

[ssl_type]

ANYREQUIRE SSL

X509 → mutual TLS

● 공백 → SSL 안 써도 접속 가능

 

MariaDB [(none)]> SHOW VARIABLES LIKE ‘%ssl%’;

 

MariaDB [(none)]> SHOW STATUS LIKE ‘Ssl_cipher’;

> 현재 세션 암호화 여부 조회

    공백일경우 SSL 미사용, 평문 통신

 

이 글은 본인의 실제 경험과 학습을 기반으로 직접 작성하였으며, AI는 참고용으로만 활용하였습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다