learn

MySQL 보안 설정 (Ubuntu)

MySQL 보안 설정 (Ubuntu)

Ubuntu에서 MySQL을 외부에 노출할 때 최소한의 보안 구성.


파일 구조

MySQL 설치 시 파일이 여러 디렉토리에 분산된다.

| 경로 | 내용 | |------|------| | /etc/mysql/ | 설정 파일 (my.cnf, conf.d/, mysql.conf.d/) | | /var/lib/mysql/ | 실제 데이터 (DB 파일들) | | /var/log/mysql/ | 로그 | | /usr/bin/, /usr/sbin/ | 실행 바이너리 | | /run/mysqld/ | 소켓 파일 (런타임) |

apt install mysql-server로 설치하면 systemd 서비스로 자동 등록된다.

systemctl status mysql

포트 설정

/etc/mysql/mysql.conf.d/mysqld.cnf:

[mysqld]
bind-address = 0.0.0.0       # 외부 허용 (IP 필터는 ufw로)
# bind-address = 127.0.0.1   # 로컬만 허용할 경우
port = 3306

bind-address vs mysqlx-bind-address

| 설정 | 프로토콜 | 포트 | 용도 | |------|---------|------|------| | bind-address | MySQL 기본 | 3306 | 일반 클라이언트, CRUD 전부 | | mysqlx-bind-address | X Protocol | 33060 | MySQL Shell, X DevAPI (거의 안 씀) |

일반 CRUD 목적이면 bind-address만 변경하고 mysqlx-bind-address127.0.0.1로 그대로 둔다.

변경 후 재시작:

sudo systemctl restart mysql

ufw 화이트리스트

nginx 프록시 불필요. MySQL은 TCP 기반이므로 ufw로 직접 제어.

# 특정 IP만 3306 허용
sudo ufw allow from 192.168.1.100 to any port 3306

# 확인
sudo ufw status

root 보안

root는 localhost에서만 접속 가능한지 확인:

SELECT user, host FROM mysql.user WHERE user = 'root';

host%이면 위험 — 삭제:

DELETE FROM mysql.user WHERE user = 'root' AND host = '%';
FLUSH PRIVILEGES;

제한된 사용자 생성

-- 특정 IP에서만 접속 허용
CREATE USER 'appuser'@'192.168.1.100' IDENTIFIED BY 'strong_password';

-- 특정 테이블만 권한 부여
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.target_table TO 'appuser'@'192.168.1.100';

FLUSH PRIVILEGES;

@ 뒤 host 값

| 값 | 의미 | |----|------| | 'localhost' | 로컬만 | | '192.168.1.100' | 특정 IP만 | | '192.168.1.%' | 해당 대역 전체 | | '%' | 어디서든 (위험) |

권한 확인 / 삭제

SHOW GRANTS FOR 'appuser'@'192.168.1.100';
DROP USER 'appuser'@'192.168.1.100';

GRANT USAGE의 의미

SHOW GRANTS 결과에 항상 나오는 이 줄:

GRANT USAGE ON *.* TO 'appuser'@'192.168.1.100'

USAGE는 "권한 없음"을 뜻하는 placeholder. CREATE USER 시 자동 생성. 실제 권한은 그 다음 줄에 별도로 명시된다.


포트 사용 확인

sudo ss -tlnp
sudo ss -tlnp | grep 3306

전체 구조 요약

외부 클라이언트 (192.168.1.100)
  └─ ufw: 3306 허용
      └─ MySQL: appuser@192.168.1.100 (target_table만)

로컬
  └─ root@localhost만

SSL 강제 (선택)

평문으로 쿼리 전송 시 패킷 스니핑 위험. 민감한 데이터라면 SSL 필수:

ALTER USER 'appuser'@'192.168.1.100' REQUIRE SSL;

참고: SSH 터널 방식 (포트 안 열어도 됨)

MySQL 포트를 아예 닫고 SSH 터널로 접속하는 방식. ed25519 키 인증 그대로 사용 가능.

ssh -L 3306:localhost:3306 user@서버IP -N

클라이언트에서 127.0.0.1:3306으로 접속. DBeaver 등 GUI 툴은 SSH 터널 설정 UI 내장.