[F-Lab 모각코 챌린지 13일차] Nginx, HTTPS

부추·2023년 6월 13일
0

F-Lab 모각코 챌린지

목록 보기
13/66

TIL

  1. Nginx 이용해서 포트포워딩 후 핸드폰 셀룰러 데이터로 노트북 서버에 접속해보기
  2. HTTPS 사용 이유, TLS/SSL handshaking 과정.



1. Nginx 실습

1-1. 초간단 배경지식 : 공인/사설IP, NAT, 포트포워딩

IPv4는 표현할 수 있는 주소가 약 43억개(32bit)로, 21세기 지구촌의 모든 전자기기를 각각의 IP 주소로 표현하기엔 모자라다. 주소를 표현하기 위해 128비트를 사용하는 IPv6가 등장했지만, 현재 구축되어있는 IPv4 세계를 바꾸기 위해선 천문학적인 비용이 들기 때문에 기존 IPv4의 수명을 늘리는 여러가지 방식들이 고안되고 있다.

그 중 하나가 사설IP와 공인IP를 이용한 NAT와 포트포워딩이다. 말한 것처럼 존재하는 모든 기기에 고유한 IP 주소를 붙이는 것은 주소의 낭비가 심하므로, 하나의 네트워크 단위로 네트워크 내부에서만 유효한 사설 IP를 할당하는 방법을 이용한다.

공인 IP주소는 전세계 IP주소를 관리하는 공식 기관이 관리한다. 공식 기관이 각 나라에 특정 범위의 IP 주소를 할당하면, 또 각 나라의 공식 기관이 나라의 인터넷 서비스 제공자들에게 일정 범위의 IP주소를 할당하고, 서비스 제공자들이 서비스 구매자들에게 IP를 할당하는 식으로 작동한다. 요컨데 특정 공인 IP 주소를 가진 네트워크 기기는 전 세계에 오직 1개이다.

보통 이렇게 공인 IP 주소를 가진 기기는 서버 컴퓨터를 제외하면 L3 스위치 혹은 라우터, 가정이나 회사의 공유기 등 하나의 LAN을 이루는 작은 네트워크 단위인 경우가 많다.

사설 IP주소는 이런 네트워크 단위 내에서 각 기기를 구분하기 위해 사용하는 내부 IP 주소이다. 같은 공유기를 쓰는 노트북이나 핸드폰 등의 네트워크 기기가 가진 공인 IP 주소는 같지만, 각각이 네트워크 안에서 가진 사설 IP 주소는 다르다. 사설IP는 같은 공인IP를 사용하는 네트워크 내부에서 겹쳐선 안되지만 다른 네트워크를 사용하는 기기들과는 겹쳐도 된다. 같은 네트워크 안에서 서로를 구분하기 위해 사용하는 주소이기 때문이다.


문제는 네트워크 내의 기기가 네트워크 바깥과 통신할 때 발생한다. 사설 IP 주소를 가지고 어떻게 바깥과 통신할까?

바깥 네트워크에 요청을 보낼 때, 사설 IP주소를 가진 내부 기기는 자신이 속한 네트워크의 공인 IP 주소를 달고 나간다. 이것을 NAT(Network Address Translation)라고 한다. 요청에 대한 응답을 받을 땐 라우터나 공유기가 요청 기록을 토대로(이때 포트번호를 포함해서 기기를 구분하는 NAPT가 사용되는데 관습적으로 NAT라고 부르는듯) 방금 전 요청을 보낸 기기에게 응답을 전달한다.

더 큰 문제는 바깥에서 요청이 들어올 때다. 위의 그림 예시에서 123.123.123.123:80에 요청이 들어왔다고 해보자. 공유기 1은 내부에 있는 6개의 네트워크 기기 중 어떤 기기에게 해당 요청을 전달해야할까? 이 때 사용하는 것이 포트포워딩이다. 사전에 '특정 포트로 들어온 요청은 네트워크 내에 특정 사설IP 주소를 가진 기기에게 전달해주자' 라고 정해놓는 것이다. 포트 번호를 이용해서 내부 기기로 패킷을 이동시키는 과정이므로, "포트포워딩"이라는 용어는 적절한 것 같다.

