L3에 관한 정리

2021. 10. 29. 19:50게임서버/TCP IP 이론

320x100

안녕하세요 대학생 개발자입니다.

 

오늘은 L3에 대해서 정리를 좀 해보도록 하려고 합니다.

 

L1, L2까지는 직접 연결된 단 두 개의 호스트만을 연결할 수 있는 방법에 대해서 제시를 하고 있었는데요

이제 L3로 오게 되면서 멀리 있는 호스트 즉 경유지를 거쳐서 직접 연결되지 않은 호스트에게 데이터를 전달할 수 있는 프로토콜이 등장하게 됩니다.

 

바로 IP라는 프로토콜입니다. 물론 OSI의 L3는 IP 다는 100% 맞다는 것은 아니지만 TCP/IP 4 layer에서는 일반적으로 IP이기 때문에 IP라고 말씀드렸고요. 그리고 주로 게임 서버에서는 IP 외에는 건드릴 경우가 없다고 생각해서 IP에 대해서 정리를 해보려고 합니다.

 

123.211.151.4와 같이

IP는 Dotted decimal type으로.으로 구분된 1 byte의 데이터 4개 즉 4바이트의 데이터가 주소가 됩니다.

물론 IPv6 같은 경우에는 4바이트가 아니라 6바이트로 되어있긴 하지만 당장 네이버 같은 대형회사들만 봐도 IPv6에 대한 대비를 크게 안 하고 있는 것으로 보아서... 우리가 쓰려면 좀 아직 멀었지 않나 싶습니다.

그래서 앞으로의 IP라는 단어는 IPv4를 의미한다고 생각하시면 될 것 같네요.

 

먼저 전에 정리를 드렸던 내용입니다.

우리가 데이터를 전달하면 ethernet에서는 ARP라는 프로토콜을 통해 어떤 맥주소를 가진 기기에게 보내려면 어느 인터페이스로 내보내야 된다가 정해지게 되는데요

만약 내 호스트가 있는 LAN상에 그런 ip를 가진 호스트가 존재하지 않는다면 이제 더 이상 나의 호스트는 직접 전달이 불가능해지게 됩니다.

그러면 우리는 이때 공유기 혹은 라우터에게 이 데이터를 전달해버리죠.

이때의 공유기는 라우터가 되는것일겁니다.

일반적인 사람들이 사용하는 네트워크 환경인 공유기 하나에 여러 컴퓨터가 물려있는 그런 상황이라면 일반적으로 어느 경우든 인터페이스가 동일할겁니다.

그 상황에서 LAN환경에 dest가 있다고 해도 ip를 가진 호스트에게 보내기 위해 공유기가 있는 인터페이스로 내보내게 될겁니다.

이상황에서의 공유기는 L2 허브로써의 역할을 수행하게 되는겁니다. 

 LoopBackAddress를 제외하고 말이죠.

 

만일 우리가 전달해서 외부로 나간 데이터가 한 번에 주인을 찾을 수 있다면 그 의미는 라우터가 이 아이피를 대상으로 어느 인터페이스로 내보내야 올바른 목적지로 가야 되는지 알고 있다는 의미가 될 것입니다.

위 말과 같이 라우터는 아이피를 보고 판단할 수 있는 능력이 있습니다.

실제 스위치라는 녀석들은 다 그렇죠 L2 스위치는 맥주소를 보고 판단해서 어느 인터페이스로 보내야 될지 결정을 하듯 라우터도 마찬가지입니다.

자신이 가진 라우팅 테이블을 기반으로 받은 아이피를 서브넷 마스킹해서 인터페이스와 동일하다면 거기로 내보내는 방식을 채택하고 있습니다.

이 과정을 보고 packet forwarding라고 합니다. 

 

여자 처자 해서 패킷이 잘 도착했다면 무사히 도착을 한 것입니다.

여기서 이제 중간중간의 함정들을 살펴보도록 하겠습니다.

IP는 유실이 안될까요? 라우터가 처리량을 오버해서 메모리가 꽉 차 버린다면요? 만약 나에게 보내고 싶다면요? 만약 세상에 존재하지 않는 ip라고 한다면요?

 

이런 각각의 케이스를 살펴보도록 하겠습니다.

먼저 이전에 정리했던 내용의 연장이 되는 세상에 존재하지 않는 ip라면 어떻게 될까에 대한 것입니다.

물론 너무 터무니없는 422.345.0.1 이런 아이피는 당연히 API선에서 걸러버립니다.

