몇 일전 면접에서 받았던 질문이다.


"그럼 IPv4에서 IPv6로의 전환은 어떻게 가능할까요? IoT 솔루션의 경우에는 많은 경우에서 IPv6를 사용하는 걸로 알고 있는데 혹시 이 부분에 대해서 답변 주실 수 있나요?"


워딩은 정확하진 않지만, 대략적으로 이런 워딩의 질문을 받았던 것으로 기억한다. 생각지도 못한 질문이였고, 솔직히 말해서 그게 가능하겠구나라는 생각도 면접장에서 처음 했었다. 사실 너무나 당연하게도 IPv4 주소체계를 사용하는 머신이 있고 IPv6 주소체계를 사용하는 머신이 있다면, 어떤 프로토콜을 사용하고 DHCP에서 어떻게 주소를 받아왔는지만 다르지 두 머신의 연결이 불가능할 이유는 당연히 없다. 질문 자체도 생각할 여지가 많았지만 그리 잘 답변하지는 못했던 것 같다. 그럼에도 이 질문이 계속해서 뇌리에 남는 것은, 질문의 난이도도 난이도이지만 내가 뭔가 공부를 잘못하고 있었을 수도 있겠다는 충격을 줬던 질문이였기 때문인 것 같다.


지금까지의 나 자신을 돌아보면 '신입이니까', '학부생이니까' 등의 선입견과 함께 지식을 배우거나 받아들일 때에도 스스로 무의식적인 필터링을 걸어왔던 것 같다. 조금만 사고의 틀이 넓어지면, 나의 내면에서부터 지식을 받아들이는 것을 거부해왔던 걸지도 모르겠다는 생각이 든다. 오늘의 주제도 사실 당연히 고민을 한번쯤은 해볼 수 있는 주제들인데도 '왜 이런 생각을 그동안 한번도 해보지 못했을까'라는 생각이 계속해서 머리 속에 맴돈다. 그 간의 공부는 아무래도 조금은 수정의 여지가 있어보인다.


주제와 동떨어진 얘기는 여기까지 마무리하고, 오늘의 주제를 관통하는 IP가 무엇인지부터 이해해보며 글을 시작해보고자 한다.

 

인터넷 프로토콜

 

그 이름부터 친숙한 IP는 Internet Protocol의 약자로서, 네트워크 프로토콜 중의 하나로서 드넓은 네트워크 세계에서 주소를 지정하고 라우팅하는 방식을 지정한다. 즉, 상호 연결된 네트워크 상에서 패킷을 라우팅하기 위한 프로토콜이다. 


여기서, "상호 연결된 네트워크"라는 말은 말 그대로 서로 통신이 가능하다라는 것 의미한다. 인터넷을 생각해보자. 내 컴퓨터가 인터넷에 연결되어 있다면, 우리는 자유롭게 인터넷에 연결된 다른 컴퓨터로 연결을 전송할 수 있다. 반대로 인터넷에 연결하지 않고, 내 노트북과 학교 컴퓨터를 연결하려고 하면 당연히 연결이 안된다. IP는 상호 연결된 네트워크에서 작용한다.


그 다음 '패킷'이라는 용어는 네트워크 상에서 데이터를 전송할 때 사용하는 기본 단위 정도로 이해할 수 있다. 특히 L3의 네트워크 계층에서는 그 의미가 조금 더 확장되어 IP를 거친 데이터 단위를 의미한다. 만약 우리가 1GB 정도의 데이터를 전송하는 상황을 예로 들어보자.  1GB의 크기는 상당히 큰 크기이다. 컴퓨터가 1GB를 그대로 뚝 떼어다가 옮기고자 하는 컴퓨터에 전선을 따라서 뚝 떼어주면 좋겠지만 현실은 그렇게 동작하지 않는다. 우선 우리의 컴퓨터는 네트워크를 통해 전송을 시작하기 이전에 일정 크기 이상의 데이터를 작게 쪼개서 전송한다. 이때 쪼개지는 단위 하나하나가 패킷이다. 쪼개진 패킷은 목적지에서 다시 합쳐지는데 이를 통해 물리적으로 전송하기엔 너무 거대한 데이터 뭉치를 여러 패킷으로 나눠서 전송할 수 있게 되었다.


IP 패킷은 크게 '헤더(Header)'와  '페이로드(Payload)'라는 두 부분으로 이뤄지는데, 헤더 부분에는 패킷이 전송되는데 필요한 메타데이터가 들어오고, 페이로드 부분에는 전송 계층에서 쌓여져 내려온 데이터가 들어오게 된다.


본격적으로 헤더 이야기를 하기 전에 페이로드에 대해서 잠깐만 이야기를 더 해보고자 한다. 우리가 네트워크 상에 데이터를 전송하게 되면 가장 먼저 Application Layer(L7)를 거치게 된다. 예를 들어 웹 브라우저를 통해 웹페이지에 접속하거나 이메일을 보낸다면 HTTP/HTTPS 기반의 L7 관련 프로토콜을 통해 해당 요청이 처리되기 시작한다. 이때 우리가 전송하고자 하는 정보는 Header라는 메타데이터를 품고 있는 정보와 합쳐진다. 합쳐진 정보는 그렇게 다음 Layer로 전송된다.


