Network - 네트워크 기초(veth, bridge, routing, NAT, port-forward)

2026. 1. 5. 22:09·CKA

이 글은 Linux network namespace(netns) 를 처음 접하는 사람을 대상으로, “컨테이너(Docker)가 네트워크를 어떻게 격리하고 연결하는지”를 직접 명령으로 재현해보는 정리입니다.
이론(OSI) 대신, 리눅스 관점에서 실제로 무엇이 생기고(인터페이스/라우팅/Neighbor(ARP)), 어떤 설정이 필요한지를 따라가며 이해하는 방식으로 구성합니다.

또한, 학습 과정에서 많이 헷갈리는 포인트(예: ip link에서 보이는 lo/eth0, ARP vs route, veth가 라우팅을 “해주는지”, 왜 /24인지, bridge에 master로 붙이는 이유, 포워딩/NAT가 필요한 이유 등)를 중간중간 보강 설명으로 함께 넣었습니다.


1) Network Namespace란?

컨테이너는 “호스트와 분리된 공간”에서 동작합니다. 네임스페이스(namespace)는 이 분리를 구현하는 리눅스 기능입니다.

비유로 설명하면:

  • 호스트(집) 안에
  • 컨테이너마다 방(네임스페이스) 을 하나씩 주는 구조

각 방은 독립된 세계처럼 보입니다.

  • 방 안(컨테이너)은 자기 방의 네트워크 인터페이스/라우팅/Neighbor(ARP) 테이블만 봅니다.
  • 집 전체를 관리하는 부모(호스트 root)는 모든 방을 다 볼 수 있고, 원하면 방들 사이를 연결할 수도 있습니다.

네트워크 관점에서 netns의 핵심은 이겁니다:

  • 컨테이너(netns)는 호스트의 eth0, 라우팅 테이블, ARP 테이블을 그대로 보지 못합니다.
  • 대신 컨테이너는 자기만의 가상 인터페이스, 자기만의 라우팅, 자기만의 Neighbor(ARP) 테이블을 “별도로” 갖습니다.

2) ip link에 보이는 lo와 eth0는 뭐야?

네트워크를 실습하기 전에, 많은 분들이 여기서부터 헷갈립니다.

  • lo(loopback)
    • “자기 자신(localhost)으로 통신하는” 내부용 가상 인터페이스
    • 보통 127.0.0.1(IPv4), ::1(IPv6)
  • eth0
    • 외부 네트워크(LAN/VPC)에 실제로 연결되는 “첫 번째” NIC(가상/물리)
    • VM에서는 보통 이게 인터넷/사내망으로 나가는 기본 출구입니다.

즉,

  • lo = 내부 통신 전용
  • eth0 = 외부 네트워크 출구

네임스페이스로 들어가면 eth0이 안 보일 수 있는데, 이건 “사라진” 게 아니라 네임스페이스가 분리되어서 “보이지 않는 것”입니다.


3) 기본 준비: netns 만들고 내부 상태 확인하기

3.1 네임스페이스 생성/목록

sudo ip netns add red
sudo ip netns add blue

ip netns list

3.2 호스트의 인터페이스 확인

ip link

3.3 네임스페이스 내부에서 명령 실행

두 가지 방법이 있습니다.

(1) ip netns exec 사용

sudo ip netns exec red ip link
sudo ip netns exec blue ip link

(2) ip -n <ns> 축약형 (ip 명령에만 적용)

sudo ip -n red link
sudo ip -n blue link

대부분 처음엔 lo만 보이고, eth0은 보이지 않습니다.

실습 팁: netns 안에서 loopback이 DOWN이면 일부 동작이 이상할 수 있어 먼저 올려주는 게 좋습니다.

sudo ip -n red link set lo up
sudo ip -n blue link set lo up

3.4 ARP 테이블과 라우팅 테이블도 분리된다

ARP는 예전엔 arp -n을 많이 썼지만, 요즘은 ip neigh를 권장합니다.

ip neigh            # 호스트 neighbor(ARP) 테이블
sudo ip -n red neigh
sudo ip -n red route

처음 만든 netns는 네트워크 연결이 없어서 neighbor/route가 거의 비어 있는 게 정상입니다.


4) ARP Table vs Route Table: 무엇이 다르나?