하지만 실제로 있을법한 ip 10.5.17.112 이런 아이피를 했는데 없는 아이 피라 면요?

라우터는 헤더를 까면서 이런 행동을 한답니다.

ip header의 TTL 값을 1 감소시키기 + 다음번 가야 할 맥주소를 L2에 전달 정도를 크게 한답니다.

그러니까 TTL을 1 감소시키니까 0이 된다면 forwarding을 하지 않고 discard 해버리겠다는 의미가 되는 거죠.

 

다음으로 라우터가 처리량을 오버해버리면서 메모리가 넘쳐흐르게 된다면요?

물론 그전에 기술자분들께서 라우팅 테이블을 좀 수정을 해서 넘치지 않게 하거나 메모리를 늘려주거나 등 다양한 조치를 할 것입니다. 하지만 만약 그럴 틈도 없이 차 버린다면요?

 

그때는 어떻게 되나요?

 

안타깝지만 IP에서는 재전송을 보장해주지 않습니다.

그냥 없어진 패킷일 뿐이에요...

그는 좋은 패킷이었죠

하지만 걱정 마세요.

IP가 못해준 재전송을 TCP라는 프로토콜에서 커버해주고 있습니다

 

나에게 보낼 땐... 어떻게 될까요?

내 아이피를 적거나 127로 시작하는 loop back address를 적게 된다면 내 pc에서 나가지도 않는답니다.

그냥 하나의 호스트의 메모리에서 메모리로 복사가 일어나고 끝이 나요.

L3계층에서 다시 올려 보내 버린답니다...

L4는 왜 일을 한거야 그럼...

그리고 LoopBack의 경우에는 MTU라는게 존재하지 않습니다 당연히도 내 메모리에서 메모리로의 복사기 때문인데요.

그렇기 때문에 TCP에서 MSS단위로 잘라버리지 않습니다.

 

저는 라우터에 갔다가 다시 돌아오는 경우로 생각했는데 생각보다 단순하더라고요...

그저 내 아이 피면 메모리상에서의 복사만 일어나고 끝이라니...

뭐... 그렇다고 하니까 그런 거겠죠.

일단 실제 route print를 해보면 내 아이피나 루프백의 경우를 가지고 있습니다.

 

L3계층에서는 그래서 그 아이피면 굳이 내보내지 않습니다.

 

그럼 이제 IP와 때 놓을 수가 없는 도메인에 대해 정리를 해보려고 해요.

아마 다들 DNS라는 건 들어 보셨을 거예요.

Domain name system인데...

 

이 시스템은 말 그대로 아이피는 너무 특색이 없고 외우기도 힘들기 때문에 아이피에 특색 있는 이름을 갖다 붙여주는 하나의 테이블이 되는 거죠

 

또 특이한 점은 주소체계에서 주소라는 것은 단 하나만 있는 것을 원칙으로 해야 되는데 도메인 같은 경우에는 여러 도메인이 하나의 아이피를 가리킬 수도 있고 하나의 도메인이 여러 아이피를 가리킬 수도 있답니다. 

 

어쨌든 위와 같이 ping을 때리고 dns 캐시를 초기화 한 다음 다시 ping을 때리는 방법으로 확인해도 알 수 있고.

 

이렇게 nslookup을 이용해서도 한 도메인에 ip가 여러 개 묶일 수 있다는 것도 알 수 있습니다.

 

그럼 반대로 하나의 도메인에 ip를 여러 개를 묶는 케이스는 어떤 게 있는가 하면요

스위치의 역할입니다.

서버를 분산시켰음에도 불구하고 제대로 트래픽이 분산되지 않고 한곳에 집중에 된다고 한다면 서버에서는 어쩔 수 없이 계속 메모리를 늘려가면서 대응하거나 혹은 다른 방법으로 분산을 시킬 방법을 찾아야겠죠...

찾다 찾다 더 이상 나오지 않을 경우 이런 식으로 dns서버를 이용한 분산을 일부 사용하기도 한답니다.

위의 결과와 같이 아이피를 뺑뺑뺑 돌려가면서 address의 순서를 바꿔버리면서 전달하게 된다면 클라이언트에서 특별한 로직 첨가 없이 1번째만 가져다 쓴다고 해도 계속 아이피가 바뀌게 되니까요 허허...

 

하지만 사실... ping을 해보시든 뭘 하든 하나의 도메인을 입력하면 계속 같은 도메인만 나오게 돼요.

그리고 껏다켜거나 혹은 특정 시간 단위로 이 아이피는 변경되게 되는데요.

