인프라는 어떻게 구성해야 할까?

Shef·2023년 2월 6일
20

Infra

목록 보기
1/5
post-thumbnail

인프라란 무엇인가요?

여러분은 '인프라'라고 하면 무엇이 떠오르시나요?
저는 바로 도로, 수도, 통신 등이 떠오릅니다.
도시가 여러가지 서비스를 제공하기 위한 환경이라고 할 수 있겠네요.

저희가 서비스를 만들 때 사용하는 단어인 '인프라'는 그럼 무엇을 의미할까요?
바로 저희 서비스를 제공하기 위한 환경을 의미합니다.

인프라의 본질은 사용자의 신뢰를 얻는 것

만약 도로가 제대로 만들어지지 않아 자동차로 여기저기 다닐 수 없고,
통신망이 제대로 구축이 안되어서 전화가 터지지 않는다면, 여러분은 그 도시에서 살고 싶으신가요?
저는 절대로 살고 싶지 않습니다. 처음부터 그런 환경에서 살았다면 모르겠지만, 이미 너무나도 좋은 환경에 익숙해져 있거든요.

저희의 서비스도 마찬가지입니다.

사용자가 원할 때 접근할 수 없다면, (무중단 / 가용성)
사용자가 서비스를 이용하는데 매번 기다려야 한다면, (성능)
사용자의 개인정보가 누출된다면, (보안)

사용자는 저희의 서비스를 이용하고 싶지 않을 것입니다.

즉, 인프라를 제대로 구축한다는 것은 사용자가 언제든 저희 서비스를 믿고 이용할 수 있도록 신뢰를 구축하는 것입니다.

그럼 어떻게 인프라를 구성해야 하나요?

어떻게 인프라를 구성해야 하는가.. 굉장히 막연한 질문이죠?
일단 저희가 이미 서비스를 하나 만들었다고 상상하고 차근차근 구축하면서 알아보도록 하겠습니다. 저희가 만든 서비스의 서버는 WAS서버 한 대와 DB서버 한 대로 구성되어 있습니다.

자.. 음.. 서버를 어디에 둘까요?

온프레미스 방식은 신경 쓸게 너무 많다

개인 PC에서 서버 돌리기

쉽게 떠올릴 수 있는 방법은 집에서 쓰던 컴퓨터로 서버를 돌리는 방법입니다.
ngrok이나 포트포워딩 등 이런저런 방법을 사용해서 외부에서 집 컴퓨터로 접속이 가능하게 구성하였습니다. 한 동안 이 컴퓨터로 서버도 돌리고 게임도 하면서 지내다가 문득 이런 생각이 듭니다.

'근데 이 컴퓨터 언제 끄지?'

컴퓨터 웅웅대는 소리로 불면증에 걸리기 직전에 컴퓨터를 과감히 끄고,
사용자들의 신뢰를 잃어버렸습니다.

사무실에서 서버 돌리기

사무실 한 켠에 작은 공간을 마련하고 2개의 서버 컴퓨터를 위치시킵니다.
집에서 잠도 잘 자고 즐겁게 서버를 운영하던 어느 날, 사무실이 어두워졌습니다.

정전으로 인해 서버는 다운되고, 사용자들의 신뢰를 잃어버렸습니다.

정전에 대비하기 위하여 정전 상태에서도 비상 전력을 공급해주는 UPS를 알아보다가 다음 글을 보게 됩니다.

더 머리가 아파오기 전에 데이터센터를 임대하고 서버를 옮깁니다.

데이터센터에서 서버 돌리기

서버를 옮긴 다음 날, 화재로 인해 서버가 다운되었습니다.

클라우드 업체로 서버와 고민을 떠넘기자

서버 장비를 직접 구입하고 운영하는 방식은 고려해야 할 요소가 너무나도 많습니다.

'여러 데이터센터에 서버를 이중화 해야 할까?'
'장비가 망가지면 어떻게 하지?'
'트래픽이 늘어날 것을 대비해 서버 장비를 더 산다면 얼마나 더 사야할까?'
'데이터 센터 내의 다른 서버로 DDoS 공격이 올 때도 우리 서버가 안전할까?'
'디스크가 깨지면 데이터가 유실될텐데 어떻게 하지?'

...

몇 가지만 고려하지 못하더라도 서버는 쉽게 다운되고 사용자들의 신뢰를 잃기 쉽습니다.
단순히 클라우드를 사용하여 서버를 운영하는 것만으로도 좋은 인프라의 요소를 많이 갖출 수 있습니다.

그럼 이제 클라우드를 사용해서 인프라 구축을 시작해보도록 하겠습니다.
클라우드는 가장 보편적인 AWS를 사용하도록 하겠습니다.

일단 EC2로 서버를 만들어보자

이제 그림과 함께 다시 상상해 봅시다.

클라우드를 사용하기로 하고 일단 AWS EC2를 활용해서 WAS 서버와 DB 서버를 구축했습니다. 클릭 몇 번이면 서버가 만들어지니 너무나도 편합니다. 즐거운 마음으로 서비스 개발에만 집중하던 어느 날 기사 헤드라인에서 우리 서비스를 발견합니다.

