1. 브라우저에서 URL을 해석한다.
2. DNS 서버에서 IP 주소 받아오기
3. ARP 프로세스 (서버 PC까지 이동하는 과정)
4. TCP 소켓 통신 (데이터를 주고받기 위해 연결, 해제하는 과정)
5. TLS/SSL handshake (암호화 통신을 위한 과정)
6. HTTP 통신 (전하고자 하는 실제 내용 요청, 응답)

브라우저에서 URL을 해석

예) https://www.goldfishhead.tistory.com:80/manage/newpost.html?type=post&key1=value1#top

https:// (프로토콜)

  • 클라이언트(요청하는 컴퓨터)와 서버(응답하는 컴퓨터) 간의 통신 규약이다.
  • http로 보내는 데이터 종류: html 문서, 이미지, 동영상, 오디오, 텍스트 등
  • https(http + secure)은 http의 통신 내용을 암호화한다.

www (호스트(2차 도메인))

  • 예) www, ftp(파일 송수신), mail(메일 송수신)

goldfishhead.tistory.com (도메인)

  • IP 주소에 해당하는 부분, 숫자로 이루어진 IP 주소를 기억하는 것은 어렵기 때문에 편의상 이름을 지정해준다.(DNS)
  • 사람이 읽을 수 있는 도메인 이름을 컴퓨터가 읽을 수 있는 IP 주소로 변환해주어야 한다.

:80 (포트 번호)

  • 표준 HTTP 포트(http는 80, https는 443)를 사용하면 포트 번호는 보통 생략한다.

/manage/newpost.html (기본 문서)

  • 웹 서버 내 자원(페이지)의 경로이다.
  • 위와 같은 방식은 이미 모든 수정이 끝난 html 파일의 물리적 경로이다. (예: 블로그)
  • 위와 같은 물리적 경로(서버 내 실제 경로)가 아닌 추상화하여 보여주는 방식도 존재한다.
    (예: 변경 가능한 내용이 포함된 페이지를 응답해야 할 경우 => /manage/newpost.html처럼 물리적 경로가 아니라 /manage/newpost 와 같은 추상화된 경로로 요청 시 서버 내에서 DB에서 정보를 불러와 html 페이지에 내용을 추가한 뒤에 요청한 사용자에게 보내주도록 할 수 있다.)

?type=post&key1=value1 (쿼리스트링)

  • 서버에 전달하는 추가 파라미터(정보)이다.
  • key=value 형식으로 전달한다.
  • '/'가 아닌 '?'로 구분하고 파라미터가 여러 개일 경우 '&'로 쌍들을 구분한다