그림을 보자. 사전에 공유기 포트포워드 설정을 "나에게 온 80번 요청은 192.168.0.20:80으로 보내자" 라고 설정하면 요청 패킷은 주황색 화살표의 경로로 이동한다. 물론! 내부 네트워크 기기의 어떤 포트로 정해줄 것인지 역시 설정할 수 있다. 이 때 123.123.123.123의 공인 IP 주소를 가진 공유기에게 직접적으로 요청이 들어온 포트번호(예시에선 80번)을 외부 포트, 패킷을 전달할 내부 네트워크 기기에 포트 번호를 내부 포트라고 한다.


위 개념을 실제로 실습해보겠다. 실습 과정은 다음과 같다!

  1. nginx로 노트북 컴퓨터에 웹서버를 설치하고 특정 포트(5270)에 nginx 서버를 열어두겠다.
  2. 우리집 공유기에 포트포워딩 규칙을 설정하겠다. 대충 55555번 포트로 들어온 요청을 노트북 컴퓨터의 nginx 서버가 돌아가는 5270번 포트로 이동시키겠다.
  3. 휴대폰 셀룰러 데이터로 "{우리집 공유기 IP주소}:55555" URL로 접속해보겠다.



1-2. Nginx ?!

1) 초초초간단 nginx 설명

Nginx란? 웹서버 프로그램이다. 특정 IP 주소를 가진 컴퓨터의 특정 포트에 nginx 서버를 열 수 있다. 그럼 컴퓨터는 해당 포트로 들어온 사용자의 요청에 응답을 내리는 서버로 동작한다. 근데 보통 생각하는 웹 어플리케이션 서버처럼 동적 페이지를 제공하는 등의 대단한 역할을 할 수 있는건 아니고, 그냥 정적 컨텐츠를 내려보내줄 뿐이다.

WAS 시대에 이런 웹 서버를 사용하는 이유는 로드 밸런싱, 리버스 프록시 등이 있다는데 그것은 나~중에 웹서버 관련해서 공부할 때 살펴보도록 하고! 눈 앞에 닥친 과제를 하자.

2) 설치

내 컴퓨터 환경은 .. hombrew랑 그를 이용한 mysql 하나가 깔린 맥북이다. (끝)

가장 먼저 brew를 이용해 nginx를 설치했다.

$ brew install nginx

수십 초를 기다리면 다운로드가 완료되고, configuration 파일의 위치를 알려준다. 아마 버전 차이 탓일 것 같은데, 인터넷으로 찾은 통상적 config파일의 위치(/usr/etc/nginx)랑 달랐다.

/opt/homebrew/etc/nginx/nginx.conf

나의 경우는 위와 같았다.

하여튼, Nginx가 성공적으로 설치되었으므로 실행시켜보자.

$ brew services start nginx

커맨드를 입력하면 맥북의 경우 백그라운드에서 실행될 수 있는 프로그램 어쩌고 알림이 뜨는데 무시하고, 크롬 주소창에 localhost:8080으로 접속해보자. 포트 번호가 8080인 이유는 nginx의 초기 설정 포트 번호가 8080이기 때문이다. 이 설정은 당연히 cofig 파일에서 바꿀 수 있다.

nginx 서버가 잘 ! 띄워졌다. 내 컴퓨터의 IP주소(localhost, 127.0.0.1)에 해당하는 포트번호(8080)로 네트워크 통신을 시도하면 잘 된다는 것을 실제로 확인했다.


3) configuration

이제 configuration을 진행해보자. nginx가 알려준 configuration 파일로 이동하자. 에디터로는 vim을 쓸 것이다.

$ vi /opt/homebrew/etc/nginx/nginx.conf

좍좍좍 내리다보면 http 부분이 나오는데, 여기서 server.listen 항목이 nginx 서버가 열린 포트번호이다. 원하는 번호로 바꾸자.