여기서 개념을 한 번 잡고 가면 이후가 훨씬 편해집니다.

  • Route Table(L3): “목적지 IP로 가려면 어느 인터페이스로/어느 게이트웨이로 보낼까?”
  • ARP/Neighbor Table(L2): “같은 네트워크로 직접 보낼 때, 그 IP의 MAC 주소는 뭐지?”

통신 흐름은 일반적으로:

  1. Route Table로 “다음 홉(next hop)” 결정
  2. ARP/Neighbor로 “다음 홉의 MAC 주소” 해석
  3. L2 프레임으로 실제 전송

즉, ARP와 route는 경쟁 관계가 아니라 연쇄 관계입니다.


5) 네임스페이스 둘을 직접 연결하기: veth pair(가상 케이블)

이제 red와 blue를 연결해보겠습니다.

5.1 veth는 라우터가 아니다(중요)

많이 하는 오해가 “veth로 연결하면 서로 라우팅이 되는 거 아니야?”인데, 아닙니다.

  • veth는 양 끝이 연결된 가상 이더넷 케이블입니다.
  • 라우팅(다른 네트워크로 넘기기)은 “라우터/게이트웨이 + 라우팅 테이블”이 하는 일입니다.
  • veth는 단지 L2 링크를 제공하고, 그 위에서 ARP가 돌고 IP가 오갈 수 있게 해줍니다.

5.2 veth pair 생성

sudo ip link add veth-red type veth peer name veth-blue

5.3 각 끝을 네임스페이스로 이동

sudo ip link set veth-red netns red
sudo ip link set veth-blue netns blue

5.4 IP 할당: 왜 /24지? /32면 안 돼?

다음 명령을 보겠습니다.

sudo ip -n red addr add 192.168.5.1/24 dev veth-red
sudo ip -n blue addr add 192.168.5.2/24 dev veth-blue

여기서 /24를 쓰는 이유는 “red와 blue를 같은 서브넷으로 묶어서, 게이트웨이 없이 직접 통신”시키기 위함입니다.

  • /24면 red는 192.168.5.0/24가 “직접 연결된 네트워크”라고 인식하고,
    192.168.5.2는 “내 링크 안”이므로 게이트웨이 없이 ARP로 MAC을 찾고 바로 전송합니다.
  • /32면 192.168.5.1 “단일 주소만” 소유한 인터페이스가 되어,
    192.168.5.2로 가는 “directly connected route”가 생기지 않아
    별도 라우트/게이트웨이가 없으면 통신이 안 됩니다.

즉, 실습 의도가 “같은 네트워크에서 직접 통신”이면 /24가 자연스럽습니다.

5.5 인터페이스 up

sudo ip -n red link set veth-red up
sudo ip -n blue link set veth-blue up

5.6 통신 확인 + ARP(Neighbor) 확인

sudo ip -n red ping -c 2 192.168.5.2
sudo ip -n red neigh

여기서 ARP(Neighbor)가 왜 연관되냐면:

  • red가 192.168.5.2로 보내려면 L2 MAC 주소가 필요
  • red는 ARP 요청을 보내 blue의 veth MAC을 알아냄
  • 그 결과가 neighbor table에 저장됨

즉, veth + 같은 서브넷 통신 = route는 “직접 링크로 보낸다” 결정, ARP는 “MAC을 알아낸다” 역할입니다.


6) 네임스페이스가 여러 개라면? bridge(가상 스위치)를 만든다

네임스페이스가 3개/4개가 되면 veth 직결은 비효율적입니다. 현실에서 스위치가 필요하듯, 내부 가상 네트워크에도 스위치가 필요합니다.

여기서 Linux bridge가 스위치 역할을 합니다.

6.1 브릿지 생성 및 up

sudo ip link add vnet0 type bridge
sudo ip link set vnet0 up

6.2 master vnet0는 뭐 하는 거야?

질문이 자주 나오는 부분입니다:

sudo ip link set veth-blue-br master vnet0

이건 veth-blue-br 인터페이스를 bridge(vnet0)의 “포트(port)”로 붙이는 것입니다.

  • vnet0 = 스위치 본체
  • veth-blue-br = 스위치에 꽂는 케이블(포트)
  • master vnet0 = “이 포트를 vnet0 스위치에 연결해라”