그 후, L4에 해당하는 Transport Layer에서는 생성된 데이터를 세그먼트 형태로 분할하고 각 패킷에 헤더를 추가한다. 헤더에는 출발지 포트, 목적지 포트, 순서 정보(Seq), 오류 검출 코드 등의 정보가 포함된다. 위에서와 마찬가지로, 전달된 데이터에 추가적으로 Header가 합쳐진 다음 다음 Layer로 전송된다. 결국 L3의 IP에서 마주하는 정보는 순수한 데이터가 아니다. 위에서부터 내려오면서 헤더가 여러번 붙여진 정보를 처리해야 한다. 마찬가지로 IP 또한 이러저러한 메타 데이터를 헤더를 통해 추가한다. 그렇게 IP 또한 IP 헤더 정보와 위에서부터 여러 헤더로 감싸진 페이로드를 더하여 그 다음 L2로 넘겨주게 된다.

이런 IP에는 IPv4와 IPv6라는 두가지 버전이 존재한다. 인터넷이 등장하고 수많은 PC가 도입됨에 따라 IPv4만으로 모든 컴퓨터를 표현하기에는 곧 한계에 다다를 것이라는 의견들이 발생했다. IPv6는 그러한 문제를 해결하기 위한 해결책이다. IPv4의 경우 약 42억개의 주소를 표현할 수 있다. IPv6가 표현가능한 주소의 개수는 2^128로 이를 숫자로 표현하면 마치 무한대에 가까운 주소를 표현할 수 있음을 알 수 있다.
(총 가능한 주소의 수: "
340,282,366,920,938,463,463,374,607,431,768,211,456")


그러나 두 버전의 차이는 여기에서 그치지 않는다. 헤더의 필드에서도 두 구조 간에는 주요한 차이가 있다.



먼저 IPv4의 헤더 대한 설명이다.



IPv4의 헤더 구조



출처: Wikipedia



Header는 패킷의 전송에 필요한 메타데이터를 품는다.
도대체 어떤 정보들이 필요하길래 Data를 보내는데 저렇게 많은 필드가 필요할까? 각각의 필드를 이해해보자.


Version: IP 프로토콜의 버전을 나타낸다. IPv4의 경우이기에 4가 들어간다.


Header Length(IHL): IPv4의 헤더의 길이를 담는 필드로, 기본 길이는 20 Bytes로 시작하여 추가적인 옵션이 붙는 경우 60 Bytes까지도 늘어난다.

  • 여담으로 IPv6의 경우 헤더의 길이가 40 Bytes으로 고정이며, 추가적으로 확장 헤더라는 개념을 사용한다. 이는 아래에서 IPv6 구조도를 설명하며 다시 설명한다.

  • 4비트의 크기로 표현되는데, 헤더의 길이는 해당 비트로 표현된 이진수에 4배를 곱한 값이다.


ToS(Type of Service): 원래 QoS 정보를 담기 위해 도입된 필드였으나, 시간이 지나면서 DiffServ 및 ECN을 위한 용도로 활용된다고 한다. DiffServ가 6 MSB, ECN이 2 LSB로 표현된다. 용어가 다소 생소한데, 하단에 설명을 자세하게 적어두었으니 참고하시길 바란다.


Total Length: 전체 IP 페킷의 바이트 길이(Header + Payload)가 들어간다. 최대 65,535 바이트까지 표현가능하다 (2^16).


Identification: 16 비트로 구성되어 있으며 원본 데이터그램(Datagram)이 파편화(Fragmentation)되었을 때, 각 파편(Fragment)을 구별하기 위해 사용된다. 

  • 출발지 호스트에서 MTU의 제약 때문에 여러 패킷으로 쪼개진 세그먼트는 목적지 비트에서 Identification을 기준으로 다시 합쳐져서 하나의 세그먼트로 Layer 4에 전달된다.


Flags: 3비트로 구성되어 있으며 (LSB 2개만 사용), 패킷의 Fragmentation 동작을 제어하는데 활용된다.

  • DF(Don't Fragment), MF(More Fragment) 비트가 존재하며, 기본값은 000이다.
  • DF: 중간 라우터에 의해서 Fragmentation되지 않을 것을 표현, 001
  • MF: 계속해서 추가적인 패킷들이 따라온다는 것을 표현한다. 마지막 패킷에서는 표시되지 않는다. 010
  • DF와 MF는 동시에 사용될 수 있으며 (011), 패킷이 쪼개지지 말아야하며, 이후 쪼개진 값이 아직 들어오지 않았음을 의미한다.


Fragment Offset: 쪼개진 파편들의 Offset이다. 만약 패킷의 순서가 뒤죽박죽으로 들어왔다고 해도 Offset을 통해 올바른 순서로의 조립을 보장하는 필드이다.


TTL(Time to Live): 당초 패킷이 네트워크 내에서 살아있을 수 있는 시간을 의미했으나, 지금은 얼마나 많은 라우터를 거칠 수 있는지를 표시한다. 라우터를 거칠 때마다 TTL 값은 1씩 감소하며, 값이 0이 된다면 패킷은 삭제된다.


Protocol: Layer 4, 전송계층의 프로토콜명을 담는다. TCP의 경우 6, UDP의 경우 17라는 값이 담기게 된다.


Header Checksum: 헤더의 손상 여부를 가리는데 활용된다. 만약 출발지에서 계산되어 Checksum에 담긴 값과 목적지에서 계산한 Checksum 값이 다르다면 해당 패킷은 손상된 것으로 간주하여 폐기한다. 주의할 점은 IP 헤더에 대한 무결성을 검증할 뿐, TCP, UDP 세그먼트 값에 대한 무결성까지는 검사하지 않는다. 즉 헤더를 제외한 페이로드에 대해서는 무결성이 보장되지 않는다.


Chceksum의 계산 과정은 다음과 같다

  1. Header Checksum 필드를 0으로 설정
  2. IP 헤더의 모든 필드를 16 비트 단위로 쪼갬 (32 비트로 표현된 한 줄 -> 16 + 16)
  3. 분할된 모든 16 비트의 값을 더함. 만약 덧셈 중 오버플로우가 발생한다면 이는 LSB에 더한다.
  4. 더해진 값의 보수 값을 계산한다.
  5. 최종적으로 보수 값이 Header Checksum 필드에 저장된다.
  6. 목적지에 패킷을 수신할 때, 위의 계산 과정은 다시한번 반복되면, 계산된 값이 헤더에 위치한 체크섬과 일치하는지 확인한다.

Source Address & Destination Address:

  • IPv4의 주소를 표현하는 필드로 각각 32 비트로 표현된다.


Options: 다양한 추가적인 기능에 대한 값들이 들어간다.


Padding: IP 헤더의 길이를 32비트의 배수로 맞추기 위해 사용되는 값이다. 특별한 의미 없이 포맷을 맞추기 위해 사용되며 필요한만큼 추가된다.



아래는 위에서 설명하지 못한 개별적인 용어에 대한 설명이다.




QoS(Quality of Service): 네트워크에서 여러 유형의 트래픽(e.g. 음성, 비디오, 데이터)이 전송되는 경우, QoS는 각 트래픽 유형에 대해서 서로 다른 우선 순위를 지정하여 네트워크 자원을 최대한 효율적으로 사용하도록 돕는다. 예를 들어 실시간 음성 통화의 경우에는 데이터 다운로드의 경우보다 높은 우선 순위를 보장받을 수 있다. 중요한 패킷이 더욱 빨리 처리된다고 생각할 수 있겠다.

DiffServ(Differential Services): 트래픽을 여러 클래스로 분류하여 각 클래스 간에 다른 처리 수준을 제공하는 기술이다. 그러나 DiffServ의 우선순위를 매핑해둔 DSCP값들을 어떻게 처리할 것인지에 대해서는 별도의 규약이 없기 때문에 강제성은 없다. 때문에 네트워크 장비를 관리하는 운영 정책에 따라 네트워크 관리자의 판단 하에, 일반적으로 우선 순위가 높다고 알려진 DSCP를 후순위로 미루는 것도 충분히 가능하다.

DiffServ의 PHB, 다음과 같은 종류의 클래스를 가지고 있다. 어디까지나 요약 정도의 느낌으로 봐주시면 좋겠다. 실제 정의는 훨씬 복잡하다.


  1. Default Forwarding (DF) - PHB (Per-Hop Behavior) Class:  기본 클래스로 별도의 QoS 구성 없이 전달되는 트래픽에 사용된다. (PHB: 패킷이 네트워크 장비에서 어떻게 처리될 것인지를 지정하는 '프로파일'의 일종이다. 예를 들어 PHB의 우선 순위가 높은 경우 동일한 라우터에서 패킷의 우선 순위가 다르게 처리된다.)

  2. Expedited Forwarding (EF) - PHB Class: 주로 낮은 지연, 패킷 손실을 요구하는 실시간 애플리케이션 (e.g. VoIP <- 음성 통화)에 사용되는 클래스이다. 가장 높은 우선 순위를 가지는 PHB이다.

  3. Class Selector (CS) - PHB Class: 레거시 ToS와의 호환성을 위해 도입되었으며, CS0부터 CS7까지 총 8개의 클래스를 가지고 있다. 숫자가 커질 수록 높은 우선 순위를 나타낸다.

  4. Assured Forwarding (AF) - PHB Class: 여러 우선 순위의 트래픽을 나타낼 수 있는 4개의 클래스로 구성되며, 각 클래스는 다시 3개의 drop precedence로 나뉜다(e.g. AF11, AF12, AF13, ... , AF43). 이때 클래스의 크기는 커질 수록, drop precedence는 낮을 수록 우선순위가 커진다. (drop precedence는 번역이 마땅치 않아 그대로 기재한다. 내림차순의 우선 순위 정도로 이해해도 좋을 것 같다.)

  5. Scavenger Class: 중요하지 않은 서비스들에 대해서 남은 네트워크 대역폭(bandwidth)를 할당하고 관리하기 위한 목적으로 생성. 필수적이지 않은 애플리케이션이나 시간에 민감하지 않은 서비스에서 메세지를 대량전송하고 싶은 경우 사용할 수 있다. 남은 대역폭을 사용하다보니, 중요한 프로그램의 성능을 최대한 건드리지 않으면서 추가적으로 가능한 만큼에 대해서만 자원을 사용하고 싶은 서비스에 적합하다고 한다.


ECN(Explicit Congestion Notification): 패킷의 손실을 줄이기 위해 네트워크의 혼잡을 조기에 감지하고 대응하는데 활용된다. 혼잡이 감지된다면, ECN은 트래픽을 조절하기 위해 송신자에게 별도의 알림을 전송하는 것을 통해 트래픽의 손실을 방지하거나 최소화할 수 있다.

Fragmentation(파편화): 처리가능한 단일 패킷 크기보다 크다면, 패킷을 쪼갠다.

  • Datagram: 전송 계층(Transport Layer, Layer 4)에서 네트워크 계층(Layer 3)으로 전달되는 정보 단위

  • 데이터 링크 계층(Data Link, Layer 2)에서 데이터를 보내기 위해서는 최대 보낼 수 있는 프레임의 수를 넘어서는 안된다. 이때 최대 보낼 수 있는 프레임의 크기를 MTU(Maximum Transmission Unit)라고 부른다.

  • 만약 전송하고자 하는 패킷의 크기가 MTU를 넘는다면, 이를 파편화, 즉 쪼개야 한다.
    (e.g. 4000 바이트를 보낼 예정, MTU가 1500 -> 총 3개의 Fragment 생성 )

  • Layer 3, 네트워크 계층에서 수행된다. (TCP/UDP의 전송 계층을 지나온 세그먼트가 IP에 의해 여러 개의 작은 IP 패킷으로 쪼개짐)

  • 출발지 호스트 혹은 라우터에서 쪼개진다. 라우터의 경우 다음 홉이 처리할 수 있는 MTU보다 크다면 이를 쪼갠다.
  • IPv6의 경우에는 출발지 호스트에서만 쪼개는 것이 가능하다. 이는 Fragmentation에 의한 복잡성과 그에 따른 오버헤드를 줄이기 위함이라고 한다. 때문에 IPv6의 Layer 3에서는 경로 MTU 탐색 기술을 활용하여 최적의 MTU를 결정하여 패킷의 크기를 설정하는 과정이 추가적으로 요구된다.

 

IPv6의 구조도


그렇다면 IPv6는 어떨까? 버전이 늘어났으니까 필드에 대한 복잡성도 늘어나지 않았을까? 예상과 달리 IPv6의 헤더는 IPv4의 헤더보다 훨씬 간단하다. 다만, 헤더의 크기만큼은 대부분의 IPv6 패킷이 IPv4의 패킷보다 크다. 어떻게 헤더의 구조를 간략화시키면서 IPv4의 기능을 확장시켰을까? 결론부터 얘기하자면 이는 확장 헤더라는 개념을 통해 가능하다. 아래 필드 목록을 이해해보며 보다 자세하게 이해해보자.


출처:&nbsp;https://www.networkacademy.io/ccna/ipv6/ipv4-vs-ipv6

 

 

  • Version: 4 Bits, IPv4의 경우와 동일하다. IPv6의 경우 6이 들어간다.


  • Traffic Class: 8 Bits, IPv4의 ToS에 해당한다. 정확하게는 QoS 방식이 아닌 DiffServ 아키텍처의 ToS 필드와 일치한다.

    • Tos와 동일하게 6 MSB는 DSCP를 표현하는데 활용되고, 나머지 2비트는 ESN을 표현하는데 활용된다. (위의 용어 설명 참고)

  • Flow Label: 20 Bits, 동일한 "흐름(Flow)", "세션(Session)"에 속하는 패킷들을 식별하는데 활용한다.

    • 간단하게 말해서 흐름이라는 것은 패킷을 구분짓는 단위로서, 어떤 특정 세션, 연결 혹은 동일한 응용프로그램의 일부로 동작하는 것을 나타내는 용어이다.  

    • 해당 흐름에 대해서 한번 경로가 결정되면, 그 흐름에 속하는 모든 패킷들은 동일한 패킷으로 전송된다. 이는 특정 응용 프로그램 패킷들의 일관된 지연시간을 보장한다.
    • 이때, 흐름 단위를 결정하는 요소로는 1) 출발지 주소:포트, 2) 목적지 주소:포트, 3) (Layer 4, 전송 계층의) 프로토콜 타입, 4) Flow Label 등이 있다.

    • 예를 들어 VoIP(Voice over IP, 음성 통화)의 경우, 패킷을 일관되게 처리하는 것이 중요하다. Flow Label을 통해 VoIP 트래픽을 선별해낼 수 있다면 네트워크 장비로 하여금, VoIP 흐름에 속하는 패킷들에 대해서 우선 순위를 부여하거나 특정 경로를 선택하도록 도움을 줄 수 있다.

    • 마지막으로 Flow Label의 생성은 오직 Source에서만 이뤄진다. 패킷의 전송 과정 중에 변경되는 것은 허용되지 않는 행동이다. 


