로컬 환경에서 외부 DB 서버에 접근해보자 (feat. MySql, SSH 터널링, VPC)

yujamint·2023년 5월 31일
0

infra

목록 보기
1/3
post-thumbnail

들어가며

우테코 장바구니 협업 미션을 진행하며 외부 서버에 존재하는 MySql에 접근해야 했다.

추가로, 로컬 환경에서 DB 서버로 직접 접근할 수 없는 환경이다.

개발의 편의성을 위해 로컬에서 DB 서버에 직접 접근할 수 있도록 하는 과정에서 많은 삽질을 했다. 같은 삽질을 반복하지 않기 위해 이를 기록하고자 한다.


개발 환경

  • 총 3개의 서버 존재
    1. 개발을 진행하는 로컬 서버
    2. 스프링 서버를 띄우는 APP 서버 (AWS EC2)
    3. MySql 서버를 띄우는 DB 서버 (AWS EC2)
  • EC2 인스턴스의 보안 그룹 설정으로 인해, DB 서버는 APP 서버에서만 접속할 수 있다. 즉, 로컬 서버에서는 DB 서버에 다이렉트로 접근할 수 없다.

SSH 터널링이 무엇일까? 왜 필요할까?

(편한 이해를 위해 테스트 DB는 배제하고, 프로덕션에 사용되는 MySql DB만을 언급)

개발의 편의성을 위해 로컬 서버에서도 DB에 접근할 수 있도록 하자.

하지만 보안 설정상, 로컬 서버에서의 접근은 막혀 있다. DB 서버에 접근하는 방법을 모색해야 한다.

이때 ssh 터널링을 이용할 수 있다. ssh 터널링을 간단하게 설명하자면, “출발지에서 목적지로 한 번에 이동할 수 없을 때, 목적지로 이동 가능한 지점을 거쳐서 이동하는 우회 접근 방법”이다.

지하철 노선도를 예로 생각해보자. 우리는 잠실새내역(2호선)에서 석촌역(8호선)으로 이동하고 싶다. 두 역은 노선이 다르기 때문에 바로 이동할 방법이 없다. 이때 석촌역과 같은 노선에 속한 잠실역(2호선, 8호선)을 거쳐서 이동하는 방법, 즉, ssh 터널링을 선택할 수 있다.

이를 현재의 개발환경에 적용해보자.

로컬 서버에서 DB 서버에 접근하고 싶지만, 바로 이동할 수 없다. 그렇기 때문에 DB 서버에 접근 가능한 APP 서버를 우회해서 접근한다.

즉, 로컬 서버 → APP 서버 → DB 서버의 형태로 접근할 것이다.

SSH 터널링 설정

DBeaver, MySql Workbench, DataGrip 등 많은 툴에서 DB 연결 시에 SSH 터널링을 지원한다.

이 글에서는 DataGrip을 기준으로 설명한다. 위 3개의 툴 모두 사용해 본 결과, 설정 방법은 비슷하다.

설정 방법

ssh-connect
  • Host: DB 서버에 접근하기 위해 우회APP 서버의 주소를 입력한다.
    • 우회할 서버, 현재의 APP 서버를 점프 호스트라고도 부른다.
  • Port: ssh 연결을 할 것이기 때문에 22번 포트를 사용한다.
  • Username: 점프 호스트의 Username을 적는다.
    • 터미널에서 ssh 연결을 할 때, ubuntu@43.~ 를 입력하며 연결했을 것이다. @ 앞 부분이 Username, 뒷 부분이 Host라고 생각하면 된다.
  • Private key file: 로컬에서 점프 호스트로 접속할 때 사용하는 key file 경로를 입력한다.

이렇게 설정을 마친 뒤 Test Connection을 해보면, 다음과 같이 SSH 연결에 성공했다는 것을 확인할 수 있다.

ssh-connect-success

삽질의 시작 - root 계정

SSH 터널링은 준비됐다. 이제 로컬에서 DB 서버에 접속되는지 확인만 하면 된다.

접속할 DB 서버의 정보를 입력하자.

