Linux 에서 네트워크 계층 연결 시뮬레이션

CompTIABeginner
지금 연습하기

소개

이 실험에서는 Linux 환경에서 네트워크 계층 연결의 기본 원리를 탐구합니다. Docker 컨테이너를 사용하여 두 개의 별도 노드를 시뮬레이션하고, ip 명령어를 사용하여 정적 IP 주소를 수동으로 할당하는 방법을 배웁니다. 그런 다음 ping 유틸리티를 사용하여 공유 가상 네트워크에서 이 노드 간의 직접 통신 경로를 테스트합니다.

먼저 동일한 서브넷에서 노드를 구성하여 성공적인 연결을 관찰합니다. 그런 다음 한 노드를 다른 서브넷으로 재구성하여 예측 가능한 통신 실패, 즉 'Destination Host Unreachable' 오류를 확인합니다. 이 실습은 IP 서브넷이 직접 통신을 어떻게 제어하는지, 그리고 다른 논리적 네트워크에 있는 장치가 라우터 없이는 연결할 수 없는 이유를 명확하고 실용적으로 보여줍니다.

2 노드 실습 환경 준비

이 단계에서는 실험의 기반이 되는 환경을 설정합니다. 전체 가상 머신을 사용하는 대신, 가볍고 격리된 Docker 컨테이너를 활용하여 두 개의 별도 네트워크 노드를 시뮬레이션합니다. 두 노드 간의 통신을 가능하게 하기 위해 먼저 사용자 지정 Docker 네트워크를 생성합니다. 이 가상 네트워크는 물리적 네트워크 스위치처럼 작동하여 두 노드를 동일한 공유 통신 세그먼트에 배치합니다.

노드를 위해 Ubuntu 22.04 Docker 이미지를 가져옵니다.

docker pull ubuntu:22.04

먼저 두 노드가 사용할 가상 네트워크를 생성합니다. 이 네트워크의 이름을 lab_net으로 지정하고 특정 IP 주소 범위를 할당할 것입니다. 이 범위는 이후 단계에서 중요하게 사용됩니다.

터미널에서 다음 명령을 실행합니다.

docker network create --subnet=192.168.56.0/24 lab_net

이 명령은 Docker 에게 lab_net이라는 새 브리지 네트워크를 생성하고 192.168.56.0/24 서브넷을 사용하도록 구성하도록 지시합니다. 네트워크 생성 확인을 위해 긴 고유 ID 가 출력되는 것을 볼 수 있습니다.

e8c1c2a3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1

다음으로 첫 번째 노드인 node1이라는 컨테이너를 실행하고 lab_net 네트워크에 연결합니다.

docker run -d --name node1 --network lab_net --cap-add=NET_ADMIN ubuntu:22.04 sleep infinity

이 명령을 자세히 살펴보겠습니다.

  • docker run: 새 컨테이너를 생성하고 시작하는 표준 명령입니다.
  • -d: 컨테이너를 "분리 (detached)" 모드로 실행합니다. 즉, 백그라운드에서 실행됩니다.
  • --name node1: 컨테이너에 간단하고 기억하기 쉬운 이름을 할당합니다.
  • --network lab_net: 이전에 생성한 가상 네트워크에 컨테이너를 연결합니다.
  • --cap-add=NET_ADMIN: 컨테이너에 NET_ADMIN 권한을 부여합니다. 이 권한은 IP 주소 추가와 같은 네트워크 설정을 수정하는 데 필요합니다.
  • ubuntu:22.04: 표준 Ubuntu 환경을 제공하는 우리가 사용하는 Docker 이미지입니다.
  • sleep infinity: 컨테이너를 활성 상태로 유지하기 위해 무한히 실행되는 간단한 명령입니다.

이제 유사한 명령을 사용하여 두 번째 노드인 node2를 실행합니다.

docker run -d --name node2 --network lab_net --cap-add=NET_ADMIN ubuntu:22.04 sleep infinity

마지막으로 두 노드가 올바르게 실행되고 있는지 확인합니다. docker ps 명령은 현재 실행 중인 모든 컨테이너를 나열합니다.

docker ps

다음과 유사한 출력을 볼 수 있으며, node1node2가 모두 실행 중임을 확인할 수 있습니다.

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
a1b2c3d4e5f6   ubuntu:22.04   "sleep infinity"         5 seconds ago    Up 4 seconds              node2
g7h8i9j0k1l2   ubuntu:22.04   "sleep infinity"         15 seconds ago   Up 14 seconds             node1

두 노드가 동일한 가상 네트워크에서 실행되므로 실험 환경 준비가 완료되었습니다. 다음 단계에서는 IP 주소를 구성하고 연결을 테스트합니다.

