용어 목록
온디맨드
사용한 만큼만 비용을 지불하는 것
예컨대, 유저수나 트래픽 양에 따라 지불 금액이 달라진다. 특정 상황에 트래픽이 발생했을 때만 추가 비용을 지출한다.
또한, 서비스 타입에 따라 서버 타입을 원하는대로 바꿔가며 임대할 수도 있다.(메모리/CPU/GPU 등 각각 많이 필요로 하는 서비스가 있으니까?)
온프레미스
물리 서버. 기업에 요구 사항에 맞춰 직접 데이터 센터를 구축하는 것을 의미한다. 유지 보수 비용(고정 비용)이 발생한다. 또한, 직접 운영과 관리가 필요하다. (수요와 상관없이) 이는 폐쇄형 배포 모델이다.반대인 오프 프레미스는 클라우드 서버. 임대형과 비슷함. 이를 공개형 배포 모델이라 함.
IaaS(Infrastructure as a Service)
네트워크와 서버는 구축, OS 및 런타임 구성과 어플리케이션 구동은 직접 구현해내야 한다.
PaaS(Platform as a Service)
네트워크와 서버 OS 및 런타임 구성까지 구축, 그 위에 어플리케이션을 구동하는 일은 직접 해내야 한다.
SaaS(Software as a Service)
네트워크/서버/OS 및 런타임 구성/어플리케이션 모두 제공. Slack, Notion과 같은 서비스만 사용하면 되는 상태. 로컬에 설치하지 않고 클라우드로 모든 기능들을 제공한다.
(AWS)Region
전 세계에 국가 단위로 존재하며 물리적으로 AZ의 집합이다.
AZ(Availability Zone)
한 국가 내 지역별로 설치된 IDC(Internet Data Center)의 집합이다. 데이터 센터 하나로 관리하면 데이터 센터의 물리적인 변화가 일어났을 때 대처하기 어렵다. 이중 서버라고 생각하면 될듯?
ap-southeast-2a/2b/2c와 같이 Region 뒤에 넘버링이 붙는다.
IDC(Internet Data Center)
물리 서버로써, AZ 각각은 2개의 Data Center로 구성되어있다.
AWS
Region 서비스
Region과 AZ에 위치한 서버로, 클라우드로 서비스를 제공한다.
AWS 클라우드의 리전 서비스를 사용하고 싶을 때 Proximity(근접성), Available Service(특정 리전에서만 지원)의 기준으로 선택한다.
Global 서비스
Region에 상관없이 전역적으로 제공되어야 하는 서비스다. Global Edge Network Service라고도 부른다.
그 예로 IAM이 있는데, IAM의 기능인 AWS 계정 권한과 역할 관리는 어느 Region이든 상관없이 전역적으로 필요한 기능이다. 때문에 Region을 선택할 수 없다.
이제 네트워크로 들어가본다.
CIDR
CIDR는 Base IP와 Subnet Mask로 구성된다. "가용 네트워크 IP 대역"을 정의하는데 사용되는 표기법이다.
10.0.0.0 ~ 10.0.0.255까지 사용 가능한 IP 대역이라면, 10.0.0.0/24와 같이 간단히 표기할 수 있다.
CIDR은 Base IP와 Subnet Mask로 구성되어있다. Base IP는 사용 가능한 첫 IP, Subnet Mask는 Base IP에서 불변 영역을 의미한다. (앞선 /24처럼 간단하게 표기한다.)
그렇다면 CIDR은 어디서 사용하는가?
AWS VPC에서 네트워크를 설정하고 서브넷으로 네트워크 영역을 나눌 때 사용한다. 예컨대, 10.0.0.0/24라고 CDIR을 가정해보자.
가장 마지막의 옥텟이 가변의 영역이 되는데, 여기서 서브넷을 나눌 수가 있다. 그림에서는 서브넷 마스크를 2비트로 설정했고, 각각 10.0.0.0 ~ 10.0.0.63까지가 2-3(딱히 예가 생각나지 않아서 반으로 예시를..)반, 10.0.0.64~10.0.0.127까지가 2-4반이 될 수 있는 것이다. 표현하자면 /26이 되는데, 사실상 2비트를 사용한 서브넷의 경우 불변이라는 건 속임에 가깝다고 생각한다. 우리가 3반으로 가고 싶다면 무조건 10.0.0.0 ~ 10.0.0.63 사이로 접속해야 하기 때문에 불변보다는 강제에 더 가깝지 않나.
두번째는 설정을 적용할 타겟 IP 대역을 정의할 때 CDIR을 사용한다. Route Table 규칙 내 Destination 정의 시, 규칙을 적용할 서브넷을 명시할 때. 10.0.0.63은 2-3반 서브넷으로 보내고, 0.0.0.0/0에 대한 요청은 IGW로 보낸다.
OSI 7 Layer
물리 네트워크는 다양한 네트워크 장비가 구성되어 있는데, 각 네트워크 장비는 데이터를 전송할 때 전송을 위해 보는 데이터가 다르다.
가장 마지막 계층인 Applicatoin Layer는 HTTP Header와 Method, IP, Port가 관심사다. 네트워크의 서비스를 제공하는 계층이기 때문에 HTTP가 가장 대표적인 예.
4번째 계층인 Transport Layer는 IP와 Port를 프로토콜로 사용한다. 여기서는 세션의 설정과 유지, 종료를 담당하며 TCP와 UDP 등이 있다.
Network Layer는 IP를. Data Link Layer는 오류 감지 및 수정, 데이터 프레임을 전송하기 때문에 MAC 주소를 프로토콜로 사용한다. 대표적인 예가 Ethernet인데, 데이터를 프레임 단위로 쪼개서 주고 받는다. 이때 각 하드웨어의 고유한 주소를 MAC 주소라 한다. 이를 통해 서로를 식별한다.
주요 장치들
Switch(L2)
MAC 주소 기반 전달, Private으로 내부 네트워크 간 연결
Router(L3)
IP 기반 전달, Public으로 외부 네트워크 간 연결
Load Balencer(L4)
Ip와 Port 기반 분산, 많은 양의 트래픽을 여러 서버로 분산
Load Balencer(L7)
HTTP Header, Method, IP, Port 기반 분산.
앞선 HTTP 페이로드 분석을 통해 DDoS 등 네트워크 공격 방어
이제 다시 AWS로 돌아간다.
AWS VPC
앞선 장비들을 통한 여러 작업들은 간단하게 AWS 클라우드를 통해 쉽게 설정이 가능하다.
VPC는 Virtual Private Cloud로, 클라우드 인트라넷과 서브넷으로 구성되어있다. 이것을 통해 우리는 클라우드 Private 네트워크 영역을 부여 받을 수 있다.
이것을 세부적으로 나누어 서브넷(SubNetwork)로 구성해서 몇개의 네트워크로 자를 수 있다. 일반적으로 Private/Public 2가지로 분류하며, 선택에 따라 다르게 분류 가능하다. Private에 server와 database subnet을 나누어 둔다든지...
앞서 AWS에서 알아봤던 AZ를 떠올리면 될 듯.
10.0.0.0/16의 CIDR로 VPC를 생성한다.
그 후 subnet 4개를 만들어준다. 분명 VPC를 10.0.0.0/16로 정의했고, subnet 각각을 10.0.1.0/24 ~ 10.0.4.0/24로 정의하려 했는데 중첩된다는 이상한 오류를 내뿜었다. 중첩될 일이 없는데 대체 뭐지 싶어서 여러번 삭제했다가 생성했고 VPC도 재생성하니 subnet이 잘 만들어졌다.
다음으로 인스턴스 하나를 생성한다. 이 때 앞서 만든 public subnet 중 하나에 할당해준다. 굳이 고정 IP를 할당해 줄 필요도 없으므로 자동 할당 퍼블릭 IP도 활성화 한다.
이렇게 만든 인스턴스를 연결하여 실행하면 인스턴스 네트워크 설정이 올바르게 구성되지 않았다는 오류가 발생한다.
앞서 만든 VPC는 Virtual Private Cloud의 약자로 말 그대로 인트라넷과 똑같다. 외부와 연결할 수 있는 대문 하나가 필요하다.
IGW(Internet Gateway)
VPC 내부 서버가 외부와 통신할 수 있게 만들어주는 것이 IGW.
IGW는 인스턴스 단위 외부 IP를 할당한다. VPC 내부 서버가 외부와 양방향으로 접근 가능하도록 열어주는 GateWay다.
후에 알아 볼 내부 IP가 외부 IP로 변경되는 NAT 주소 변환 제공이 있다.
이렇게 만든 IGW를 VPC에 할당해준다. 하지만, 이렇게 해도 인스턴스 연결이 불가능하다.
Public Subnet이 자동으로 IGW를 통해 외부로 나갈 수 있을까? 그렇겐 할 수 없고, Public Subnet에 모든 트래픽을 IGW와 연결하기 위해서는 Route Table 설정을 해줘야 한다.
Route Table
Public/Private Subnet에 연결하며 해당 Subnet 내 서버에서 요청 발생 시 어디로 가야하는지 이정표 역할을 하는 네비게이션. 이때 요청이 향하는 방향은 Destination, 어디로 향해야 하는지는 target임. Destination이 0.0.0.0이면 Target은 IGW가 되겠다.
하지만 여태까지 했던 작업은 위 그림과 같이 정의하고 생성만 해줬을 뿐 연결이 안 되어있다. 이제 라우트 테이블을 생성하고 붙여보자.
Route Table을 하나 생성해서 VPC에 연결하고,
만들어뒀던 2개의 Public Subnet에 각각 연결해준다. 사실 우리가 Subnet을 Public/Private으로 나눴던 건 단지 나누고 이름만 붙였을 뿐 큰 의미를 가지지 않았으나, 이제 라우트 테이블을 연결해줌으로써 그 의미를 갖게 됐다.
라우트 테이블을 생성하고 연결해줬으니 그에 맞는 목적과 타겟을 정의해놓는다.
0.0.0.0/0(모든 트래픽)은 우리가 아까 생성해줬던 IGW로 이동하게 만들어준다.
그럼 이렇게 인스턴스 연결도 잘 되고 (SSH 22포트임) ping도 잘 온다.
SSH Tunneling Bastion
VPC 내부 서버가 외부로 통신할 수 있는 방법으로 Route Table의 예를 알아봤다. 2가지가 더 있는데, 그 중 하나가 SSH Tunneling.
SSH Tunneling, Jump, Box/Host/Server, Bastion 등 다양한 이름으로 불리는데, 외부 서버를 통한 내부 접근을 의미하며 Private 서브넷 내 위치한 서버에 인바운드 접근을 위해 외부 서버 Bastion을 통해 단방향 연결을 하는 것이다.
Public에서 Private Subnet과 연결해야 할 상황이 두가지가 있다.
1. Private 서브넷에 외부 개발자 컴퓨터에서 SSH를 통해 접근이 가능해야 할 때: 인바운드
2. Private 서브넷에서 Public으로 나가는 경우(외부 라이브러리 설치할 때): 아웃바운드
SSH Tunneling은 인바운드의 상황에서 사용하는 방식이다. 이때는 Bastion 서버를 통해 밖에서 안으로 들어올 문을 연다.
Jump, Box와 같은 다양한 이름이 존재하는 이유는 외부에서 Private 서브넷 내 서버에 접근하기 위해 Public 서브넷 내 서버를 디딤돌 삼아 점프를 하는 것과 비슷하기 때문이다.
그래서 연결 후 명령을 사용할 때 외부에서 접근하고자 하는 '내가' Bastion을 통해 접근하고 명령을 작성한다.
이를 위한 동작 원리로 Private Key - Public Key Pair를 사용한다.
1. local-to-bastion.pem: Local에서 bastion(Public)
2. bastion-to-private.pem: Bastion(Public)에서 Server(Private)
`
우선, local에서 bastion에 접근하기 위한 pem 키를 하나 생성한다.
이렇게 아까 만들었던 키를 bastion 인스턴스에 적용해주고, public subnet 중 하나에 할당해준다.
그 후 인스턴스를 연결하고, Bastion의 퍼블릭 IP를 통해서 로컬에서 접속이 가능한지 확인한다.
만약 이것이 된다면, 현재 local에서 Bastion으로 연결을 성공한 것이다.
주의해야 할 점은 그 다음이 bastion에서 private subnet의 연결이라고 생각할 수 있는데 아니다. Bastion은 그에 대한 통로를 뚫어주는 것 뿐 중간 매개체 역할을 하는 것이 아니다. 때문에 앞서 말했던 것처럼 명령을 local에서 bastion이 아닌 private subnet으로 직접 보낸다. 지금부터는 Local에서 Private subnet으로 연결하기 위한 Key Pair를 생성한다.
마찬가지로 키를 하나 생성하고, 이제 private instance를 하나 만든다.
여기서 이미 VPC 안의 private subnet이 있는데 왜 인스턴스를 만드는지 잠깐 짱구같은 생각을 했다. 우리가 처음 만들었던 VPC의 private Subnet 중 하나에 지금 만드는 private 인스턴스를 할당해주면 된다.
당연히 아까 만들어 둔 local-to-private 키를 적용해준다. 또한, bastion의 보안 그룹 추가도 잊지 말자.
bastion-private-instance라는 이름으로 private instance를 생성해줬고, 이제 local에서 접근이 가능한지 테스트 해보자.
하지만 bastion에서 만들어 둔 private instance로 접근하려니 뭔가 접근 문제가 발생한다. Private EC2에 SSH 접근을 위해서는 Key pair가 필요하기 때문이다. 아무래도 private instance 해당 키 페어를 알 방법이 없기 때문인듯.
Bastion의 인스턴스에서 아까 다운로드 받았던 local-to-private.pem을 복사해서 만들어준다. 그 후
읽기 권한을 주면, 위와 같은 명령어로 private instance에 접속이 가능하다. 10.0.3.130은 private의 private IP 주소다.
이제 모든 걸 다 확인했으니 로컬에서 private instance로 bastion을 통해 접근해보겠다.
우선 터미널 2개 중 1개에
ssh -i local-to-bastion-1.pem -N -L 33322:10.0.3.130:22 ec2-user@{bation IP} 와 같이 명령어를 실행 후 그대로 둔다.
그 후 또다른 터미널 1개에
ssh -i local-to-private-1.pem -p 33322 ec2-user@localhost
명령어를 넣어주는데, 아래와 같은 오류가 발생한다.
내용은 원격 호스트 식별 정보가 변경되었으며 기존에 등록되어 있는 RSA key가 다르다는 것. 누군가 기존 접속 정보를 바꿔 가로채는 man-in-the-middle attack에 주의하라는 경고문이다. 아마 수업에서 진행했을 때 host의 정보가 남아있는 듯 하다. 나의 경우는 7번 줄의 호스트가 문제가 있다고 알려준다.
33322 포트를 동일하게 수업 시간에 사용했다.
vi /c/Users/NT551XCJ/.ssh/known_hosts을 사용해서 6, 7번째의 host를 삭제해줬다.
접속이 완료되었다.
하지만 문제가 발생한다. ping google.com을 입력하면 요청이 정상적으로 이뤄지지 않는다.
NAT Gateway/Instance
지금 우리가 하고자 하는 건, private instance에서 외부로 나가고 싶은 상황이다. 지금까지 해왔던 SSH Tunneling은 외부에서 private Instance로 접근하고자 하는 목적이었다. 이를 위해 VPC 내부 subnet 내 모든 서버가 외부와 아웃바운드(단방향)로 접근 가능하도록 열어주는 Gateway가 필요하다.
NAT GateWay는 Private EC2로부터 온 네트워크 패킷을 재작성(IP 변조)하여, 외부와 대신 통신해준다.
NAT Instance를 생성할 때, Source/Destination Check 설정을 무조건 꺼야한다. 설정이 켜져있다면, NAT가 통신할 때 사용하는 IP와 실제 End System의 IP가 달라 에러가 발생한다.
EC2 인스턴스에는 기본적으로 "Source/Destination Check" 설정이 켜져있다. 이 설정이 켜져 있으면, 인스턴스는 자신이 전송하거나 수신하는 트래픽의 출발지(Source)와 목적지 IP 주소가 자신의 IP 주소와 일치해야만 통신을 허용한다.
다시 우리의 문제 지점으로 돌아와서,
우리는 현재 NAT GateWay를 사용하지 않으면 안 되는 시점에 도달해있다. 아웃바운드(내부에서 외부로)를 가능케 하기 위해 NAT Instance를 만든다.
우선, NAT Instance 역할을 할 EC2 Public을 하나 만든다.
AWS에서 NAT Instance보다 NAT GateWay를 공식화했단다. 사실 수업할 때 gateway가 존재하는 걸 확인하고 실습할 때 혼자 써보려 했는데... 매우 비싸다고 한다. 큰일 날 뻔 했다.
커뮤니티 버전의 NAT 인스턴스를 사용해준다. Key Pair는 local-to-bastion key를 할당해준다. 우리가 만들었던 public sunbet 중 하나와 연결해주고,
HTTP, HTTPS 각각 우리가 만들어뒀던 VPC의 CIDR로 정의한다.
이후 인스턴스 메인 화면에서 인스턴스 설정 -> 소스/대상 확인 변경을 클릭해 Source/Destination을 비활성화(중지)해준다. 이를 통해 NAT 인스턴스가 다른 인스턴스를 대신해서 트래픽을 라우팅 할 수 있다.
그 다음, Private subnet의 라우팅 테이블을 하나 생성한다. 이 때, 0.0.0.0/0 트래픽일 때 NAT Instance로 전달되도록 라우팅을 추가해준다. (명시적 서브넷 연결을 통해 private subnet과 연결해준다.)
이제 모든 게 완성되었으니 ping을 다시 날려보지만, 작동하지 않는다. NAT Instance EC2의 SG(보안 그룹)의 인바운드 규칙에 모든 ICMP 요청에 대해 풀어주어야 한다고 한다.
ICMP는 Internet Control Message Protocol로, 인터넷 제어 메시지 프로토콜이다.
우리가 테스트 해 볼 때 사용하는 Ping은 ICMP 메시지로 원격지 시스템이 도달 가능한지 확인할 수 있는 도구다.
정처기에서 봤던 Ping은 DDoS 공격 등을 하려 할 때, 공격할 대상을 검색하는 용도, 대량의 핑을 공격에 사용하기도 한다. 그래서 대다수의 PC는 보안 관계상 Ping을 받아도 응답을 보내지 않는다.
그래서 우리는 모든 ICMP 요청에 대해서 허용하도록 만들어준다. 인바운드 규칙은 인스턴스 메뉴 -> 보안 그룹 -> 이 곳에서 해당 인스턴스의 보안 그룹을 클릭하면 인바운드 규칙을 수정할 수 있다.
설정을 완료하고 다시 ping을 날려보면, 잘 된다!
아... 잊을 뻔 했는데 무조건 인스턴스, VPC(라우팅 테이블, IGW), 키 페어 등 중지/삭제 해주자.
'Programming > Web' 카테고리의 다른 글
[Next.js] Next.js Routing 이모저모 (0) | 2024.05.29 |
---|---|
[Servlet & Jsp &DB] 2초마다 변하는 배너 만들기 (0) | 2023.06.16 |
[Servlet & JSP] get, post 만들기 (0) | 2023.06.16 |
JavaScript Tutorial (0) | 2023.06.16 |
Web 시작 (0) | 2023.06.16 |