Payload Length: 20 Bits, 페이로드의 길이를 나타낸다.

  • IPv4와 달리 IPv6의 경우 헤더의 길이가 40 Bytes로 고정이다. 때문에 기존의 Total Length 필드가 Payload Length만 기록하는 것으로 변경되었다. 

Next Header: 16 Bits, 다음 확장 헤더의 위치를 나타낸다.

  • IPv6의 헤더의 필드들을 간소화시키는 핵심 필드이다. IPv6의 헤더는 크기가 고정적이다. 다만 이것이 표현해야할 헤더의 양이 줄어들었다는 것은 아니다. 오히려 다양한 기술의 도입으로 헤더는 더욱 무거워졌다. IPv6에서는 이를 확장 헤더를 통해 해결한다.

  • 확장 헤더의 개념 자체는 어렵진 않다. Next Header 필드의 경우 다음에 오는 확장 헤더를 표시한다.

  • Next Header 필드에 TCP나 UDP와 같은 전송 계층의 프로토콜 값이 들어가는 경우, 해당 확장 헤더가 마지막이라는 것을 의미한다.

  • 대략적인 구조: | 기본 IPv6 헤더 (40바이트) | 확장 헤더 1 | 확장 헤더 2 | ... | 상위 계층에서 온 페이로드 |

  • 예를 들어 다음의 헤더들이 존재한다.

    • Hop-by-Hop Header: 패킷 경로 상의 모든 노드가 확인해야 하는 정보, e.g. 우선순위

    • Authentication Header: 패킷의 인증 정보, 주로 IPsec에서 활용

    • ESP(Encapsulating Security Payload) Header: 보안이 설정된 페이로드 데이터

    • Fragment Header: Fragmentation된 패킷들에 대한 정보

    • Routing Header: 패킷의 중간 경로에 대한 정보, 특정 라우터를 거치도록 강제할 수 있다.

    • Destination Header: 최종 목적지에만 전달되는 정보, e.g. 모바일 환경에서 Source Destination에 대한 정보가 별도로 필요한 경우, 해당 헤더에 포함시킬 수 있다.

  • 헤더 목록들을 살펴보면 대부분은 IPv4에서도 도입된 개념들이 대부분이다. 헤더 정보에 대한 표현 방식의 차이 정도로 이해할 수 있을 것 같다.

  • 추가적인 예시를 들어보자.

    • e.g. 송신자 A가 수신자 B에게 IPv6 패킷을 전송하려고 한다. 이 패킷은 라우팅 확장 헤더를 포함하고 있고, 그 다음에 TCP 세그먼트를 담고 있다. 패킷은 다음과 같이 구성된다.

    • 먼저, IPv6의 기본 헤더가 온다. Next Header 값은 43(라우팅 확장 헤더)이다.

    • 그 다음은 명시한 대로 라우팅 확장 헤더가 온다. Next Header 값은 6(TCP)이다.

    • Next Header 값이 상위 계층의 프로토콜을 나타내므로 확장 헤더는 끝이다. 대신 IP 패킷의 페이로드, 즉 TCP의 세그먼트가 오게된다.