나같은 경우는 내가 좋아하는 가수의 생일인 5270으로 바꿔줬다.

그리고 기본으로 나오는 "Welcom to nginx!" 외 그 문구들도 맘에 안든다. index.html을 수정하고 싶다. index.html이 존재하는 디렉토리로 이동하자.

$ cd /opt/homebrew/Cellar/nginx/1.25.0/html

참고로 하위 디렉토리는 당연 버전마다 다르며, 이는 설치할 때 설치완료 후 내뱉는 설정 로그드를 참고하거나 $ nginx -V를 통해 정보를 확인해야 한다. ls를 통해 확인해보면 index.html 파일이 있다. 입맛에 따라 index 페이지 문구를 수정하자.


그 뒤, nginx 서버를 재시작했다.

$ brew services restart nginx

이제 "localhost:{방금 설정한 포트번호}"로 접속해보면!



2-3. 포트포워딩 해보기!!

우리집 공유기에 포트포워딩 규칙을 설정하자. 우리집 공유기의 IP주소를 알아야한다. 네이버에 냅다 내 IP 주소 확인을 검색해도 되고, 터미널에서 확인할 수도 있다.

$ curl ifconfig.me

그 뒤 인터넷 브라우저에 해당 IP 주소를 입력하면 공유기 설정 화면으로 들어갈 수 있다. 설정의 NAT관리, 포트포워드 설정에 들어가자!

그리고 내부 IP주소, 외부 포트, 내부 포트를 위와 같이 수정했다. 외부 포트는 그냥 내 마음대로 정했고, 내부 포트는 nginx 서버를 열었던 5270번이다. 내부 IP 주소는 nginx 서버가 열린 이 노트북이 공유기 범위 내에서 가지는 사설 IP 주소이다.

정리하면, 공유기 IP 주소의 외부 포트 55555번 포트로 들어온 요청은, 내부 IP 주소의 내부 포트 5270 번으로 포트포워딩 해주세요~ 정도이겠다. 설정 완료를 하자. 그리고 휴대폰 와이파이 연결을 끊고, "{공유기 IP주소}:55555"로 접속하자.

잘 됐다! 셀룰러 데이터를 이용한 내 휴대폰에서 내 노트북의 웹서버에 접속되는 과정을 그림으로 나타내보았다.
오른쪽에 192.168.x.x의 IP 주소를 가진 다른 기기들은 우리집 와이파이를 이용하는 TV, 데스크탑, 아이패드 등 다른 기기들이다.

nginx 웹서버의 응답은 공유기 IP 주소인 121.165.213.185를 달고 같은 경로를 통해 나간다. 이때 NAPT가 이용되는 것이다.




2. HTTPS에 관하여

2-1. HTTPS 사용하는 이유

오늘날 많은 사용하자가 이용하는 사이트에서 http를 사용하는 경우는 거의 없다(http가 무엇인지는 알겠지? 웹 서버 자원에 대한 응답-요청을 위해 사용하는 프로토콜이다). 네이버를 가도, 구글을 가도 URL schema를 확인하면 모두 "https"가 가장 앞에 붙어있다. 일부러 "http://" 라고 URL의 맨 앞에 붙여도 다시 https:// 프로토콜을 사용하는 주소로 리다이렉트 될 뿐이다. HTTPS는 HTTP에 Security의 S가 추가된 프로토콜로써, 조금 더 secure한 HTTP 통신을 지원하는 프로토콜이다. 뭐 대충 알겠지만, 왜 HTTPS가 선호될까?

1) HTTP는 보안에 취약

http는 평문 통신이다. 클라이언트와 서버가 데이터를 주고받을 때 별다른 암호화를 하지 않는 raw 데이터로 통신한다는 뜻이다. 전송 과정의 패킷을 까면 평문 메세지가 그대로 노출된다. 아이디와 비밀번호가 담긴 로그인 폼 정보를 패킷 전송과정에 참여하는 모두가 읽을 수 있는 환경에 보내는 것은 상당히 위험하다.