'OO서비스, 개인정보 유출로 시장,이용자 신뢰 모두 잃어.... '

신뢰는 보안으로부터

Security Group으로 보안을 튼튼히

개인정보가 담겨 있는 DB는 WAS 서버와 관리자의 접근만을 필요로 합니다. 따라서 인터넷과 연결될 필요가 없습니다. 방화벽은 특정 포트를 특정 IP에게만 허용하게 해줄 수 있습니다. Security Group은 AWS에서 제공하는 가상의 방화벽입니다. DB 프로세스로 접속할 수 있는 3306 포트는 WAS 서버의 IP로, SSH를 통해 DB 서버로 접속할 수 있게하는 22번 포트는 관리자 컴퓨터의 IP로 열어줍니다.

망분리로 보안을 더 튼튼히

포트와 포트에 접근 가능한 IP를 통제했지만, 단순히 패킷이 Security Group에 의해 막히는 것일 뿐입니다. 인터넷에 연결되어 있는 한 수많은 해커들에 공격에 의해 Security Group 또한 뚫릴 여지가 있습니다. 인터넷과 연결 가능한 WAS 서버는 외부망에, 인터넷과 연결이 필요 없는 DB 서버는 내부망에 둠으로써 해커들이 접근하지 못하게 할 수 있습니다.

먼저 AWS로부터 254개의 EC2 인스턴스를 포함할 수 있는 VPC(Virtual Private Cloud)를 할당 받습니다. VPC는 '가상 사설망'이라는 뜻으로 수많은 기업들이 같이 사용하는 클라우드 망을 마치 우리 서비스 전용망으로 사용하는 것과 같습니다. 각각의 VPC는 서로 독립되어 있어 네트워크 간섭이 일어나지 않습니다.

VPC에 Subnet을 2개로 구성하고 하나는 외부망 다른 하나는 내부망으로 사용해 봅니다.
Subnetting은 하나의 망(네트워크)를 여러 작은 망으로 나누는 것을 의미합니다.

각각의 Subnet은 내부 라우터를 통해 통신하고 각각의 Subnet을 아우르는 VPC라는 거대한 망은 외부 라우터를 통해 인터넷과 통신합니다. 이 외부 라우터를 AWS에서는 인터넷 게이트웨이(IGW)라고 부릅니다.

외부망과 내부망은 단순히 인터넷과 연결되어 있냐 아니냐에 차이입니다. Subnet과 연결된 라우터의 라우팅 테이블에, 외부로 나가는 패킷의 목적지로 인터넷 게이트웨이가 기록되어 있다면, 인터넷 게이트웨이는 이 라우터를 알게 되고, 결론적으로 외부에서 이 Subnet에 접근 가능해지게 됩니다. 이런 Subnet을 '외부망'이라고 부르고, 이런 식으로 인터넷 게이트웨이와 연결되지 않은 Subnet을 '내부망'이라고 부릅니다.

Bastion Server로 보안을 더더 튼튼히

VPC를 할당 받고 외부망과 내부망을 구성하고 WAS 서버는 외부망에, DB서버는 내부망에 구성했는데 한 가지 문제가 생겼습니다. 내부망은 인터넷 게이트웨이와 연결되어 있지 않기 때문에 더 이상 외부로부터 접근이 불가능합니다. 그렇다면 저희는 어떻게 내부망 안에 있는 DB 서버에 SSH를 통해 접속할 수 있을까요?

내부망과 연결된 라우팅 테이블에다가 관리자 컴퓨터의 IP로 나가는 패킷은 IGW로 향하도록 기록하는 것은 그리 현명한 선택이 아닙니다. 결국 인터넷과 연결된 통로가 생긴 셈이고, 이 부분을 통해 악성 루트킷이나 랜섬웨어가 침투할 수 있습니다.

내부망이라 하더라도 같은 VPC 안에서는 내부 라우터를 통하여 서로 접근이 가능합니다. 따라서 외부망에 서버를 하나 만들고 관리자의 컴퓨터는 이 서버를 경유하여 내부망으로 접근하도록 구성할 수 있습니다. 이렇게 된다면 악성 루트킷이나 랜섬웨어에 의해 피해를 보더라도 이 서버만 재구성해주면 되므로 서비스의 영향을 최소화 할 수 있습니다.

민감한 서버들에 보안을 각각 강화하는 것보다, 이렇게 입구 서버를 하나 만들고 이 서버의 보안을 충실히 함으로써 관리 포인트를 줄일 수 있습니다.

해커들의 공격을 막아주며 내부를 보호해주는 이 서버를 마치 중세 시대의 성 외곽을 보호하기 위해 돌출된 부분과 같다고 하여 'Bastion 서버'라고 부릅니다.

Reverse Proxy Server로 보안을 더더더 튼튼히

자 이제 Bastion 서버를 통해서 저희의 DB 서버에 접근할 수 있어 안전한 것 같습니다.
그런데 Bastion 서버 뿐만이 아니라 저희 DB서버에 접근할 수 있는 서버가 한 가지 더 있습니다. 바로 앞에서 구성했던 WAS 서버입니다. 해커는 튼튼한 Bastion 서버 보다는 뭔가 헐랭이 같은 WAS 서버를 노릴 수 있습니다.