Hop Limit: 8 Bits, IPv4의 TTL 필드에 해당한다.

  • 중간에 노드를 만날때마다 Hop Limit을 하나씩 줄인다.

  • 만약 0이 된다면, 해당 패킷은 폐기한다.

Source Address & Destination Address: 128 Bits, IPv4와 동일하되 필드의 길이가 늘어났다. 아래는 IPv6 주소 체계에 대한 짧은 요약이다.

  • IPv6의 주소는 16비트의 8개 그룹으로 나뉜다.

  • 각 그룹은 4자리의 16 진수로 표현되며 각 그룹 간에는 콜론(:)을 통해 구분된다. (IPv4의 경우에는 8비트의 4개 그룹이다)

  • IPv6에서는 연속된 0으로 표현된 그룹의 경우 ::로 축약이 가능하다.

    • e.g. 2001:0db8:85a3:0000:0000:8a2e:0370:7334

      -> 2001:0db8:85a3:0:0:8a2e:0370:7334

      -> 2001:0db8:85a3::8a2e:0370:7334
  • 특수한 주소 
    • '::1': Loop Back 주소. IPv4의 Localhost이다.
    • '::': 주소가 지정되지 않은 인터페이스를 의미한다.


IPv4와 IPv6 간의 헤더 비교


이렇게 IPv4와 IPv6에 대한 헤더의 필드를 살펴보았다. 사실 하나하나가 별도의 주제로 글을 쓸 만큼 가벼운 주제가 아닌 필드들이 많기에 더욱 정확한 이해를 위해서는 추가적인 공부가 필요하지 싶다.