또한 공격자가 응답/요청 과정에 있는 패킷을 탈취해서 malfunction 데이터를 추가할 수도 있는데, 이를 받은 서버나 클라이언트는 이게 정말로 상대방이 보낸 pure data가 맞는지 알지 못한다. 서버로부터 신뢰할 수 없는 데이터를 받는다는 뜻이다.

2) 검색 엔진의 가산점

가장 대표적인 검색 엔진인 구글의 경우, https 프로토콜을 지원하는 사이트의 경우 검색 엔진 상위에 노출될 수 있도록 해당 사이트에 가산점을 부여한다. PV를 올려 광고수익을 얻어야 하는 대부분의 인터넷 사이트들은 이런 검색 엔진의 검색 결과 상위에 노출될 수 있도록 https를 지원한다.

물론 https를 지원하는 사이트가 청렴하고 신뢰성 높은 자료만을 이용한다거나 그러는 것은 아니다. 하지만 통신 과정에서 암호화를 이용한다는 것은 데이터를 요청 보내는 클라이언트 입장에서도 중요한 사항이므로 웬만하면 https 지원 사이트를 이용하는 것이 좋다.


2-2. TLS / SSL : 4계층과 3계층 사이에 추가

HTTPS 프로토콜을 이용하면, 통신 데이터를 프로그램이 직접적으로 이용할 수 있도록 하는 4계층과 전송 계층인 3계층 사이에 보안 관련 작업이 일어나는 계층이 추가된다. 이를 Secure Sockect Layer의 약자로 "SSL"이라 부른다. TLS는 Transport Layer Security의 약자로 SSL의 업그레이드된 보안 프로토콜이다. [오늘날 https에서 사용되는 보안 프로토콜]은 엄밀히 말하자면 TLS지만, 관습적으로 SSL이라고 부르기도 하는 모양이다. 그러나 정확한 용어 사용을 지향하기 위해 TLS라고 부르겠다.

HTTP와 HTTPS의 차이를 단적으로 보여주는 그림이다. 기존의 평문 통신을 암호화 레이어를 추가해 암호화 통신으로 바꾸는 과정(레이어)이 추가된 모습이다.

TCP 연결을 위해 3-way handshake가 일어난 직후, 서버와 클라이언트간 TLS 연결 역시 확보하기 위해 TLS handshake가 일어난난다. 해당 과정이 어떻게 구현되는지 과정을 살펴보자.


2-3. HTTPS

1) 대칭키와 비대칭키

  • 대칭키 (symmetric key) : 암호화(encryption)와 복호화(decryption)에 같은 키가 사용된다. 빠른 암호화 및 복호화가 가능하지만, 대칭키가 노출되면 참사가 일어난다.
  • 비대칭키 (asymmetric key) : 암호화와 복호화에 다른 키가 사용된다. 보통 암호화에 사용하는 키를 공개 키(public key), 복호화에 사용하는 키를 개인 키 혹은 비밀 키(private key)라고 한다. 보통 공개 키는 말 그대로 모두가 볼 수 있게 public으로 열어놓고, 개인 키는 소유주만이 가지고 있다 공개 키로 암호화된 데이터를 복호화할 때 사용한다. 공개 키로 암호화한 것은 개인 키로만 복호화할 수 있고, 비밀 키로 암호화한 것은 공개 키로만 복호화할 수 있다. 공개 키는 전송할 데이터를 암호화할 목적으로, 개인 키는 데이터의 무결성 및 신원확인을 위한 목적으로 주로 사용한다. 대칭키보다 암호화/복호화 과정이 느리다.

비대칭키를 이용한 암호 통신 과정은 간단하다. A와 B가 통신을 한다 가정하자. B는 자신의 공개 키를 세상에 공개한다. A는 공개된 B의 공개키로 자신이 보낼 데이터를 암호화한다. B의 공개키로 암호화된 데이터는 B의 개인 키로만 복호화할 수 있기 때문에, B가 개인 키를 어디 흘리지 않는 한 A가 암호화한 데이터는 오로지 B만 복호화할 수 있다.