ip addr을 사용하여 첫 번째 노드에 고정 IP 구성

이 단계에서는 첫 번째 컨테이너인 node1에 고정 IP 주소를 할당합니다. 고정 IP 는 수동으로 구성되며 변경되지 않는 주소인 반면, 동적 IP 는 종종 DHCP 서버에 의해 자동으로 할당됩니다. 저희 시뮬레이션에서는 고정 IP 를 사용하여 네트워크 구성을 정밀하게 제어합니다.

모든 작업은 호스트 머신의 메인 터미널에서 수행하며, docker exec 명령을 사용하여 node1 컨테이너 내부에서 명령을 실행합니다.

먼저 기본 ubuntu:22.04 이미지는 매우 최소화되어 있습니다. 필요한 네트워킹 도구를 설치해야 합니다. node1 컨테이너 내부의 패키지 목록을 업데이트하는 것부터 시작하겠습니다.

docker exec node1 apt-get update

컨테이너가 최신 패키지 정보를 가져오는 동안 출력이 표시됩니다.

다음으로, iproute2 패키지 ( ip 명령 제공) 와 나중에 사용할 ping 명령을 제공하는 iputils-ping을 설치합니다.

docker exec node1 apt-get install -y iproute2 iputils-ping

도구가 설치되었으므로 이제 node1의 현재 네트워크 구성을 검사해 보겠습니다. 표준 Docker 컨테이너 내부의 네트워크 인터페이스는 일반적으로 eth0으로 명명됩니다.

docker exec node1 ip addr show eth0

출력에는 eth0 인터페이스에 대한 세부 정보가 표시됩니다. Docker 의 내부 DHCP 서버에서 이미 할당된 IP 주소 (예: 192.168.56.2) 가 보일 수 있습니다. 이제 자체 고정 IP 를 추가할 것입니다.

9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.2/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever

이제 node1에 고정 IP 주소 192.168.56.10을 할당합니다. /24는 CIDR 표기법으로 넷마스크 255.255.255.0을 의미하며 네트워크 크기를 정의합니다.

docker exec node1 ip addr add 192.168.56.10/24 dev eth0

이 명령은 성공하면 아무런 출력을 생성하지 않습니다. 변경 사항을 확인하려면 ip addr show eth0 명령을 다시 실행합니다.

docker exec node1 ip addr show eth0

이제 원래 IP 주소 옆에 새 고정 IP 주소가 secondary로 표시되는 것을 볼 수 있습니다. 이는 node1이 이제 192.168.56.10 주소로 구성되었음을 확인합니다.

9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.2/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.56.10/24 scope global secondary eth0
       valid_lft forever preferred_lft forever

동일 서브넷의 두 번째 노드에 고정 IP 구성

이 단계에서는 두 번째 노드인 node2에 고정 IP 주소를 구성합니다. 두 장치가 라우터 없이 직접 통신하려면 동일한 논리적 서브넷에 있어야 합니다. node1에 사용했던 것과 동일한 192.168.56.0/24 서브넷에서 node2에 IP 주소를 할당할 것입니다. 이 설정은 두 장치가 모두 동일한 로컬 네트워크에 속하는 크로스오버 케이블로 연결된 두 대의 PC 를 논리적으로 모방합니다.

먼저 node1에서 했던 것처럼 node2 컨테이너 내부에 필요한 네트워킹 도구를 설치해야 합니다. 패키지 목록을 업데이트하는 것부터 시작합니다.

docker exec node2 apt-get update

다음으로 node2iproute2iputils-ping 패키지를 설치합니다.

docker exec node2 apt-get install -y iproute2 iputils-ping

도구가 설치되었으므로 이제 node2에 고정 IP 주소를 할당할 수 있습니다. node1(192.168.56.10) 과 동일한 서브넷에 있지만 고유한 주소인 192.168.56.11을 사용하겠습니다.

docker exec node2 ip addr add 192.168.56.11/24 dev eth0

이 명령은 node2 컨테이너의 eth0 네트워크 인터페이스에 /24 넷마스크와 함께 192.168.56.11 IP 주소를 추가합니다. 명령이 성공하면 아무런 출력을 생성하지 않습니다.

IP 주소가 올바르게 할당되었는지 확인하기 위해 node2의 네트워크 구성을 검사해 보겠습니다.

docker exec node2 ip addr show eth0

출력에는 새로 추가된 고정 IP 주소가 secondary로 표시되어야 합니다. 이는 node2가 올바르게 구성되었으며 연결을 테스트할 다음 단계를 준비할 준비가 되었음을 확인합니다.