이걸 안 하면, 네임스페이스에서 나온 트래픽이 브릿지를 통해 다른 포트로 스위칭되지 못합니다.

6.3 네임스페이스를 브릿지에 붙이는 veth 생성

직결 veth는 지우고(선택), 브릿지 연결용 veth를 새로 만듭니다.

(선택) 기존 직결 veth 삭제

sudo ip link del veth-red

red 연결

sudo ip link add veth-red type veth peer name veth-red-br
sudo ip link set veth-red netns red
sudo ip link set veth-red-br master vnet0
sudo ip link set veth-red-br up

blue 연결

sudo ip link add veth-blue type veth peer name veth-blue-br
sudo ip link set veth-blue netns blue
sudo ip link set veth-blue-br master vnet0
sudo ip link set veth-blue-br up

6.4 네임스페이스 쪽 IP 설정 및 up

여기서는 내부 네트워크를 192.168.15.0/24로 둡니다.

sudo ip -n red addr add 192.168.15.1/24 dev veth-red
sudo ip -n blue addr add 192.168.15.2/24 dev veth-blue

sudo ip -n red link set veth-red up
sudo ip -n blue link set veth-blue up

통신 확인:

sudo ip -n red ping -c 2 192.168.15.2

7) 호스트에서 네임스페이스로 접근하고 싶다: 브릿지에 호스트 IP 부여

현재 네임스페이스는 192.168.15.0/24 내부망에 있고, 호스트는 그 네트워크에 “브릿지 인터페이스는 있지만 IP가 없을 수” 있습니다.

브릿지(vnet0)에 호스트 IP를 주면 호스트가 내부망의 “참가자”가 됩니다.

sudo ip addr add 192.168.15.5/24 dev vnet0

이제 호스트에서:

ping -c 2 192.168.15.1
ping -c 2 192.168.15.2

8) 네임스페이스에서 LAN/인터넷으로 나가기: 라우팅 + IP Forward + NAT

이 파트가 가장 중요한데, 여기서 “왜 포워딩이 필요하고, 왜 NAT가 필요한지”가 자주 헷갈립니다.

가정:

  • 호스트 외부 LAN: 192.168.1.0/24
  • 호스트 eth0: 192.168.1.2
  • 내부 브릿지: 192.168.15.0/24
  • 호스트 vnet0: 192.168.15.5
  • blue: 192.168.15.2

8.1 네임스페이스에 게이트웨이(호스트) 라우트 추가

sudo ip -n blue route add default via 192.168.15.5

8.2 왜 ip_forward가 필요하나?

리눅스는 기본적으로 “라우터”가 아닙니다. 즉,

  • vnet0로 들어온 패킷을 eth0로 “전달(forward)”하는 기능이 기본 OFF입니다.

켜기:

sudo sysctl -w net.ipv4.ip_forward=1

8.3 왜 NAT(MASQUERADE)가 필요하나?

포워딩만 켜면 패킷은 나가지만, 응답이 돌아오지 않을 수 있습니다.

이유:

  • blue의 출발지 IP는 192.168.15.2 (LAN 입장에선 모르는 사설망)
  • LAN의 서버/라우터는 192.168.15.0/24로 가는 경로를 몰라서 reply가 유실

그래서 호스트가 출발지 주소를 자기(LAN IP)로 바꿔서 내보내면(reply가 호스트로 돌아옴), 호스트가 다시 내부로 전달할 수 있습니다.

sudo iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -o eth0 -j MASQUERADE

테스트:

sudo ip -n blue ping -c 2 192.168.1.3
sudo ip -n blue ping -c 2 8.8.8.8

NAT 없이도 가능하지만, 그 경우 LAN 라우터/호스트들에 192.168.15.0/24 via 192.168.1.2 같은 “리턴 경로”를 라우팅으로 알려줘야 합니다.


9) 외부에서 내부(네임스페이스 서비스)로 들어오기: 두 가지 방법

blue가 192.168.15.2:80에서 웹을 띄운다고 합시다.

외부에서 접근 방법은 두 가지:

옵션 A) 외부에 라우트 추가(사설망 경로 공개)

외부 호스트/라우터에:

  • 192.168.15.0/24는 호스트(192.168.1.2)로 가라고 추가