IPv4와 IPv6는 IP 프로토콜의 버전이므로 많은 유사점이 있을 수 밖에 없다. 그럼에도 불구하고 구체적인 헤더 구조와 필드는 상당히 다르다고 보는 것이 맞을 것이다. 특히 시각적으로 보여지는 두 버전 간의 차이는 극명해보인다.

그러나 필드 각각을 이해해보면, 사실 이름만 바뀌었다고 느껴지는 필드들도 몇몇 보인다. 예를 들어 IPv4의 TTL 필드는 원래 패킷이 네트워크 내에서 존재할 수 있는 시간을 나타내기 위한 것이었다. 그러나 현재는 패킷이 지나가는 라우터의 횟수를 제한하는 역할을 한다. 이러한 변화에도 불구하고 필드의 이름은 'Time to Live'로 유지되었는데, 이는 이름만 바뀌고 기능은 유지된 필드 중 하나로 볼 수 있다. IPv6에서는 이를 Hop Limit이라는 보다 직관적인 이름으로 변경하였다. 결국 의미는 동일하되, 이름만 변경되었다.

 

위의 이론을 기반으로 다음과 같이 두 버전의 헤더를 비교해보았다. 검증을 거치지 않은 개인적인 의견이기에 어디까지나 이런 의견이 있구나 정도로만 봐주시면 좋겠다.


IPv4 Header Field IPv6 Header Field 설명
Version Version IP 프로토콜의 버전을 나타냅니다.
Header Length (IHL) (IPv6에는 존재하지 않음; 40 Bytes로 고정) 헤더의 길이를 나타냅니다.
Type of Service (ToS) Traffic Class 서비스 타입 또는 트래픽 클래스를 나타냅니다.
Total Length Payload Length 전체 패킷의 길이를 나타냅니다.
Identification (확장 헤더를 통해 Fragmentation 처리됨) Fragmentation를 위한 식별자입니다.
Flags (확장 헤더를 통해 Fragmentation 처리됨) Fragmentation 옵션을 나타냅니다.
Fragment Offset (확장 헤더를 통해 Fragmentation 처리됨) Fragmentation을 통해 쪼개진 패킷의 순서를 나타냅니다.
Time to Live (TTL) Hop Limit 패킷이 네트워크에서 존재할 수 있는 최대 횟수를 나타냅니다.
Protocol Next Header
(TCP/UDP인 경우 다음 패킷이 페이로드)
상위 프로토콜을 나타냅니다.
Header Checksum (IPv6에는 존재하지 않음; 효율성을 위해 제거됨) 헤더의 체크섬입니다. IPv6에서는 이 필드가 제거되었습니다.
Source Address Source Address 패킷의 출발지 주소를 나타냅니다.
Destination Address Destination Address 패킷의 목적지 주소를 나타냅니다.
Options (if IHL > 5) (확장 헤더를 통해 Fragmentation 처리됨) 추가적인 옵션을 나타냅니다. IPv6에서는 확장 헤더로 처리됩니다.

 