#top (내부 경로(책갈피))

  • 페이지 자체에 다른 부분에 대한 북마크이다.
  • 북마크 된 지점에 위치한 내용을 보여주기 위해 브라우저에게 방향을 알려준다.(페이지의 윗부분 위치는 #top, 중간은 #bottom 으로 지정했을 경우 #bottom 이 붙어있으면 페이지 중간 위치로 바로 이동하도록 할 수 있다)
  • fragment identifier(부분 식별자)라고 해서 요청이 서버에 보내지지 않는다.

DNS 서버에서 IP 주소 받아오기

https://www.goldfishhead.tistory.com -> 123.123.11.321
사람이 읽을 수 있는 도메인 이름을 컴퓨터가 읽을 수 있는 IP 주소로 변환해주어야 한다.

  1. 브라우저는 도메인이 캐시에 들어있는지 확인한다.
  2. 캐시에 없다면 검색을 위해 gethostbyname 라이브러리 함수를 호출한다.
  3. gethostbyname은 DNS 통한 호스트명 확인을 시도하기 전 호스트명이 로컬의 hosts 파일에서 참조될 수 있는지 확인한다.
  4. 캐시와 hosts 파일 모두에서 호스트명을 찾지 못하면 gethostbyname은 네트워크 스택에 정의된 DNS 서버에 요청을 보낸다.(일반적으로 로컬 라우터나 인터넷 공급자의 캐시 DNS 서버로 보내진다)
    • DNS 서버가 같은 서브넷에 존재한다면 네트워크 라이브러리 DNS 서버에 대해 APR 프로세스를 거친다.
    • DNS 서버가 다른 서브넷에 존재한다면 네트워크 라이브러리 기본 게이트웨이 IP에 대해 ARP 프로세스를 거친다.

ARP 프로세스 (서버 PC까지 이동하는 과정)

ARP 란?

  • Address Resolution Protocol (주소 결정 프로토콜)
  • 네트워크 계층 주소와 링크 계층 주소 사이의 변환을 담당하는 'IP 프로토콜'이다.
  • 네트워크 계층에서는 IP 프로토콜을 사용하여 현재 나의 IP에서 상대방 IP로의 경로로 라우터를 거쳐 전송된다.
  • 하지만 실제적으로 우리 컴퓨터는 '랜카드'를 사용하여 네트워크에 연결되어 있기 때문에 3계층에서 2계층으로의 정보 전달을 위해서 MAC 주소가 필요하고 이를 위해 ARP 프로토콜이 필요하다.

ARP 과정

  1. 목적지 IP의 ARP 항목이 ARP 캐시에 있다면 라이브러리 함수는 다음의 형태로 결과를 리턴한다. 목적지 IP = MAC.
  2. 항목이 ARP 캐시에 없다면 라우트 테이블을 검색해서 목적지 IP 주소가 로컬 라우트 테이블의 서브넷에 존재하는지 봅니다. 존재한다면, 라이브러리가 그 서브넷에 속하는 인터페이스를 활용합니다. 없다면, 라이브러리는 우리 기본 게이트웨이의 서브넷에 속하는 인터페이스를 활용합니다.
  3. 선택된 네트워크 인터페이스의 MAC 주소가 검색이 된다.
  4. 네트워크 라이브러리는 데이터 링크 계층을 통해 ARP 요청을 보낸다.
  5. 송신자는 목적지 물리 주소가 필요하므로 물리 주소 요청을 위한 ARP 요청 패킷을 브로드캐스트로 전송합니다. 브로드캐스트를 하는 이유는 목적지 물리 주소를 모르기 때문에 모두에게 요청합니다. 요청 패킷에는 송신자 주소가 포함되어 있어서 응답할 수 있습니다.
  6. 모든 호스트와 라우터는 송신자가 보낸 ARP 요청 패킷을 수신합니다.
  7. 해당되는 수신자만 자신의 논리 주소와 물리 주소를 넣어 응답 패킷을 유니캐스트로 전송합니다.

TCP 소켓 통신

  1. 브라우저가 목적지 서버의 IP 주소를 받으면 거기서 호스트명과 포트 번호를 뽑아내서 socket이라는 이름의 시스템 라이브러리를 호출하고 TCP 소켓 스트림 ( AF_INET/AF_INET6 과 SOCK_STREAM )을 요청한다.

    • 이 요청은 먼저 TCP 패킷(세그먼트)이 제작되는 전송 계층으로 전달된다. 목적지 포트는 헤더에 더해지고, 출발지 포트는 커널의 동적 포트 범위 (리눅스의 ip_local_port_range) 에서 선택된다.
    • 이 패킷(세그먼트)은 추가적인 IP 헤더를 덧씌우는 네트워크 계층으로 보내진다. 현재 머신뿐 아니라 목적지 서버의 IP 주소도 담아 패킷을 만든다.
    • 패킷(데이터 그램)은 곧 링크 계층에 도착한다. 현재 머신 NIC(네트워크 인터페이스 컨트롤러, 랜 카드)의 MAC 주소에 게이트웨이(로컬 라우터)의 MAC 주소까지 포함한 프레임 헤더를 더한다. 전과 마찬가지로, 커널이 게이트웨이의 MAC 주소를 모르면, ARP 쿼리를 브로드캐스트 해서 찾아야한다.
  2. 패킷은 다음 중 하나로 전송될 준비를 마친다.

    • 이더넷
    • 와이파이
    • 무선 통신 네트워크
  3. 패킷은 로컬 서브넷을 관리하는 라우터에 도착하여 목적지 서버까지 이동하게 되는데, 이때 지나치는 각각의 라우터는 IP 헤더로부터 목적지 주소를 추출해내서 다음 단계로 이어준다.

  4. 이 송수신 동작은 TCP 연결 흐름에 따라 여러 차례 일어난다.

    • 연결할 때 (3 Way Handshake):
      • 클라이언트는 초기 순서 번호 (ISN, Initial Sequence Number) 을 선택한다.
      • 클라이언트는 ISN을 설정하는 중임을 나타내는 SYN 비트가 set된 한 패킷을 서버로 보낸다.
      • 서버가 SYN을 수신하고 수용가능한 상태인지 확인한다:
        • 서버가 자신의 ISN을 고른다.
        • 서버가 ISN을 설정하는 중임을 알리는 SYN 비트를 set한다.
        • 서버가 클라이언트 ISN + 1 을 ACK 영역에 붙이고 첫 번째 패킷을 확인했다고 알리는 ACK 플래그를 추가한다.
        • 클라이언트로 SYN + ACK 를 보낸다.
      • 클라이언트가 패킷을 하나 보내 연결을 확인해줍니다 (ESTABLISHED):
        • 응답 받은 클라이언트 ISN + 1 을 보고 연결이 성립된 것을 알 수 있다.
        • 클라이언트는 서버 ISN + 1 을 ACK 영역에 붙이고 ACK 필드를 set한다.
        • 서버로 ACK 를 보낸다.
      • 서버는 패킷을 하나 보내 연결을 확인해줍니다 (ESTABLISHED):
        • 응답 받은 서버 ISN + 1 을 보고 연결이 성립된 것을 알 수 있다.
        • 이제 요청자와 수신자는 안전하고 신뢰성있는 연결이 생성되었다고 판단하고 본격적인 통신을 시작할 수 있다.
      • 데이터가 다음과 같이 옮겨집니다:
        • 한 쪽에서 N개의 데이터 바이트를 보내면서, SEQ를 해당 숫자만큼 증가시킵니다
        • 반대편이 그 패킷 (혹은 연결된 여러 패킷) 을 받았다고 알리면, 상대로부터 마지막에 받았던 순서와 같은 ACK 값을 담아 ACK 패킷을 보냅니다
    • 연결을 끊을 때 (4 Way Handshake):
      • 닫는 쪽이 FIN 메세지를 보냅니다
      • 반대편이 FIN 메세지에 대해 ACK 응답을 보낸다. 그 후 데이터를 모두 보낼 때까지 잠시 타임아웃된다.
      • 데이터를 모두 보내고 통신이 끝났으면 연결이 종료되었다고 클라이언트에게 FIN 플래그를 전송한다.
      • 클라이언트는 FIN 메세지를 확인했다는 메세지(ACK)를 보낸다.
      • 클라이언트의 ACK 메세지를 받은 서버는 소켓 연결을 close한다.
      • 클라이언트는 아직 서버로부터 받지 못한 데이터가 있을 것을 대비해 일정 시간 동안 세션을 남겨놓고 잉여 패킷을 기다리는 과정을 거친다.(TIME_WAIT)

TLS/SSL HANDSHAKE

암호화 통신은 일반적으로 TLS/SSL 프로토콜을 사용하여 이루어지는데 TLS/SSL 암호화 과정에서 필요한 정보(사용할 암호화 알고리즘, 키)의 교환을 위한 TLS Handshake 과정이 존재한다.

암호화 방식

  • 클라이언트는 서버에 접속한 직후 전자 문서인 SSL 인증서를 내려받아서 서버를 신뢰할 수 있는지 판단한 후에 검증이 되었으면 통신을 이어간다.
  • SSL 인증서
    • 클라이언트와 서버 간의 통신을 공인된 제3자(CA) 업체가 보증해주는 전자화된 문서이다.
    • CA의 개인키로 암호화된 인증서 안에는 서버의 공개키가 담겨져있다. (사전에 CA로부터 인증서를 발급받았으므로 안전한 서버이다)
  • 순서
    1. 클라이언트는 랜덤 데이터 1을 생성하여 서버에 요청을 보낸다.
    2. 서버는 랜덤 데이터 2를 생성하여 서버의 인증서와 함께 클라이언트로 응답을 보낸다.
    3. 클라이언트의 브라우저는 모든 CA들의 공개키를 가지고 있어서 CA의 개인키로 암호화된 인증서를 복호화할 수 있기 때문에 인증서를 복호화하여 서버의 공개키를 얻는다.
    4. 클라이언트는 랜덤 데이터 1과 랜덤 데이터 2를 조합하여 pre master secret키를 만든다.
    5. 인증서에 있던 서버의 공개키로 pre master secret키를 암호화한 뒤 서버로 요청을 보낸다.
    6. 서버는 서버의 개인키로 pre master secret키를 복호화한다.
    7. 이제 양쪽이 모두 대칭키를 알고 있으므로 앞으로 모든 통신은 대칭키로 암호화, 복호화한다.
  • https 프로토콜을 사용하여 접근해야 하는데 http로 접근할 경우?
    • 서버 측에서 302 redirect를 이용하여 https 프로토콜로 변경한 주소로 연결해준다. 하지만 http 연결을 거쳐가기 때문에 쿠키 정보 탈취 등 보안에 취약할 수 있는데 이를 막기 위해 클라이언트에게 해당 도메인에 대해 https를 강제로 사용하도록 하는데 이를 HSTS라고 한다.
    • HSTS 란?
      • 클라이언트에게 HTTPS를 강제하도록 하는 것을 권장하는 것
      • 클라이언트에서 강제하기 때문에 http를 이용한 연결 자체가 시도되지 않으며 클라이언트 측에서 차단된다는 장점이 있다.
      • 클라이언트에서 최초로 서버에 요청을 하면 서버는 HSTS 설정에 대한 정보(max-age:언제까지 설정을 유효할지)를 브라우저에게 응답하게 됩니다. 이후 클라이언트는 해당 서버에 대해서 https 요청을 강제화 하게 된다.
      • HSTS는 클라이언트에 일정 시간(max-age) 동안 등록이 되기도 하지만 google, twitter 등의 웹사이트는 구글 크롬 브라우저에 하드코딩되어 HSTS가 preload 되어 강제화 되도록 되어있다.
      • 최초 혹은 일정 시간(max-age)이 지난 뒤 요청 시에 http로 요청할 경우 한 번은 https로 redirect를 하면서 HSTS 정보를 받아야 하기 때문에 이를 막기 위해서 브라우저 preload 리스트에 미리 들어가 있는 것이 좋다.

HTTP 통신

HTTP 통신은 기본적으로 '요청(Request)'과 '응답(Response)'으로 이루어져 있다.
클라이언트가 서버에 요청을 보내면, 그에 맞는 응답 결과를 돌려주고, 클라이언트는 사용자에게 서버로부터 응답받은 결과를 보여준다.
커넥션(Connection)이 계속 연결되어있지 않다는 게 HTTP 통신의 특징이다.
패킷은 크게 '헤더(Header)'와 '바디(Body)'로 되어 있는데, Header에는 보내는 사람의 주소, 받는 사람의 주소, 패킷의 생명 시간 (TTL, Time To Live) 등이 담겨 있고, Body에는 우리가 전하고자 하는 실제 내용이 들어 있다.

HTTP 요청 메시지 형식

  • HTTP Request Message = Request Header + 빈 줄 + Request Body

    • Header
      • 첫 번째 줄 (start-line)
        • 요청 메서드 + 요청 URI + HTTP 프로토콜 버전
        • GET /background.png HTTP/1.0
        • POST / HTTP 1.1
      • 두 번째 줄 ~ (http headers)
        • Header 정보들 (‘Header Name: Header Value’ 형태)
        • 각 줄은 Line Feed(LF)와 Carriage Return(CR)으로 구분된다.
      • 빈 줄 (empty-line)
        • 요청에 대한 모든 메타 정보가 전송되었음을 알린다.
    • Body
      • POST, PUT의 경우에만 존재
      • 요청과 관련된 내용 (HTML 폼 콘텐츠 등)

HTTP 응답 메시지 형식

  • HTTP Response Message = Response Header + 빈 줄 + Response Body

    • Header
      • 첫 번째 줄 (status-line)
        • HTTP 프로토콜 버전 + 응답 코드 + 응답 메시지
        • HTTP/1.1 404 Not Found.
      • 두 번째 줄 ~ (http headers)
        • Header 정보들 (‘Header Name: Header Value’ 형태)
          • 날짜, 웹서버 이름, 웹서버 버전, 콘텐츠 타입, 콘텐츠 길이, 캐시 제어 방식 등
        • 각 줄은 Line Feed(LF)와 Carriage Return(CR)으로 구분된다.
    • 빈 줄 (empty-line)
      • 요청에 대한 모든 메타 정보가 전송되었음을 알린다.
    • Body
      • 실제 응답 리소스 데이터
      • 201, 204와 같은 상태 코드를 가진 응답에는 보통 body가 존재하지 않는다.

예시)

  • 페이지를 요청하기 위한 HTTP 메시지를 만든다.
  • 메시지는 get메서드이고 /manage/newpost.html을 요청하는 메시지이다.
  • 웹브라우저는 서버와 TCP 3Way Handshaking 방식으로 커넥션을 생성한다.
  • 웹브라우저는 서버에 HTTP 요청을 보낸다.
  • 서버는 메시지를 받고 HTTP 메세지를 해석한다.
  • get이라는 메서드이고 /manage/newpost.html을 요청했다는 것을 인지한 뒤, 해당 리소스가 있는지 찾는다.
  • 찾으면 상태 코드가 200인 메시지와 함께 응답 메시지를 작성 후 클라이언트에게 전송한다.
  • 서버는 클라이언트와 TCP 4Way Handshaking 방식으로 커넥션을 종료한다.
  • html을 받은 클라이언트는 웹 브라우저에 페이지를 띄우고 사용자에게 보여준다.

참고:
https://wangin9.tistory.com/entry/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-URL-%EC%9E%85%EB%A0%A5-%ED%9B%84-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC%EB%93%A4-2DNS-%EC%84%9C%EB%B2%84-%EA%B2%80%EC%83%89?category=827054

https://rsec.kr/?p=315

https://asfirstalways.tistory.com/356

https://cordelia273.space/11

https://gmlwjd9405.github.io/2019/04/17/what-is-http-protocol.html

+ 따끈한 최근 게시물