그치만 비대칭키를 이용한 암호화/복호화는 느리다. HTTP 통신을 하면서 얼마나 많은 데이터를 암호화 해야 하는데, 모든 데이터를 일일이 공개키로 암호화하고 있으면 컴퓨터 리소스를 암호화에 필요 이상으로 소모하게 된다. 따라서 대칭키를 사용하는게 좋지만, 또 통신 참여자 둘만 공유하는 대칭키를 형성하기란 쉽지 않다. 대칭키를 전송하는 과정에서 또다른 공격이 있을 수 있기 때문이다. 암호화에 사용할 대칭키를 평문으로 보낸다면... 우리집 비밀번호를 이마에 써붙이고 다니는 것이나 마찬가지이다.

각각의 장단점을 취하기 위해 비대칭키 암호화를 이용한 대칭키 공유하는 방법이 사용된다. '실제 데이터 암호화에 사용할 대칭키'를 공유하기 위해 대칭키 자체를 비대칭키로 암호화해서 상대방에게 전송하는 것이다.


2) CA(Certificate Authority)

설마 위의 설명을 보고 완벽하겠군! 하고 생각한건 아니길 바란다. 아래 상황에선 어쩔거냐?

클라이언트 A와 서버 B가 비밀 통신을 하려고 한다. A는 암호화에 사용할 대칭키를 만들었다. 이 대칭키를 암호화해서 B에게 보내기 위해 B에게 공개키를 요구한다. B는 자신의 공개키를 A한테 보내주려고 하는데!!!!
중간에 나쁜놈 C가 패킷을 갈취해서 B의 공개키를 자신의 공개키로 바꿔서 다시 A에게 보내줬다.
아무것도 모르는 A는 받은 C의 공개키가 B의 공개키라고 철썩같이 믿어서 C의 공개키로 대칭키를 암호화한 뒤 전송한다. C는 A가 보낸 패킷을 갈취해서 자신의 개인 키로 복호화해 대칭키를 얻어냈다. 대칭키가 노출되는 참사가 일어나고 말았다..

여기서 문제의 시작은 A가 공개 키랍시고 받은 키가 실제 B의 공개키가 아니었다는 부분이다. 말하자면 데이터의 무결성이 흠집난 것이다. 지금 받은 공개키 데이터가 B의 것이 확실한지, 신뢰할 수 있는 근거가 필요하다. 이 때 등장하는 것이 CA, certificate authority이다.


CA는 공식 인증 기관이다. 신뢰할 수 있는 자신의 공개 키를 사전에 네트워크 세상에 공개한다. 우리가 http 통신에 주로 사용하는 브라우저에는 CA의 공개키가 내장되어있다. CA가 암호화한 데이터가 CA의 공개키로 복호화된다면, 해당 데이터는 CA가 보증한 데이터가 된다. 따라서, CA에게 인증받았다는 것을 증명하기 위해 서버는 CA의 개인키로 암호화된 인증서를 사이트 앞에 걸어놓는다.

CA는 자신에게 인증서를 요청한 서버에게 인증서를 발급하는데, 과정을 살펴보자.

  1. 서버는 CA에게 자신의 정보와 공개 키를 제출한다.
  2. CA가 심사를 마치고, 해당 정보를 자신의 비밀 키로 암호화해 인증서를 발급한다. 이 과정을 CA의 전자서명이라고 부르기도 한다.
  3. 서버가 해당 인증서를 사이트 앞에 걸어놓는다.
  4. 서버에 요청을 보내려는 클라이언트는 서버 앞에 걸린 인증서를 해당 CA의 공개키로 복호화한다. (공개키는 브라우저에 내장되어 있다는 것을 상기하자)
  5. 이렇게 받게된 서버의 공개키는 CA에게 인증받은 신뢰할 수 있는 공개키이다.

