이전 글에서 다뤘듯이, Private Database는 외부에서 인터넷을 통해 접근할 수 없다. public IP가 할당되지 않았고, Internet Gateway을 Subnet의 라우팅 테이블에 추가하지 않았기 때문이다. 그렇다 보니, 로컬(local) 환경에서 일반적인 SSH 연결로는 Private DB와 통신을 주고받는 것이 불가능하다.
SSH Tunneling이 필요한 것도 그래서다. SSH Tunneling의 의미는 대략 다음과 같다.
SSH 터널링이란 터널링을 SSH 프로토콜을 이용하여 구현하는 것이다. 사내 내부망에 있는 서버로 직접 접속을 허용하지 않는 경우 외부에서 내부에 접근하기 위해서 터널링 기술을 이용하고 이때, SSH 프로토콜을 이용하여 패킷을 암호화하는 것이다.
쉽게 말하면, Public EC2와 Private DB를 엮어 SSH 터널을 생성한 뒤, 로컬(local)에서 Public EC2로 요청을 보내면, 해당 요청이 Public EC2로 전송된 뒤 서버 내부에서 다시 포워딩되어 Private DB로 도달하게 만드는 것이다. 포트 포워딩을 떠올리면 된다. 포트 포워딩이 가능한 이유는 이전 글에서 언급했던 것처럼, Private EC2의 22번 SSH 포트를 허용해뒀기 때문이다.
우선, Public EC2와 Private DB를 엮어 SSH 터널을 생성해보자.
# 명령어 형식
ssh -i [pem키 경로] -CNf -L [local port]:[database host]:[remote port] [username]@[remote host]
# 예시
ssh -i [pem키 경로] -CNf -L 33306:127.0.0.1:3306 ubuntu@[EC2 프라이빗 IPv4 주소 or 호스트 이름]
명렁어 세부 설명
[local port]
: Private DB와 연결할 Public EC2의 포트 번호. 필자의 경우 Public EC2 내부에 설치된 MariaDB가 3306번을 사용 중이었기 때문에, 임의의 번호인 33306번을 지정했다.
[database host]
: Private DB의 IP 주소나 호스트 이름을 적어주면 된다. Private DB가 Private EC2 안에서 localhost로 존재한다면 127.0.0.1
을 입력한다.
[remote port]
: Private DB가 사용 중인 포트 번호를 입력한다.
[username]
: remote host의 username
[remote host]
: tunnel을 연결할 Private Instance(EC2)의 프라이빗 IPv4 주소나 호스트 이름을 입력한다. 필자의 경우 프라이빗 IPv4 주소를 입력했다.
N
: 서버에 대한 포트 포워딩 접속을 유지
F
: background에 ssh 터널을 등록. 주기적으로 터널링 명령어를 입력할 필요가 없어진다.
L
: Private EC2로 접속한 후, 127.0.0.1 서버의 3306에 접속하는 터널을 33306 포트에 등록
C
: 이에 대한 모든 데이터를 압축하여 명령을 요청
Private DB 접속
# MariaDB 접속 명령어
mysql -u root -p -h [database host] -P [local port] -> password 입력 -> 접속 성공
# 예시
mysql -u root -p -h 127.0.0.1 -P 33306
mysql error: Access denied for user 'root'@'localhost’
가 발생했을 경우
# Mysql(MariaDB)접속
sudo mysql -u root -p
# root 계정 확인
SELECT User, Host, plugin FROM mysql.user;
# root 계정에 비밀번호 지정
ALTER user 'root'@'localhost' IDENTIFIED BY '[password]';
로컬(local)과 Private DB를 연결하는 터널을 생성하려면, 두 가지 설정이 선행돼야 한다. 첫 번째는 Private EC2의 3306포트를 개방하여 localhost 이외의 ip가 Private DB에 접근할 수 있도록 하는 것이다. 다른 하나는 로컬(외부)에서 Database에 로그인할 수 있도록 외부 접속용 계정을 생성하는 일이다.
우선 AWS 계정으로 로그인하여 Private EC2가 3306 포트로의 외부 접속을 허용하도록 보안 규칙을 편집하자.
외부 접속이 허용되도록 Private DB 설정 파일(mysql.conf.d
혹은 mariadb.conf.d
)을 편집하는 것도 잊지 말자. bind-address
를 주석처리하면 DB에 127.0.0.1
과 0.0.0.0
모두에서 접근할 수 있다.
이제 외부 접속용 DB 계정을 생성하자. 생성 방법에 관한 설명은 생략하겠다. 구글에서 'mysql 외부 접속 계정'이라고 검색하면 관련 자료를 쉽게 찾을 수 있다. 계정이 정상 생성됐다면, 아래 이미지처럼 Host 값이 '%'인 계정이 만들어진다.
mysql -u root -p
-> DB 접속USE mysql
SELECT user, host FROM user;
# 명령어 형식
ssh -N -L [local port]:[Private EC2 host name]:[remote port] -i [pem키 경로] [username]@[Public EC2 host name OR public IP]
# 예시
ssh -N -L 33306:ip-172-xx-xx-xxx.ap-northeast-2.compute.internal:3306 -i xxx-xxxxxxx-xxxx.pem ubuntu@52.xx.xx.xxx
# 터널 생성 확인
lsof -i :[local port]
# 예시
lsof -i :33306
# DB 접속
myysql -u [외부 접속용 계정] -p -h 127.0.0.1 -P [local port]
# 예시
mysql -u sangxxx -p -h 127.0.0.1 -P 33306