이를 테면 사용자의 개인정보가 담긴 패킷이 WAS로 오기 전에 탈취해 갈 수 있습니다. 또는 WAS가 DB로 의도하지 않은 SQL문을 전달하게 하는 SQL Injection, 게시물이나 댓글에 악성코드를 심어 쿠키를 탈취하는 XSS 공격을 통해 DB로부터 민감한 정보를 빼갈 수도 있겠죠.

물론 WAS 서버에서 TLS 설정을 하거나 애플리케이션 코드에서 적절하지 않은 요청을 필터링하는 방식으로 위와 같은 위협을 잘 방어할 수 있습니다만, 이런 많은 위협들을 방어하는 것을 오로지 WAS의 몫으로 남겨두어야 할까요? 위와 같은 위협 외에도 다른 많은 위협이 있고 WAS는 자신의 서비스 로직을 처리하기도 바쁜데 말이죠.

만약 WAS의 앞단에 Bastion 서버처럼 보안 처리를 도와줄 서버를 하나 더 둔다면 어떨까요? 사용자가 데이터를 요청하면 이 서버가 중간에서 요청을 받아 보안 검사를 하고 WAS로 넘겨주는 겁니다. 다시 WAS는 이 서버로 응답을 넘겨주고 이 서버는 응답을 사용자에게로 전달하죠. 이렇게 함으로써 인터넷으로부터 WAS로의 트래픽을 차단하여 보안이 한층 더 강화될 수 있습니다.

이렇게 앞단에 서버를 설치하게 되면 보안 이외에도 부하분산을 위한 로드 밸런서의 역할, 서버의 상태 체크 등 여러가지 일을 수행 할 수 있어 더욱 좋습니다.

통상적으로 사용자와 서버 사이에서 중개 역할을 해주며 내부로부터 사용자의 패킷을 받아 인터넷으로 대신 보내주는 서버를 'Proxy 서버'라고 부릅니다. 반대로 위와 같이 인터넷으로부터 패킷을 받아서 내부로 보내주는 서버를 'Proxy 서버'와 대비해서 'Reverse Proxy 서버'라고 부릅니다.

마무리

자.. 여기까지 오느라 힘들었습니다.
이제 최종적으로 완성된 저희의 인프라를 보도록 하겠습니다.

보안은 그럭저럭 잘 지키고 있는 것 같습니다.

...

그런데 만약 사용자가 엄청나게 몰리기 시작한다면 어떻게 될까요?
만약 WAS나 DB에 장애가 난다면?
DB의 수많은 데이터로 인해 서비스가 매우 느려진다면?

사용자와의 '신뢰'를 지킬 수 있을까요?

...

'최종적으로'라는 말은 취소해야겠습니다.
저희의 인프라는 아직도 갈길이 멀군요. ^^;

번외편

내부망에서 먼저 인터넷에 접속할 수는 있다?

내부망의 서버도 때로는 인터넷으로의 연결이 필요할 때가 있습니다. 이를테면 인터넷을 통해 DB 서버의 업데이트를 하고 싶을 수도 있겠죠. 인터넷으로부터 먼저 들어오는 트래픽은 차단하면서, 내부망으로부터 외부망으로는 먼저 통신을 시도할 수 있는 방법이 있습니다.

바로 NAT(Network address translation) 게이트웨이를 사용하는 것입니다. NAT 게이트웨이는 Private IP를 퍼블릭 IP로 변환해서 Public IP를 갖고 있지 않은 내부망이 인터넷과 통신할 수 있게 도와줍니다. 내부에서 먼저 통신을 시도할 때는 내부 서버의 IP를 NAT 테이블에 기록하여 응답으로 돌아오는 데이터가 다시 내부 서버로 들어갈 수 있지만, 내부 서버의 공인 IP가 실제로 존재하는 것은 아니기 때문에 외부에서 먼저 통신하는 것은 여전히 불가능합니다.

Bastion Server를 더 잘 활용하려면?

  1. VPN을 활용하고 인증과정을 더하여 철저히 인증된 사용자만 접근할 수 있게 하기.
  2. Bastion Server로의 접속이 허용된 관리자라 할지라도 터미널로 접속해서 작업한 명령어 히스토리를 기록할 수 있도록 Bastion Server에 설정해두기.
  3. WAS나 Reverse Proxy Server 등 민감하지 않은 서버일지라도 접속할 때는 Bastion Server를 경유하기. 이를 통해 위 서버들이 DDoS 등의 공격으로 접속이 불가능하더라도 관리자는 Bastion Server를 통해 접근할 수 있다.

Reference

NEXTSTEP - 인프라 공방
VPC 개요
퍼블릭 및 프라이빗 서브넷
[이해하기] NAT (Network Address Translation) - 네트워크 주소 변환

2개의 댓글

comment-user-thumbnail
2023년 7월 1일

내용 너무 좋네요! 감사합니다

1개의 답글