11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.3/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.56.11/24 scope global secondary eth0
       valid_lft forever preferred_lft forever

ping 을 사용하여 노드 간 직접 연결 확인

이 단계에서는 node1node2 간의 네트워크 연결을 테스트합니다. 이제 두 노드 모두 동일한 서브넷에 IP 주소를 가지고 있으므로 직접 통신할 수 있어야 합니다. ping 명령을 사용할 것입니다. ping은 대상 호스트에 작은 데이터 패킷 (ICMP Echo Request) 을 보내고 응답을 기다리는 기본적인 네트워크 유틸리티입니다. 성공적인 응답은 두 장치 간에 네트워크 경로가 존재함을 확인합니다.

이 성공적인 테스트는 두 대의 PC 를 크로스오버 케이블로 연결하는 것과 유사하며, 두 장치 모두 동일한 로컬 네트워크에 있고 서로 직접 통신할 수 있습니다.

먼저 node1에서 node2로 ping 을 시도해 보겠습니다. node1 컨테이너 내부에서 node2의 IP 주소인 192.168.56.11을 대상으로 ping 명령을 실행할 것입니다.

docker exec node1 ping -c 4 192.168.56.11

이 명령을 자세히 살펴보겠습니다.

  • docker exec node1: 다음 명령을 node1 컨테이너 내부에서 실행합니다.
  • ping: 연결을 테스트하는 유틸리티입니다.
  • -c 4: ping에 정확히 4 개의 패킷을 보내고 중지하도록 지시하는 플래그입니다. 이 플래그가 없으면 ping은 무기한 실행됩니다.
  • 192.168.56.11: node2의 대상 IP 주소입니다.

성공적인 출력을 볼 수 있으며, node2로부터 응답을 받습니다.

PING 192.168.56.11 (192.168.56.11) 56(84) bytes of data.
64 bytes from 192.168.56.11: icmp_seq=1 ttl=64 time=0.123 ms
64 bytes from 192.168.56.11: icmp_seq=2 ttl=64 time=0.087 ms
64 bytes from 192.168.56.11: icmp_seq=3 ttl=64 time=0.091 ms
64 bytes from 192.168.56.11: icmp_seq=4 ttl=64 time=0.085 ms

--- 192.168.56.11 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3074ms
rtt min/avg/max/mdev = 0.085/0.096/0.123/0.015 ms

"4 packets transmitted, 4 received, 0% packet loss" 줄은 연결이 작동하고 있음을 확인합니다. 이제 node2에서 node1로 ping 을 보내 반대 방향으로 연결을 확인해 보겠습니다.

docker exec node2 ping -c 4 192.168.56.10

다시 한번, 성공적인 일련의 응답을 볼 수 있으며, 통신이 양방향임을 확인합니다.

PING 192.168.56.10 (192.168.56.10) 56(84) bytes of data.
64 bytes from 192.168.56.10: icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from 192.168.56.10: icmp_seq=2 ttl=64 time=0.088 ms
64 bytes from 192.168.56.10: icmp_seq=3 ttl=64 time=0.092 ms
64 bytes from 192.168.56.10: icmp_seq=4 ttl=64 time=0.089 ms

--- 192.168.56.10 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3081ms
rtt min/avg/max/mdev = 0.088/0.092/0.099/0.004 ms

성공입니다! 두 노드 모두 마치 동일한 로컬 네트워크 세그먼트에 있는 두 대의 컴퓨터처럼 서로 통신할 수 있습니다.

두 번째 노드를 다른 서브넷으로 재구성

이 단계에서는 두 노드 간의 직접 연결을 의도적으로 끊을 것입니다. 이를 위해 node2node1과 완전히 다른 IP 서브넷으로 재구성할 것입니다. 이는 두 장치가 물리적으로 연결되어 있지만 논리적으로 다른 네트워크로 분리된 시나리오를 시뮬레이션합니다.

현재 node1192.168.56.0/24 서브넷에 있습니다. 이제 node2192.168.58.0/24 서브넷으로 이동시킬 것입니다. 세 번째 숫자 (옥텟) 가 다르기 때문에 (5658) 별개의 서브넷으로 간주됩니다.

node2가 새 네트워크에서 완전히 격리되도록 하려면 먼저 eth0 인터페이스에서 모든 기존 IP 주소를 제거해야 합니다. 여기에는 이전에 추가한 고정 IP 와 Docker 가 자동으로 할당한 원래 IP 가 모두 포함됩니다. ip addr flush 명령이 이 작업을 위한 올바른 도구입니다.

docker exec node2 ip addr flush dev eth0

이 명령은 eth0에서 모든 IP 구성을 제거하여 깨끗한 상태를 보장합니다. 성공하면 아무런 출력을 생성하지 않아야 합니다.

