VirtualBox에서 Ubuntu를 라우터로 만들어봤다

전희준·2026년 9월 19일

Network

목록 보기
9/10
post-thumbnail

지난 실습에서는 Ubuntu VM 두 대를 같은 네트워크에 놓고 ping, ARP, TCP 통신을 확인했어요.

이번에는 조금 더 나아가서 두 VM을 아예 다른 네트워크로 분리해봤습니다. 그리고 그 사이에 Ubuntu VM을 한 대 더 두고 라우터 역할을 맡겼어요.

처음에는 “인터페이스 두 개에 IP만 넣으면 알아서 통신하지 않을까?” 싶었는데, 실제로 해보니 그렇지 않았어요. 라우터의 IP Forwarding도 켜야 하고, VM1과 VM2에도 상대 네트워크로 가는 길을 알려줘야 했습니다.

중간에 인터페이스가 안 보이기도 했고, 명령어를 잘못 입력하기도 했고, 마지막 traceroute 결과는 예상과 다르게 나오기도 했어요. 이번 글에는 성공한 결과만 적기보다 그 과정도 같이 남겨보려고 해요.


실습 환경

사용한 환경은 다음과 같아요.

  • Mac (Apple Silicon)
  • VirtualBox
  • Ubuntu Server ARM64
  • VM1, RouterVM, VM2

IP는 아래처럼 구성했습니다.

장비인터페이스IP 주소
VM1enp0s9192.168.10.10/24
RouterVMenp0s9192.168.10.1/24
RouterVMenp0s10192.168.20.1/24
VM2enp0s9192.168.20.20/24

그림으로 보면 이런 구조예요.

VM1                 RouterVM                  VM2
192.168.10.10       192.168.10.1             192.168.20.20
       │                 │                          │
       └── labnet1 ──────┤                          │
                         ├── 192.168.20.1 ─ labnet2 ┘

VM1이 있는 192.168.10.0/24와 VM2가 있는 192.168.20.0/24는 서로 다른 네트워크입니다. 그 사이에서 RouterVM이 패킷을 넘겨주는 게 이번 실습의 목표였어요.

RouterVM에는 위의 내부망 인터페이스 두 개 외에 인터넷 연결용 NAT 인터페이스 enp0s8도 남겨뒀습니다.


1. VM2를 다른 서브넷으로 옮기기

기존에는 VM1과 VM2가 모두 192.168.10.0/24에 있었어요. 라우팅 실습을 하려면 둘을 다른 네트워크로 나눠야 해서 VM2의 주소를 192.168.20.20/24로 바꿨습니다.

VM2에서 Netplan 파일을 열고 내부 네트워크용 인터페이스인 enp0s9를 수정했어요.

sudo nano /etc/netplan/00-installer-config.yaml

제가 사용한 설정은 다음과 같습니다.

network:
  ethernets:
    enp0s8:
      dhcp4: true
      dhcp6: true
      match:
        macaddress: 08:00:27:41:ac:0e
      set-name: enp0s8
    enp0s9:
      dhcp4: false
      addresses:
        - 192.168.20.20/24
      accept-ra: true
  version: 2

여기 적힌 MAC 주소는 제 VM에서 확인한 값이에요. 다른 환경에서 따라 한다면 이 부분까지 똑같이 복사하면 안 되고, 원래 자신의 설정에 들어 있던 값을 사용해야 합니다.

파일을 저장한 뒤 아래 명령어로 문법을 확인하고 적용했어요.

sudo netplan generate
sudo netplan apply
ip -br addr

enp0s9 옆에 192.168.20.20/24가 보이는 걸 확인했습니다.


2. 아무 설정 없이 먼저 ping을 보내봤다

VM2의 주소를 바꾼 다음, VM1에서 바로 ping을 보내봤어요.

ping 192.168.20.20

예상대로 아무 응답도 오지 않았습니다.

VM1이 알고 있는 내부 네트워크는 192.168.10.0/24뿐이에요. 192.168.20.20이 다른 네트워크라는 건 알 수 있지만, 그쪽으로 가려면 누구에게 패킷을 보내야 하는지는 모르는 상태였습니다.