그 이유는 도메인에 대한 캐싱을 하고 있기 때문인데요.

우리 디바이스도 도메인을 캐싱하고 있고 도메인 서버도 항상 그 도메인에 대한 정보를 캐싱하고 있답니다.

하지만 캐싱된 캐시 서버의 경우에는 직접 바로 그 서버에 접근하는 것보다 정보가 업데이트되는 속도가 늦을 수도 있는데 짧으면 몇 시간 길면 일 단위로 캐싱을 하기 때문이라고 합니다.

그래서 우리가 유튜브에서 영상을 보려고 한다면 캐시 서버에 있는 데이터를 가지고 와서 보게 될 거고요.

일정 시간이 지나고 나서 캐시가 비워질 때쯤 다시 직접 서버에 달라고 요구를 하는 방식으로 데이터를 계속 가지고 있습니다.

그게 아니라면...

우리나라에서 유튜브나 구글 서칭 같은걸 요구할 때마다 해외로 나가는 트래픽만 해도 어마어마한데 전 세계에서 그렇게 한다면 어떻게 되겠어요.

난리 나죠...

뭐 이해가 갑니다.

조금 늦지만 트래픽이 줄어들고 그럼 돈이 줄어드는 거니까요.

 

아 그리고 IP의 Data Length는 2바이트 즉 16비트입니다 16 비트면 65535죠...

하지만 실제 64kb씩 데이터를 한 번에 쑝쑝 보내진 않습니다.

MTU라는 것 때문인데요

MTU는 뭐... 정확히 몇이다라고 정해진 규약 같은 건 없습니다만 현재는 대체적으로 1500을 사용 중입니다.

즉 하나의 패킷이 1500byte를 넘게 되면 나눠서 보낸다는 의미가 되죠.

아마 제 생각에는 기술적인 문제보다는 무슨 이유가 있어서 그런 것 같습니다...

솔직히 1500바이트보다 더 못 보낼 것 같진 않거든요...

운영체제나 컴퓨터 구조론을 공부해 보신 분들이 라면 아실 겁니다.

이런 현상을 fragmentation(단편화)라고 하죠

우리가 일반적으로 사용하는 힙에서 동적 할당을 할 때도 bucket단위로 잘라서 사이즈가 100퍼센트 부합하지 않더라도 그 정도 크기랑 비슷하다 싶으면 할당해주는 방식으로 과도한 단편화를 막고 있습니다.

약 십몇단계인데... 제가 기억이 잘나지 않습니다.

그 부분은 째뜬 그게 지금 중요한 것은 아니고요 허허...

 

지금 제가 하려고 하는 말은 MTU가 1500이 넘게 되면 IP 헤더의 fragmentation flag를 손보게 됩니다.

그리고 IP 헤더의 fragmentation offset값을 손보게 됩니다.

그리고 실제로 fragmentation이 이뤄지게 되는 거죠.

그리고 도착지 호스트에서는 fragment offset에 맞춰서 순서를 정렬하고 그리고 flag를 확인해서 더 오는지 안 오는지를 보는 것이죠.

여기까지는 아하 그렇구나 하고 따라오시면 되는데 한 가지 의문이 생깁니다.

그러면 쪼개서 보내는 게 무슨 문제가 있길래 이렇게 호들갑이야? 라고 생각하실 수도 있겠군요

 

이유는 단순합니다.

IP는 재전송이라는 기능을 프로토콜에서 정의하지 않고 있습니다.

즉 14500byte를 보내서 10등분이 나는 것이 문제가 아닙니다.

단 1개라도 제대로 도착을 못한다면 나머지 9개의 패킷은 도착해봐야 쓸모가 없는 패킷이 된다는 의미입니다...

도착지에서 다시 합칠 수 없기 때문입니다.

열심히 보내봐야 의미가 없어진다는데...

이거 얼마나 어이가 없고 허무맹랑합니까 진짜...

 

그렇기 때문에 TCP의 역할이 더더욱 중요한 것이겠죠.

이번 글은 여기까지 작성하도록 하겠습니다.

허허... 이번 글에서는 L3에 대해서 좀 정리를 해봤는데 물론... 기억나는 만큼만 적어서 많이 모자란 것 같긴 합니다...

보시고 부족한 정보가 있다거나 아니면 유익했던 정보가 있다면 댓글로 남겨주시면 감사하겠습니다.

긴 글 읽어주셔서 감사합니다 ^_^..

320x100