이제 새 서브넷에 속하는 새 IP 주소인 192.168.58.11을 추가해 보겠습니다.

docker exec node2 ip addr add 192.168.58.11/24 dev eth0

변경 사항을 확인하기 위해 node2의 네트워크 구성을 다시 검사해 보겠습니다.

docker exec node2 ip addr show eth0

모든 이전 IP 주소가 사라지고 새 IP 주소 (192.168.58.11) 만 남아 있는 것을 볼 수 있습니다. 이는 node2가 더 이상 192.168.56.0/24 서브넷에 있지 않음을 확인합니다.

11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.58.11/24 scope global eth0
       valid_lft forever preferred_lft forever

node1192.168.56.0/24 서브넷에 있고 node2192.168.58.0/24 서브넷에 있으므로 이제 논리적으로 격리되었습니다.

연결 테스트 및 실패 관찰

이 마지막 단계에서는 노드 간에 다시 ping 을 시도할 것입니다. 이제 node2가 새 서브넷에 진정으로 격리되었으므로 통신이 실패할 것으로 예상하지만, 네트워킹 계층이 작동하는 방식을 보여주는 두 가지 다른 중요한 방식으로 실패할 것입니다.

먼저 node1에서 node2의 새 IP 주소 (192.168.58.11) 로 ping 을 시도해 보겠습니다.

docker exec node1 ping -c 4 192.168.58.11

출력을 관찰하십시오. 명령이 시간 초과되어 100% 패킷 손실이 발생합니다.

PING 192.168.58.11 (192.168.58.11) 56(84) bytes of data.

--- 192.168.58.11 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3076ms

이 시간 초과는 node1이 여전히 Docker 네트워크로의 경로를 가지고 있기 때문에 발생하며, 따라서 ping 패킷을 보냅니다. 네트워크는 이를 node2로 전달합니다. 그러나 node2는 더 이상 해당 네트워크에 있지 않고 돌아갈 경로가 없으므로 응답을 보낼 수 없습니다. node1에서의 ping 은 응답을 받지 못합니다.

다음으로, 다른 방향을 테스트해 보겠습니다. node2에서 node1로 ping 을 시도해 보세요.

docker exec node2 ping -c 4 192.168.56.10

이번에는 거의 즉시 다른 오류 메시지가 표시됩니다.

ping: connect: Network is unreachable

ping: connect: Network is unreachable 메시지는 중요합니다. 이는 node2의 운영 체제에서 즉시 오는 응답입니다. OS 가 라우팅 테이블을 확인하고 대상 192.168.56.10이 경로가 없는 네트워크에 있음을 확인하고 패킷 전송 시도조차 거부했음을 의미합니다. 이는 모든 경로를 지운 ip addr flush를 사용한 직접적인 결과이며, 컨테이너를 다른 네트워크로부터 완전히 격리시켰습니다.

이 실습은 IP 서브넷팅 및 라우팅의 중요한 역할을 성공적으로 시연했습니다. 장치가 동일한 서브넷에 있으면 직접 통신할 수 있습니다. 다른 서브넷에 있는 경우, 적절한 경로를 가진 라우터와 같은 Layer 3 장치가 트래픽을 전달해야 합니다.

요약

이 실습에서는 사용자 정의 브리지 네트워크에 연결된 Docker 컨테이너를 사용하여 2 노드 네트워크 환경을 시뮬레이션하는 방법을 배웠습니다. ip addr 명령을 사용하여 네트워크 인터페이스에 고정 IP 주소를 구성하는 필수 Linux 기술을 연습했습니다. 두 노드 모두에 동일한 서브넷의 IP 주소를 할당함으로써 ping 유틸리티를 사용하여 로컬 네트워크 세그먼트에서의 통신에 대한 기본적인 요구 사항을 입증하며 노드 간의 직접적인 Layer 3 연결을 성공적으로 확인했습니다.

이 실습은 원래 네트워크 구성을 완전히 플러시한 후 다른 서브넷의 IP 주소로 한 노드를 재구성함으로써 중요한 네트워킹 개념을 더욱 보여주었습니다. 이후 ping을 통한 통신 시도는 한 방향에서는 시간 초과, 다른 방향에서는 'Destination Host Unreachable' 오류라는 두 가지 뚜렷한 결과로 실패했습니다. 이 결과는 다른 논리적 서브넷에 있는 노드는 라우터 없이는 직접 통신할 수 없다는 것을 효과적으로 보여주었으며, 라우팅 테이블과 인터페이스 구성이 네트워크 연결에 어떻게 영향을 미치는지 강조했습니다.