RouterVM을 만들어뒀다고 해서 VM1과 VM2가 자동으로 그 장비를 찾아가는 건 아니었어요. 이 실패 화면을 보고 나니 정적 경로를 왜 설정해야 하는지 조금 더 와닿았습니다.


3. RouterVM을 두 네트워크에 연결하기

RouterVM은 양쪽 네트워크에 한 발씩 걸치고 있어야 해요.

그래서 내부망 인터페이스를 다음과 같이 설정했습니다.

enp0s9  = 192.168.10.1/24
enp0s10 = 192.168.20.1/24

Netplan 설정은 이런 형태로 넣었어요.

network:
  version: 2
  ethernets:
    enp0s8:
      dhcp4: true
    enp0s9:
      dhcp4: false
      dhcp6: false
      addresses:
        - 192.168.10.1/24
    enp0s10:
      dhcp4: false
      dhcp6: false
      addresses:
        - 192.168.20.1/24

설정을 적용한 뒤 RouterVM에서 VM1과 VM2로 각각 ping을 보내봤습니다.

ping -c 4 192.168.10.10
ping -c 4 192.168.20.20

두 번 모두 패킷 손실 없이 성공했어요.

이때 상태를 정리하면 이랬습니다.

RouterVM ↔ VM1  성공
RouterVM ↔ VM2  성공
VM1 ↔ VM2        실패

RouterVM이 두 VM과 각각 통신할 수 있다는 건 인터페이스와 VirtualBox 내부 네트워크 설정은 제대로 됐다는 뜻이에요. 하지만 아직 RouterVM이 한쪽에서 받은 패킷을 다른 쪽으로 넘겨주지는 않고 있었습니다.


4. IP Forwarding 켜기

Ubuntu는 인터페이스가 여러 개 있다고 해서 기본적으로 라우터처럼 동작하지 않아요. 패킷을 다른 인터페이스로 전달하도록 IP Forwarding을 켜줘야 합니다.

먼저 현재 값을 확인했어요.

sysctl net.ipv4.ip_forward

결과는 0이었습니다.

net.ipv4.ip_forward = 0

이 값을 1로 바꿨어요.

sudo sysctl -w net.ipv4.ip_forward=1

캡처를 보면 처음에는 =1을 빼고 입력해서 오류가 났어요. 다시 정확히 입력한 뒤에는 아래처럼 값이 바뀐 걸 확인할 수 있었습니다.

net.ipv4.ip_forward = 1

사소한 실수였지만, sysctl -w로 값을 바꿀 때는 설정 이름만 쓰는 게 아니라 변경할 값까지 함께 적어야 한다는 걸 확실히 기억하게 됐어요.

참고로 이 방법은 임시 설정이라 RouterVM을 재부팅하면 다시 원래대로 돌아갈 수 있습니다. 영구적으로 사용하려면 /etc/sysctl.d/ 아래의 설정 파일에 다음 값을 넣어야 해요.

net.ipv4.ip_forward=1

이번에는 동작 원리를 확인하는 실습이 목적이라 우선 임시 설정으로 진행했습니다.


5. 양쪽 VM에 정적 경로 추가하기

RouterVM이 패킷을 전달할 준비는 끝났지만, VM1과 VM2는 여전히 RouterVM을 이용해야 한다는 사실을 몰라요. 이번에는 각 VM의 라우팅 테이블에 직접 경로를 추가했습니다.

먼저 VM1에서 실행했어요.

sudo ip route add 192.168.20.0/24 via 192.168.10.1
ip route

라우팅 테이블 아래쪽에 다음 줄이 생겼습니다.

192.168.20.0/24 via 192.168.10.1 dev enp0s9

말로 풀면 “192.168.20.0/24로 갈 패킷은 192.168.10.1에 있는 RouterVM으로 보내라”는 뜻이에요.

VM2에는 반대 방향의 경로를 넣었습니다.

sudo ip route add 192.168.10.0/24 via 192.168.20.1
ip route

VM2에도 다음 줄이 추가됐어요.

192.168.10.0/24 via 192.168.20.1 dev enp0s9

