우테코 장바구니 협업 미션을 진행하며 외부 서버에 존재하는 MySql에 접근해야 했다.
추가로, 로컬 환경에서 DB 서버로 직접 접근할 수 없는 환경이다.
개발의 편의성을 위해 로컬에서 DB 서버에 직접 접근할 수 있도록 하는 과정에서 많은 삽질을 했다. 같은 삽질을 반복하지 않기 위해 이를 기록하고자 한다.
(편한 이해를 위해 테스트 DB는 배제하고, 프로덕션에 사용되는 MySql DB만을 언급)
개발의 편의성을 위해 로컬 서버에서도 DB에 접근할 수 있도록 하자.
하지만 보안 설정상, 로컬 서버에서의 접근은 막혀 있다. DB 서버에 접근하는 방법을 모색해야 한다.
이때 ssh 터널링을 이용할 수 있다. ssh 터널링을 간단하게 설명하자면, “출발지에서 목적지로 한 번에 이동할 수 없을 때, 목적지로 이동 가능한 지점을 거쳐서 이동하는 우회 접근 방법”이다.
지하철 노선도를 예로 생각해보자. 우리는 잠실새내역(2호선)
에서 석촌역(8호선)
으로 이동하고 싶다. 두 역은 노선이 다르기 때문에 바로 이동할 방법이 없다. 이때 석촌역과 같은 노선에 속한 잠실역(2호선, 8호선)
을 거쳐서 이동하는 방법, 즉, ssh 터널링을 선택할 수 있다.
이를 현재의 개발환경에 적용해보자.
로컬 서버에서 DB 서버에 접근하고 싶지만, 바로 이동할 수 없다. 그렇기 때문에 DB 서버에 접근 가능한 APP 서버를 우회해서 접근한다.
즉, 로컬 서버 → APP 서버 → DB 서버의 형태로 접근할 것이다.
DBeaver, MySql Workbench, DataGrip 등 많은 툴에서 DB 연결 시에 SSH 터널링을 지원한다.
이 글에서는 DataGrip을 기준으로 설명한다. 위 3개의 툴 모두 사용해 본 결과, 설정 방법은 비슷하다.
설정 방법
ubuntu@43.~
를 입력하며 연결했을 것이다. @
앞 부분이 Username, 뒷 부분이 Host라고 생각하면 된다.이렇게 설정을 마친 뒤 Test Connection
을 해보면, 다음과 같이 SSH 연결에 성공했다는 것을 확인할 수 있다.
SSH 터널링은 준비됐다. 이제 로컬에서 DB 서버에 접속되는지 확인만 하면 된다.
접속할 DB 서버의 정보를 입력하자.
모든 정보를 입력했으니 MySql의 root 계정으로 Test Connection
해보자.
실패했다.
이유를 찾아보니 root 계정은 많은 권한을 갖고 있기 때문에 기본적으로 localhost에서만 접근이 가능하도록 설정되어 있다.
즉, 보안상의 이유로 DB 서버의 localhost에서만 접근할 수 있는 것이고 나의 로컬 서버에서는 접근이 불가능한 상태다.
root 계정에서 외부 접근을 허용하도록 설정할 수도 있지만, MySql에서 제안하는대로 새로운 계정을 만들어서 외부 접근을 허용하도록 하자.
yuja
계정을 생성했다.
user 조회 결과에서 볼 수 있듯이, yuja
계정은 43.~
ip의 접근을 허용하고 있다.
43.~
는 APP 서버의 Public ip다.우리는 ssh 터널링 설정을 했고, 결국 APP 서버를 통해 DB 서버에 접근할 것이다. 그리고 APP 서버의 Public ip 접근을 허용했으니 로컬에서 DB 서버에 접근할 수 있을 것이다!
얼른 접속해보자.
실패했다.
왜 실패했을까? 다시 한 번 짚어보자.
우리는 ssh 터널링을 통해 로컬 서버 → APP 서버 → DB 서버의 흐름으로 접근할 것이다.
첫 번째로, ssh 터널링 설정이 잘 되어 있는 것을 확인했기 때문에 로컬 서버 → APP 서버의 연결은 정상적으로 이뤄졌다.
그리고, DB 서버의 MySql에는 yuja
라는 계정을 생성해줬다. 이 계정은 APP 서버의 접근을 허용하고 있다. 그러면 APP 서버 → DB 서버의 연결도 잘 돼야 할텐데..?
우리가 간과하고 있는 사실이 있다.
APP 서버와 DB 서버간의 통신은 EC2 인스턴스의 Private IP를 통해서 이뤄진다는 것이다.
두 서버는 같은 VPC 내부에 존재하고, 같은 VPC 내의 통신은 기본적으로 Public IP가 아닌 Private IP를 통해 이뤄진다.
Public ip를 통해 APP 서버에 ssh 연결을 했다. 그렇기 때문에 당연히 MySql에서도 APP 서버의 Public ip 접근을 허용하면 통신이 가능할 것이라고 생각했다.
하지만 실제로는, APP - DB 서버는 서로 Private ip를 통해 통신한다는 것이다!
이제 이 사실을 알게 되었으니 MySql에서도 Private ip의 접근을 허용하도록 하자.
mint
계정을 생성했다.
mint
계정은 192.~
ip 대역에서의 접속을 허용한다.
APP 서버의 Public ip와는 다르게, Private ip는 192.~
대역에 속한다. 그렇기 때문에 이제 DB 서버의 MySql 접속에 성공할 수 있을 것이다.
접속해보자!
실패했다.
현재처럼 다른 서버의 DB에 접근하려고 하는 경우, 즉 외부에서 접근하는 경우에는 MySql에서 외부 접근을 허용하도록 설정해야 한다.
(OS마다 기본 설정이 다르지만, ubuntu에서의 MySql기본 설정은 로컬호스트 접근만 허용하고 있다.)
외부 접근을 허용하기 위해서는 bind-address
를 설정해주면 된다.
MySql 8.0.33 버전, 우분투 환경 기준으로 설정 파일의 경로는 /etc/mysql/mysql.confg.d/mysqld.cnf
이다.
해당 파일을 확인해보면 bind-address
가 127.0.0.1(localhost)로 설정되어 있는 것을 확인할 수 있습니다. 해당 설정값을 0.0.0.0으로 변경해주면 모든 IP에 대해서 외부 접근을 허용한다.
값을 바꾼 뒤, mysql을 restart하면 다음과 같이 MySql 접속에 성공한다.
마침내 로컬에서 DB 서버로 접근할 수 있게 되었다.
처음에는 ssh 터널링에 대해서 모른다고 생각했다. 하지만 생각해보니 ssh 연결은 처음부터 잘 되었고, 정말 몰랐던 부분은 다음 2가지였다.
누군가에겐 당연한 지식일 수 있지만, 여러 번의 삽질을 하며 몰랐던 정보를 많이 알게 되어 뿌듯하다.