옵션 B) 포트 포워딩(DNAT)

“호스트의 80포트로 들어오면 blue의 80으로 전달”

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.15.2:80
sudo iptables -A FORWARD -p tcp -d 192.168.15.2 --dport 80 -j ACCEPT

이 모델이 Docker의 -p 8080:80 같은 포트 노출과 동일 계열입니다.


10) 이게 Docker/Kubernetes와 어떻게 이어지나?

이 글에서 손으로 만든 구조는 컨테이너 네트워킹의 원형입니다.

  • 컨테이너 = netns
  • 컨테이너 NIC = veth 한쪽 끝
  • 호스트 쪽 veth 끝들이 모이는 곳 = bridge(또는 OVS)
  • 외부로 나갈 때 = 호스트가 게이트웨이 + ip_forward + NAT
  • 외부에서 들어올 때 = 라우팅 공개 or DNAT(port-forward)
  • ARP/Neighbor = 같은 링크에서 “MAC 해석”을 담당 (route 결정 이후 단계)

Kubernetes에서는 CNI 플러그인이 이 작업을 자동화하고, Service(ClusterIP/NodePort/LB)는 iptables/ipvs 등과 결합해 트래픽 흐름을 구성합니다.


11) 실습 점검용 명령 모음

# 네임스페이스
ip netns list

# ns 내부 상태
ip -n red link
ip -n red addr
ip -n red route
ip -n red neigh

# 호스트 상태
ip link
ip addr
ip route
bridge link

# 포워딩/NAT
sysctl net.ipv4.ip_forward
iptables -t nat -S
iptables -S

마무리 요약

  • lo는 로컬 통신, eth0은 외부 네트워크 출구
  • veth는 “라우터”가 아니라 “가상 케이블”
  • route table은 “어디로 보낼지”, ARP(neigh)는 “MAC이 뭔지”
  • bridge는 “가상 스위치”, master vnet0는 “스위치 포트로 연결”
  • 외부로 나가려면 “라우트 + ip_forward + NAT(또는 외부 라우팅 추가)”
  • 외부에서 들어오려면 “사설망 라우팅 공개” 또는 “DNAT 포트포워딩”

 

참고

  • 네트워크 네임스페이스 실습에서 서로 ping이 안 되면 먼저 IP 설정에 NETMASK(CIDR) 가 포함됐는지 확인한다.
    • 예: 192.168.1.10/24 처럼 /24 를 붙여야 같은 대역으로 인식되고 라우팅/ARP 동작이 정상화된다.
    ip -n red addr add 192.168.1.10/24 dev veth-red
  • 다음으로 FirewallD / iptables 규칙 때문에 ICMP(ping)나 포워딩이 막히는지 점검한다.
    • 학습 환경에서는 (1) 필요한 트래픽을 허용하는 규칙을 추가하거나, (2) 실습 편의상 방화벽/iptables를 일시 비활성화해서 원인 분리(트러블슈팅)를 한다.

'CKA' 카테고리의 다른 글

Network - CNI(Container Network Interface)  (0) 2026.01.05
Network - Docker Network  (0) 2026.01.05
Network - 네트워크 기초(DNS)  (0) 2026.01.05
Network - 네트워크 기초(스위치, 라우터, 게이트웨이)  (0) 2026.01.05
Storage - 정리  (0) 2026.01.05
'CKA' 카테고리의 다른 글
  • Network - CNI(Container Network Interface)
  • Network - Docker Network
  • Network - 네트워크 기초(DNS)
  • Network - 네트워크 기초(스위치, 라우터, 게이트웨이)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      자바
      @discriminatorcolumn
      @discriminatorvalue
      reentarantlock
      스레드
      requset scope
      락
      프록시 팩토리
      typequery
      gesingleresult
      고급
      @args
      조회 성능 최적화
      버퍼
      WAS
      log trace
      프록시
      Thread
      Target
      JPQL
      cglib
      jpq
      빈 후처리기
      양방향 맵핑
      단방향 맵핑
      jdk 동적 프록시
      @within
      hibernate5module
      페치 조인
      김영한
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Network - 네트워크 기초(veth, bridge, routing, NAT, port-forward)
    상단으로

    티스토리툴바