처음에는 VM1 쪽 경로만 있으면 되지 않을까 생각했는데, 요청이 도착한 뒤 응답이 돌아올 길도 필요했어요. 결국 통신은 항상 왕복이라는 기본적인 사실이 여기서도 그대로 적용됐습니다.

이 명령으로 추가한 경로 역시 재부팅하면 사라질 수 있어요. 실제로 계속 사용할 환경이라면 Netplan의 routes 항목에 영구 설정하는 편이 맞습니다.


6. 드디어 VM1과 VM2가 통신했다

이제 VM1에서 VM2로 다시 ping을 보내봤어요.

ping -c 4 192.168.20.20

이번에는 네 개의 패킷이 모두 돌아왔습니다. 손실률도 0%였어요.

반대 방향도 확인했습니다.

ping -c 4 192.168.10.10

VM2에서 VM1로 보낸 ping도 정상적으로 돌아왔어요. 이걸로 두 서브넷 사이의 양방향 통신을 확인했습니다.

응답을 보면 TTL이 63으로 표시돼요. 초기 TTL이 64인 패킷이 RouterVM을 한 번 지나면서 1 줄어든 것으로 볼 수 있습니다. 단순히 ping이 성공한 것뿐 아니라, 중간에 라우터를 거쳤다는 흔적도 확인할 수 있었어요.


7. traceroute 결과는 생각과 조금 달랐다

마지막으로 VM1에서 VM2까지의 경로를 확인해봤습니다.

traceroute 192.168.20.20

첫 번째 홉에는 예상대로 192.168.10.1이 나타났어요.

1  192.168.10.1 (192.168.10.1) ...

이 주소는 RouterVM의 VM1 쪽 인터페이스입니다. VM1이 정적 경로에 따라 RouterVM으로 패킷을 보내고 있다는 건 확인할 수 있었어요.

그런데 두 번째 줄부터는 목적지 주소 대신 * * *만 계속 표시됐습니다.

처음에는 설정을 잘못했나 싶었어요. 하지만 VM1과 VM2 사이의 ping은 양쪽 모두 성공한 상태였죠. 따라서 이 결과만 보고 라우팅 전체가 실패했다고 판단하기는 어려웠습니다.

기본 traceroute는 UDP 패킷을 보내고 각 구간에서 돌아오는 ICMP 응답을 이용해 경로를 표시해요. 중간 장비나 목적지가 그 응답을 보내지 않거나 방화벽이 막고 있으면, 실제 통신은 가능해도 화면에는 *가 나타날 수 있습니다.

ICMP 방식으로 확인하려면 다음 명령을 사용할 수도 있어요.

sudo traceroute -I 192.168.20.20

이번 결과에서는 최소한 다음 두 가지를 확인했습니다.

  • 첫 번째 홉이 192.168.10.1이므로 VM1의 패킷은 RouterVM으로 전달되고 있었어요.
  • 이후의 *는 traceroute가 기다리던 응답을 받지 못했다는 뜻이며, ping 성공 여부와는 따로 봐야 했어요.

실습하면서 막혔던 부분

RouterVM에서 인터페이스가 하나만 보였다

처음 RouterVM에서 ip -br addr를 실행했을 때 NAT용 enp0s8만 보였어요. 당연히 enp0s9와 enp0s10에 IP를 넣으려고 했는데, 인터페이스 자체가 없으니 다음 단계로 갈 수가 없었습니다.

RouterVM을 종료하고 VirtualBox 네트워크 설정을 다시 확인했어요.

어댑터 1: NAT
어댑터 2: 내부 네트워크 labnet1
어댑터 3: 내부 네트워크 labnet2

어댑터 2와 3의 활성화 여부와 가상 케이블 연결 상태를 확인한 뒤 다시 부팅하니 세 인터페이스가 모두 나타났습니다.

Linux 설정만 계속 들여다볼 뻔했는데, 문제는 그보다 앞단인 VirtualBox 설정에 있었어요. 인터페이스 자체가 안 보일 때는 게스트 OS 안의 설정뿐 아니라 가상 하드웨어부터 확인해야 한다는 걸 배웠습니다.

다른 서브넷으로 바꾸자 ping이 멈췄다