root-connect
  • Host: 접속할 DB 서버의 ip를 입력한다. (EC2로 띄운 DB 서버)
  • Port: 연결할 DB가 사용하고 있는 포트 번호를 입력한다. MySql은 3306번 포트를 사용한다.
  • Authentication: 인증 방법을 선택한다. MySql 계정명 & 비밀번호를 통해 인증한다.
    • User: MySql 계정명
    • Password: 계정의 비밀번호
  • Database: 연결할 database를 입력한다. (ex. chess, subway, shopping-order 등.. *생략가능)

모든 정보를 입력했으니 MySql의 root 계정으로 Test Connection해보자.

root-connect-fail

실패했다.

이유를 찾아보니 root 계정은 많은 권한을 갖고 있기 때문에 기본적으로 localhost에서만 접근이 가능하도록 설정되어 있다.

즉, 보안상의 이유로 DB 서버의 localhost에서만 접근할 수 있는 것이고 나의 로컬 서버에서는 접근이 불가능한 상태다.

root 계정에서 외부 접근을 허용하도록 설정할 수도 있지만, MySql에서 제안하는대로 새로운 계정을 만들어서 외부 접근을 허용하도록 하자.

외부 접근을 허용하는 계정 생성

yuja 계정을 생성했다.

public-ip-account

user 조회 결과에서 볼 수 있듯이, yuja 계정은 43.~ ip의 접근을 허용하고 있다.

  • 43.~는 APP 서버의 Public ip다.

우리는 ssh 터널링 설정을 했고, 결국 APP 서버를 통해 DB 서버에 접근할 것이다. 그리고 APP 서버의 Public ip 접근을 허용했으니 로컬에서 DB 서버에 접근할 수 있을 것이다!

얼른 접속해보자.

yuja-fail

실패했다.

왜 실패했을까? 다시 한 번 짚어보자.

우리는 ssh 터널링을 통해 로컬 서버 → APP 서버 → DB 서버의 흐름으로 접근할 것이다.

첫 번째로, ssh 터널링 설정이 잘 되어 있는 것을 확인했기 때문에 로컬 서버 → APP 서버의 연결은 정상적으로 이뤄졌다.

그리고, DB 서버의 MySql에는 yuja라는 계정을 생성해줬다. 이 계정은 APP 서버의 접근을 허용하고 있다. 그러면 APP 서버 → DB 서버의 연결도 잘 돼야 할텐데..?

진실은 Private IP에..

우리가 간과하고 있는 사실이 있다.

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 계정을 생성했다.

private-ip-account

mint 계정은 192.~ ip 대역에서의 접속을 허용한다.

APP 서버의 Public ip와는 다르게, Private ip는 192.~ 대역에 속한다. 그렇기 때문에 이제 DB 서버의 MySql 접속에 성공할 수 있을 것이다.

접속해보자!

mint-fail

실패했다.

bind-address 설정

현재처럼 다른 서버의 DB에 접근하려고 하는 경우, 즉 외부에서 접근하는 경우에는 MySql에서 외부 접근을 허용하도록 설정해야 한다.

(OS마다 기본 설정이 다르지만, ubuntu에서의 MySql기본 설정은 로컬호스트 접근만 허용하고 있다.)

외부 접근을 허용하기 위해서는 bind-address를 설정해주면 된다.

MySql 8.0.33 버전, 우분투 환경 기준으로 설정 파일의 경로는 /etc/mysql/mysql.confg.d/mysqld.cnf이다.

bind-address-default

해당 파일을 확인해보면 bind-address가 127.0.0.1(localhost)로 설정되어 있는 것을 확인할 수 있습니다. 해당 설정값을 0.0.0.0으로 변경해주면 모든 IP에 대해서 외부 접근을 허용한다.

bind-address-set

값을 바꾼 뒤, mysql을 restart하면 다음과 같이 MySql 접속에 성공한다.

final-success

마침내 로컬에서 DB 서버로 접근할 수 있게 되었다.

마치며

처음에는 ssh 터널링에 대해서 모른다고 생각했다. 하지만 생각해보니 ssh 연결은 처음부터 잘 되었고, 정말 몰랐던 부분은 다음 2가지였다.

  1. MySql의 외부 접근 관련 설정
  2. VPC에서의 통신(Private ip를 통한 통신)

누군가에겐 당연한 지식일 수 있지만, 여러 번의 삽질을 하며 몰랐던 정보를 많이 알게 되어 뿌듯하다.

profile
개발 기록

0개의 댓글