이것이 '대칭키를 사용하기 위한 공개키를 신뢰하기 위한 인증서의 발급과정'이다. (어렵다)


3) 과정 정리

TCP handshake가 일어난 직후, TLS handshake를 통한 대칭키 공유 과정을 CA의 과정을 포함해서 살펴보자. 클라이언트 A, 서버 B, 인증기관 C가 협업한다.

  1. HTTPS를 지원하고자 하는 서버 B는 C에게 인증서를 요청한다. B의 사이트 정보와 B의 공개키를 제출한다.
  2. C는 B가 제출한 정보를 심사한 후, 해당 정보를 자신의 개인 키로 암호화하여 인증서를 제작하여 B에게 돌려준다.
  3. B는 C로부터 받은 인증서를 사이트 앞에 내건다. // 여기까지가 사전 준비!
  4. A가 B에 HTTPS 접속 요청을 한다. A는 B 사이트에 걸린 인증서를 받는다.
  5. A의 브라우저가 내장된 CA의 공개키로 인증서를 복호화하여 B의 공개키를 얻는다.
  6. A는 대칭키 생성에 필요한 데이터를 B의 공개키로 암호화하여 B에게 보낸다.
  7. A와 B는 방금 공유한 데이터를 바탕으로 대칭키를 생성한다. 이 대칭키를 토대로 서로가 통신한다.

만화는 그냥 가져와봤다. 나름 만화라고 그래도 보기 편하다.


전반적인 과정은 위와 같지만, cloudflare에 설명된 자료를 토대로 조금만 더 자세히 파고들어보자.

각 화살표를 위에서부터 1~6번이라고 하자.

  1. TCP 3-way handshake 과정의 첫번째, 클라이언트의 SYN=1 세그먼트 전송
  2. 두번째로 서버의 SYN, ACK=1 세그먼트 전송
    3.클라이언트의 SYN=1로 3-way handshake 종료, TLS handshake 시작. ClientHello : 클라이언트의 TLS 버전, 클라이언트가 지원하는 암호 프로토콜의 목록, 클라이언트의 무작위 문자열이 포함
    4.ServerHello : 서버의 인증서, 서버가 선택한 암호 프로토콜, 서버의 무작위 문자열을 담아 전송
  3. 클라이언트의 작업
    • Certificate : 클라이언트가 내장된 CA로 서버의 인증서 복호화 및 서버 인증. 서버의 공개키 얻음
    • ChangeCipherSpec : 클라이언트가 대칭키 생성에 필요한 예비 마스터 암호 생성 후 서버의 공개키로 암호화 후 전송
  4. ChangeCipherSpec / Finished : 3번의 무작위 문자열, 4번의 무작위 문자열, 5번의 예비 마스터 암호를 통해 서버와 클라이언트가 대칭키 생성. 서로 완료 메세지를 생성된 대칭키로 교환 뒤 안전한 대칭키가 생성되었음을 확인




REFERENCE

https://kibbomi.tistory.com/219

https://velog.io/@davelee/mac%EC%97%90-nginx-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0#nginx-%EC%84%A4%EC%B9%98-%EA%B2%BD%EB%A1%9C-%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD

https://velog.io/@dbwlgns98/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-CS%EC%A0%95%EB%A6%AC-2%ED%83%84-%ED%8F%AC%ED%8A%B8%ED%8F%AC%EC%9B%8C%EB%94%A9-%EC%8B%A4%EC%8A%B5#%EC%8A%A4%EB%A7%88%ED%8A%B8%ED%8F%B0%EC%9C%BC%EB%A1%9C-%EC%8B%A4%ED%96%89

https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/

https://steady-coding.tistory.com/512

https://velog.io/@chocoallergie/F-Lab-%EB%AA%A8%EA%B0%81%EC%BD%94-%EC%B1%8C%EB%A6%B0%EC%A7%80-11%EC%9D%BC%EC%B0%A8-HTTPS-SSL-TLS

profile
부추튀김인지 부추전일지 모를 정도로 빠싹한 부추전을 먹을래

0개의 댓글