그래서 IPv4와 IPv6의 호환은 어떻게 이뤄질까

IPv6는 기본적으로 IPv4와 많은 유사점을 공유한다. 그러나, 확장 헤더로 대표되는 IPv6의 패킷을 다루는 방식은 IPv4와 분명히 다르다. 확장 헤더는 IPv6가 IPv4에 비해 보다 유연하고 확장 가능하도록 설계된 주요한 특징 중 하나이다. 특히, 다양한 네트워크 상황과 요구사항에 대응할 수 있는 다양한 확장 헤더 타입들이 IPv6에 도입되었다. 이를 통해, IPv6는 보안, 트래픽 흐름, 라우팅 옵션 등 다양한 기능을 제공하며, 이에 그치지 않고 추후 새로운 기능이 도입되더라도 무한한 가능성을 열어둔다는 점에서 확장성이 무궁무진하다.


그럼에도 IPv4와 IPv6를 연결시키는 것은 쉽지 않다. 이를 가능하게 하는 기술로 해당 글에서는 Dual Stack, Tunneling, Translation까지 총 세가지 기술을 소개하고자 한다.



1. Dual Stack (이중 스택)

Dual Stack이라는 용어는 하나의 장비나 시스템에서 IPv4와 IPv6 두 가지 IP 버전을 동시에 지원하는 방식을 의미한다. 이 기술을 사용하면 하나의 NIC(네트워크 인터페이스 카드)에서 IPv4와 IPv6 주소를 동시에 할당받아 사용할 수 있다.


Dual Stack이 처리되는 순서는 대략적으로 이렇다.




  1. 주소 할당

    • Dual Stack 환경의 장비에서는 IPv4와 IPv6 주소를 동시에 할당받는다.

    • 물리적으로는 동일한 인터페이스이지만 버전에 따른 두 개의 주소를 가지고 있는 셈이다.


  2. 네트워크 스택

    • 장비 내부의 네트워크 스택은 IPv4와 IPv6 프로토콜을 모두 처리할 수 있는 로직과 라이브러리를 포함한다.

    • 들어오는 패킷의 버전을 확인하고 적절한 프로토콜 로직으로 패킷을 처리한다.


  3. 패킷 전송

    • 데이터 전송 이전에 전송하고자 하는 목적지의 IP 주소 타입(IPv4 or IPv6)을 확인한다.

    • 주소 타입에 따라 적절한 IP 프로토콜 스택을 사용하여 패킷을 생성하고 전송한다.


  4. DNS 조회

    • 주소가 두개이기에 DNS 서버를 거칠 경우에도 동작이 두 버전에서 일어난다.

    • 일반적으로는 A 레코드(Address record, IPv4)와 AAAA 레코드(Quad-A Record, IPv6)를 모두 반환받게 된다.


  5. 통신의 방향성

    • IPv4와 IPv6의 패킷은 서로 직접 통신할 수 없다.

    • Dual Stack이라 하더라도 IPv4 패킷은 IPv6 네트워크를 거칠 수 없고, IPv6의 경우에도 IPv4 네트워크를 거칠 수 없다.


  6. 풀백 매커니즘

    • 만약 IPv6 통신이 실패한다면, Dual Stack 환경에서는 자동으로 IPv4를 활용하여 통신을 재시도할 수 있다.




Dual Stack 방식은 기존의 IPv4 네트워크 인프라를 크게 수정하지 않고도, IPv4와 IPv6를 모두 지원하는 장비를 통해 IPv6의 도입을 가능하게 한다. 해당 장비는 IPv4를 사용하면서도 IPv6로의 점진적 전환을 가능하게 한다는 점에서 기존 장비와의 호환성을 보장한다.


그러나 Dual Stack은 단점이 명확한 방식이다. 


너무나도 자연스럽게 넘어갔지만, 2가지 주소 체계를 모두 관리하는 것은 쉬운 일이 아니다. 이는 운영 상의 복잡성을 야기한다. 또한 두 가지 IP 주소를 관리하고, 두 네트워크 스택을 유지하기 위한 추가적인 리소스도 만만치 않을 것이기에 하드웨어의 부담도 가중된다.


그럼에도 현재 많은 웹사이트와 온라인 서비스 또한 Dual Stack을 활용한 IPv6 지원을 실제 지원하고 있다고 알려져있다. 뿐만 아니라 대형 ISP나 데이터 센터에서도 Dual Stack 방식을 활용한 IPv6 전환이 이뤄지고 있다고 한다.


Dual Stack은 IPv4와 IPv6를 동시에 처리할 수 있는 하드웨어를 통해 IPv6로의 원활한 전환을 지원하는 기술라고 요약할 수 있을 듯 하다.



2. Tunneling (터널링)

