저번 네트워크 기본만 알았지만, 이번엔 네트워크를 보안을 위해계층별로 더 깊게 배워보는 시간을 갖겠다.
기본적으로 옛날엔 발신자 수신자 사이에 회선 교환 방식으로 사람이 수동으로 해줬다. 하지만 연결 됐을때 멀티라든지 즉시성이 떨어지는 한계를 맞이해 패킷 교환 방식으로 1969년도에 바뀌었다. 패킷이라는 단위로 데이터를 잘게 나누어 전송하는 방식으로 소포보내듯이 목적지, 출발지가 정해져 특정 회선 하나가 한 연결을 도맡는 것이 아니게 돼 한계를 극복했다. 소포가 보내지는 그 주소는 우리가 흔히 아는 인터넷 프로토콜(IP)이다.
수많은 노드(서버)들이 그 복잡한 인터넷 망을 지나 어떻게 클라이언트와 통신할 수 있을까? 제대로 정해진 주소 규칙이 있기 때문에 가능하다.
- IP는 지정한 IP 주소(IP Address)에 패킷(Packet)이라는 통신 단위로 데이터 전달한다. Packet은 pack과 bucket이 합쳐진 단어로 데이터를 담을 수 있는 통신 속 단위인데, 택배에서 하나의 박스라 생각하면 된다.
그래서 서로의 약속 하에 같은 규격으로 통신해 훨씬 편한 통신이 가능해졌다.
하지만 다 좋은 건 아니다. 비연결성, 비신뢰성 등의 한계가 있다.
우리가 채팅을 하여 메시지를 보낼때 어떤 일이 일어나는지 알아보자1. 프로그램이 메시지 내용을 0, 1의 인공어로 생성
2. HTTP 메시지를 Socket을 통해 전달
3. 메시지 데이터를 포함한 TCP 정보 생성
4. TCP 데이터를 포함한 IP 패킷 생성
5. LAN 카드와 같은 물리적 계층을 지나기 위해 이더넷 프레임 워크에 포함되어 서버로 전송
여기서 TCP/IP 패킷이란 기존 IP 패킷에 'TCP 세그먼트'를 추가하여 보완한 패킷이다. TCP 세그먼트에는 IP 패킷의 출발지 IP와 목적지 IP 정보를 보완할 수 있는 출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보 등을 포함한다.
전송 계층엔 다양하지만 크게 TCP, UDP로 나뉜다.
장치들 사이에 논리적인 접속을 성립하기 위하여 3 way handshake를 사용하는 연결지향형 프로토콜
걍 3번 왔다 갔다해서 비연결성, 비안정성 없앰
IP에 PORT, 체크섬 필드 정보만 추가돼 TCP보다 단순화된 프로토콜
커스터마이징 가능
TCP 특징과 비교해 신뢰성은 낮지만 3 way handshake 방식을 사용하지 않기 때문에 TCP와 비교해 빠른 속도를 보장
TCP완 다르게 가벼운 편이라 신뢰성보다 연속성이 중요한 서비스면(ex) 스트리밍
) UDP를 쓰는 게 낫다.
위 사진을 보면 OSI 7계층 모델, TCP/IP 4계층 모델이 있다.
컴퓨터와 키보드로만 통신하던 시절 통신의 한계를 맞이해 표준화를 통하여 어떠한 데이터가 왔을 때 호환되기 위함과 오류 발생 시 어느 파트의 오류인지 쉽게 설명 위해 나왔다. TCP/IP 4계층 모델은 실무적으로 이용할 수 있도록 현실에 맞춰 단순화된 모델이다. 7계층 봐라 얼마나 어렵냐
계층을 지나며 데이터에 계층 만의 헤더를 붙이고 물리 계층을 지나 데이터가 '캡슐화'된다. 그러면 수신자는 '역캡슐화'가 일어나 어떤 데이터인지 인식한다.
어떤 것이 있는 지만 참고
우린 프엔이니까 어플리케이션 계층(응용 계층)을 잘 알아야겠지?
네트워크의 구조를 봤을 때 응용 계층에서 많이 쓰이는 프로토콜이 있다. 바로 그 유명한 HTTP(S)! 정의 같은 건 배웠으니 특징에 대해서 깊게 들어가보자.
무상태: 클라의 상태를 보존 X, 사진에서 보이듯이 HTTP는 데이터를 유지하지 않는다.
왜!?
단점이 있음
연결을 유지해서 계속 렌더링 된다면? 서버 자원의 소모가 심해짐, 그래서 HTTP에서는 요청을 주고받을 때만 연결을 유지하고 응답을 주고 나면 TCP/IP 연결을 끊는다.
또한 비연결성 한계로 HTTP는 TCP 연결 특성상 하나의 요청을 위해 연결 - 요청 및 데이터 수신 - 종료를 하나 하나 데이터마다 받아와 오래 걸렸는데 HTTP에서 최적화를 이뤄 각각의 자원을 요청 및 응답이 다 되면 종료하는 'HTTP 지속 연결'로 한계를 돌파했다.
HTTP Secure의 약자로, 단어 뜻 그대로 기존의 HTTP 프로토콜을 더 안전하게(Secure) 사용할 수 있음을 의미
제 3자가 패킷을 못보도록 암호화
왜 써? 만약 로그인 한다 치면 아이디와 비번 모두 데이터로 전송되는데 HTTP로만 한다면 암호화가 되지 않아 패킷을 중간에 열 수 있으면 그런 정보들이 유출되기 때문에!
HTTPS는 HTTP에 서버와 클라이언트간의 CA의 인증서를 통해 서버를 인증하는 과정과 CA 인증서 위에 데이터를 암호화하는 과정을 수행하는 프로토콜, TLS(SSL)를 더한 것이다.
암호화를 하는데 '키'라는 것으로 데이터를 가린다. 2가지가 있다. 암호화와 복호화를 하는데 같은 키면 '대칭 키 암호화 방식', 다른 키면 '공개 키(비대칭 키) 암호화 방식'
로컬에 CA로 mkcert
를 사용할거기에 mkcert
를 설치해서 적용해야한다. 맥 기준, 도메인으로 localhost라고 가정
// 0. homebrew로 mkcert설치
brew install mkcert
// 1. mkcert 설치 후 로컬을 인증 기관으로 추가(시스템 루트 경로에 설치)
mkcert -install
// 2. 로컬 환경에 대한 인증서 발급
mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
// 3. cert.pem, key.pem 파일이 생성됨, key.pem의 경우 암호이기에 깃 커밋 X, 암호처럼 다루기
Node.js 환경에서 HTTPS 서버를 작성하기 위해서는 https 내장 모듈을 이용. express.js를 이용해 https 서버를 만들 수 있음
const https = require('https');
const fs = require('fs');
https
.createServer(
{
key: fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
cert: fs.readFileSync(__dirname + '/cert.pem', 'utf-8'),
},
function (req, res) {
res.write('Congrats! You made https server now :)');
res.end();
}
)
.listen(3001);
위랑 비슷한데 중간에 미들웨어 app.use
로 대체
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
https
.createServer(
{
key: fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
cert: fs.readFileSync(__dirname + '/cert.pem', 'utf-8'),
},
app.use('/', (req, res) => {
res.send('Congrats! You made https server now :)');
})
)
.listen(3001);
참고: ngrok로 HTTP로 만들어진 서버를 HTTPS 프로토콜로 터널링 가능! 나중에 해보자..?