VM2를 192.168.20.20으로 바꾼 직후 VM1에서 보낸 ping은 응답이 없었어요. 이건 장애라기보다 이번 실습에서 일부러 만든 상태였습니다.

RouterVM에 IP를 넣는 것만으로는 부족했고, IP Forwarding과 양방향 정적 경로까지 설정한 뒤에야 통신이 됐어요. 덕분에 각 설정이 왜 필요한지 순서대로 확인할 수 있었습니다.

IP Forwarding 명령어를 잘못 입력했다

처음에는 아래처럼 입력했어요.

sudo sysctl -w net.ipv4.ip_forward

값이 빠져 있어서 오류가 발생했고, =1을 붙여 다시 실행했습니다.

sudo sysctl -w net.ipv4.ip_forward=1

마지막에는 조회 명령을 한 번 더 실행해 실제 값이 1로 바뀌었는지 확인했어요.

traceroute가 목적지까지 표시되지 않았다

첫 번째 홉 뒤에 별표가 이어지는 결과가 가장 헷갈렸어요. 다만 ping이 양방향으로 성공했으므로, “별표가 있으니 네트워크가 끊겼다”라고 결론 내리지는 않았습니다.

도구마다 사용하는 패킷과 기다리는 응답이 다르기 때문에 여러 결과를 같이 봐야 했어요. 다음에 이어서 실습한다면 방화벽 상태를 확인하고 traceroute -I 결과도 비교해보고 싶습니다.


이번에 배운 점

이번 실습 전에는 라우터를 그냥 서로 다른 네트워크 사이에 있는 장비 정도로만 생각했어요. 직접 구성해보니 실제 통신을 위해서는 몇 가지 조건이 모두 맞아야 했습니다.

먼저 라우터는 양쪽 네트워크에 직접 연결된 인터페이스가 있어야 했어요. 그리고 Linux가 받은 패킷을 다른 인터페이스로 넘기도록 IP Forwarding을 켜야 했습니다. 마지막으로 각 호스트도 목적지 네트워크로 갈 때 어느 라우터를 이용할지 알고 있어야 했어요.

특히 아래 두 줄을 직접 라우팅 테이블에서 확인한 게 기억에 남습니다.

VM1: 192.168.20.0/24 via 192.168.10.1
VM2: 192.168.10.0/24 via 192.168.20.1

라우팅 테이블을 막연한 목록으로 봤을 때보다 “이 목적지로 가려면 다음에는 어디로 보내라”는 길 안내표로 생각하니 훨씬 이해하기 쉬웠어요.

또 traceroute의 별표처럼 한 명령의 결과만 보면 오해할 수 있는 상황도 경험했습니다. ping, 라우팅 테이블, 인터페이스 상태를 함께 확인하면서 판단하는 습관이 필요하다는 것도 느꼈어요.


마무리

이번 실습에서 진행한 순서는 이렇습니다.

VM1과 VM2를 서로 다른 서브넷으로 분리
→ RouterVM을 두 네트워크에 연결
→ IP Forwarding 활성화
→ VM1과 VM2에 정적 경로 추가
→ 양방향 ping 성공 확인
→ traceroute로 첫 번째 홉 확인

명령어만 놓고 보면 길지 않은 실습이지만, 직접 실패 상태부터 만들어보니 게이트웨이와 라우팅 테이블이 왜 필요한지 전보다 확실히 이해할 수 있었어요.

AWS에서 VPC, Subnet, Route Table을 처음 봤을 때는 각각 따로 떨어진 기능처럼 느껴졌는데, 이번 실습을 하고 나니 결국 패킷이 어느 네트워크를 거쳐 어디로 가야 하는지 정해주는 과정이라는 점도 조금씩 연결되기 시작했습니다.

다음에는 RouterVM에서 tcpdump를 실행해 VM1에서 온 ICMP 패킷이 실제로 enp0s9로 들어오고 enp0s10으로 나가는 장면까지 확인해볼 생각이에요. 임시로 넣은 IP Forwarding과 정적 경로를 재부팅 후에도 유지되도록 바꾸는 작업도 이어서 해보려고 합니다.

0개의 댓글