앞서 언급한 Dual Stack 방식은 하드웨어가 IPv4와 IPv6를 동시에 지원하게 함으로써 문제를 해결하는 반면, 터널링은 별도의 하드웨어 없이 IPv6 패킷을 IPv4로 감싸 새로운 패킷 형태로 전송함으로써 호환성 문제를 극복한다. 즉, Dual Stack이 보다 하드웨어적인 해결에 가깝다면, 터널링은 하드웨어와 함께 소프트웨어적인 해결을 적용한다고 이해할 수 있겠다.


이때 감싸는 작업은 캡슐화(encapsulation)라고 불리는데, 캡슐화를 거친 IPv6 패킷은 IPv4 헤더로 감싸졌기에 마치 IPv4로 인식되어 라우터들을 거치게 된다. 최종적으로 목적지에 도착한 패킷은 다시 IPv4 헤더를 제거하는 과정을 거치는데 이를 비캡슐화(decapsulation)이라고 부른다. 이 과정을 거쳐 수신 측에서는 원본 IPv6 패킷을 그대로 처리할 수 있게 된다. 패킷 내의 데이터는 적절한 애플리케이션 또는 서비스로 전달된다.


터널링에는 여러 방식이 있는데, 오늘은 그 중 대표적인 6to4라는 기술을 소개해보고자 한다. 이는 6to4에서의 캡슐화는 다음의 단계를 거쳐 완성된다.


  1. IPv6 패킷 준비: 송신 측에서는 일반적인 방법으로 IPv6 패킷을 생성한다. 다만, 한 부분에서 평범한 IPv6 패킷과 차이가 있다.

    • Prefix(CIDR): 바로 6to4을 사용하는 IPv6 패킷의 경우에는 주소의 첫 16비트가 "2002"라는 접두어로 고정된다.

    • IPv4 Address: 이후 원본 IP 주소가 32비트 형태로 추가된다.

    • SLA(Subnet ID):그 다음 16비트는 SLA로 채워진다. 만약 큰 조직에서 내부 서브넷을 쪼개야 한다면, 해당 비트를 활용할 수 있다.

    • Interface ID: 마지막 64비트는 인터페이스 식별자로 사용된다. 일반적이라면 NIC(Network Interface Card)에 기록된 MAC 주소를 기반으로 생성된다.

       
  2. IPv4 헤더 생성: 송신 측에서는 IPv4 헤더를 준비한다. 이때 송신 측 주소는 6to4 기능을 수행하는 송신 측 장비의 IPv4 주소로 설정되고, 목적지 주소는 6to4 릴레이 주소(IPv6 네트워크 환경) 또는 IPv4의 형태의 목적지 주소(IPv4 네트워크 환경)로 구성된다.


    • 어떤 목적지 주소 형태를 사용할지는 현재 보내고자 하는 네트워크가 어떤 IP 버전을 사용하는지에 기반한다.


    • 만약 IPv6 네트워크 환경을 사용한다면, 해당 환경의 라우터들은 IPv4로 위장한 6to4를 처리할 수 없다. 때문에 6to4를 지원하는 별도의 중개자가 추가적으로 필요하다. 이를 6to4 릴레이라고 부른다.


  3. 캡슐화(Encapsulation): 준비된 IPv6 패킷을 위에서 생성한 IPv4 헤더의 데이터 부분에 넣는다. 즉, IPv6 패킷 전체가 IPv4 패킷의 페이로드가 된다. 6to4를 지원하는 IPv4 패킷 헤더의 필드와 IPv6 헤더의 필드 간에 일대일 변환이 이뤄지는 것은 아니다.


    그럼에도 불구하고 앞서 살펴보았던 몇몇 필드들에 대해서는 두 버전 간에 어느정도의 유사성이 존재함을 확인하였다. 예를 들어 다음의 IPv6 헤더는 다음과 같이 IPv4 헤더로 변환된다.


    • Version: 캡슐화가 수행되며, IPv4의 헤더에 4가 기록된다. 페이로드 내부의 IPv6 패킷은 6이 기록되어 있다.

    • Source, Destination Address: 6to4 방식에 따라 앞서 설명한 터널링을 위한 IPv4 주소가 설정된다.

    • Payload Length: IPv4의 Total Length 필드로 변환되기 위해서는 IPv4의 헤더와 캡슐화된 IPv6 패킷의 전체 길이가 더해진다.

    • Next Header: Protocol 필드의 값이 상위 계층의 프로토콜(TCP/UDP)을 표현하지 않는다. 대신 IPv6를 표현하는 41이라는 값이 들어간다.
      (참고: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)


    • Hop Limit: TTL 필드에 그대로 복사된다.


  4. 패킷 전송: 완성된 IPv4 패킷은 일반적인 방법으로 IPv4 네트워크를 통해 전송된다.

    • 도착 이후 6to4 패킷은 비캡슐화를 수행해야 한다. 때문에 목적지의 호스트 또한 6to4를 지원할 수 있도록 하드웨어와 소프트웨어를 지원해야 한다.

 

이렇게 전송된 6to4 패킷은 IPv4 환경에서는 기존 IPv4 라우터를 거쳐 처음부터 IPv4였다는 듯이 전송되고, IPv6 환경에서는 6to4를 지원하는 릴레이 라우터를 거쳐 적절하게 전송된다.



다만 6to4 방식의 경우 개인적으로 장점보다는 단점이 많다고 생각된다. IPv6 호스트를 IPv4 네트워크에 통합시킨다는 아이디어 자체는 문제가 없다. 때문에 별도의 IPv6 인프라 없이도, 기존 IPv4 인프라를 통해서 IPv6 주소체계를 활용하는 호스트를 IPv4 환경에서도 활용할 수 있게 만들어준다.


다만, 앞서 Dual Stack의 단점으로 언급했던 하드웨어 업그레이드는 여전히 6to4 방식에서도 해결되지 않는다. 오히려 캡슐화를 위한 소프트웨어에 대한 부담만 늘 수 있겠다는 생각도 든다. 그리고 캡슐화와 비캡슐화 과정 또한 추가적인 리소스를 활용하기에 호스트 머신의 리소스 활용 측면에서도 부정적인 결과를 초래한다는 점도 고려해야 한다.


두 방식을 간단하게 테이블로 비교해보자.

 

Method Advantages Disadvantages
Dual Stack
  • 간단하고 직접적
  • 최고의 성능
  • 장비 및 리소스 필요
6to4 (Turnneling)
  • IPv4 네트워크 통합
  • 별도의 IPv6 인프라 구축 불필요
  • 추가적인 지연 및 복잡성
  • 통신 문제

 

 

3.  Translation (번역)

앞선 터널링과 달리 IPv4와 IPv6 패킷을 직접 번역하여, 두 프로토콜의 직접적인 통신을 가능하게 하는 기술이다. 구체적으로 NAT64, DNS64, SIIT(Stateless IP/ICMP Translation)이라는 세가지 기술이 대표적이다.


NAT64

  • IPv6-only 클라이언트가 IPv4 서비스에 액세스할 수 있게 하는 변환 매커니즘이다.


  • 세션을 통해 상태를 유지하며(Stateful), 저장된 연결 상태 정보를 통해 IPv4와 IPv6 주소를 서로 매핑시켜놓는다. 


  • 실제 네트워크 환경에서 단독으로 사용되기보다는 DNS64와 함께 사용되어, IPv6 클라이언트가 IPv4 웹사이트에 접근할 수 있도록 도와준다.

  • IPv4-only 주소를 IPv6 형태로 변환하는데는 활용되지 않기 때문에, 이는 별도로 464XLAT라는 기술을 활용해야 한다.



DNS64

  • IPv6-only 클라이언트가 IPv4-only 목적지의 DNS 질의를 수행할 때 IPv4의 응답을 받아 IPv6 주소로 변환해 반환하는 기술이다.


  • 실제 웹서비스 환경에서는 클라이언트는 대체로 DNS 질의를 통해 목적지의 IP 주소를 확인한다. IPv6-only 클라이언트가 DNS 질의를 실행하는 경우 만약 DNS에 저장된 응답이 A 레코드 (IPv4)라면, DNS64는 이를 AAAA 레코드 (IPv6) 형태로 변환하여 클라이언트에게 반환한다.


  • 반환된 AAAA 레코드는 패킷의 목적지 주소에 담긴다. 그대로 보내는 경우 IPv6 인프라가 아니라면 목적지를 찾을 수 없을 것이다.


  • 이 경우 NAT64 기술이 활용된다. AAAA 레코드는 NAT64를 거쳐 원래의 A 레코드로 다시 변환되며 그 후 변환된 A 레코드를 기반으로 IPv4 패킷을 원래의 IPv4 목적지로 전송한다.



SIIT (Stateless IP/ICMP Transition)

  • 상태가 없는 변환을 제공한다. 이는 직전의 NAT64와 정확히 반대되는 내용이다.


  • 별도의 세션을 활용하지 않기 때문에 각 패킷은 개별적이다.


  • A 레코드를 AAAA 레코드로 변화시키거나 그 반대의 경우도 가능하다.


  • 별도의 세션 관리가 없다는 점은 곧 장점이자 단점으로 작용한다.


    1. 예를 들어 대규모의 네트워크의 경우, 굳이 세션을 사용해도 되지 않아도 되는 서비스라면 이는 메모리 사용량 측면에서 큰 이점을 가져다준다. 또한 세션 테이블의 관리가 필요없다는 점은 운용과 관리 측면에서 훨씬 유리하다.


    2. 그러나 만약 별도의 세션을 통해 관리가 필요한 애플리케이션이라면 SIIT를 사용할 수 없다.


      • e.g. 동적 포트 할당


        • Stateful 변환에서는 세션의 상태를 추적하므로, 클라이언트나 서버에서 동적으로 할당된 포트에 대한 매핑을 유지할 수 있다.


        •  만약 포트 할당이 새롭게 필요한 경우, 해당 포트 번호에 대한 변환을 동적으로 수행한 후 이를 세션 테이블에 저장하게 지속적으로 추적할 수 있다.

 


여기까지해서 내용이 마무리되었다. 다른 분야도 마찬가지지만 네트워크 분야야 깊게 파고들어갈 수록 정말 끝이 없다는 느낌을 많이 받는다. 사실 간단하게 주제만 정리하고 글을 마무리했었어도 됐지만, 내 스스로가 IPv6에 대해서 이해를 잘 하고 있지 못하고 있다는 느낌을 받게되어 글이 쓸데 없이 길어지고 말았다.


아무쪼록 주제 자체도 흥미롭고, 내용이 (너무) 많은 거 말고는 이해가 그렇게 어렵지 않기에 한 번 익혀두고 다시 읽어보면 금방 기억이 날 듯 하다. 부족한 네트워크 지식이 조금은 늘었다고 생각하니 행복하다.

 

 

'CS' 카테고리의 다른 글

L7 프로토콜 - HTTP  (0) 2023.08.08
정적 라이브러리  (0) 2022.12.05
실행가능한 목적파일  (0) 2022.12.03
Linking(링킹) 소개  (0) 2022.12.02
시간 지역성을 위한 캐시 재배치  (0) 2022.12.01