Kubernetes

[ Kans 3 Study - 1.2 ] 컨테이너 네트워크 & IP Tables (1)

su''@ 2024. 9. 1. 03:34

 

CloudNetaStudy - Kubernets Networtk 3기 실습 스터디 게시글입니다.

 

  • 컨테이너네트워크 네임스페이스호스트네트워크 격리 환경을 구성됩니다.
  • 리눅스에서 방화벽 기능을 제공하는 IPtables호스트컨테이너의 통신에 관여를 합니다.
  • [Sam.0] Netfilter and iptables - Link , A Deep Dive into Iptables and Netfilter Architecture - Link
 

A Deep Dive into Iptables and Netfilter Architecture

netfilter와 iptables를 이해하기에 좋은 자료입니다.

netpple.github.io

 

[ 1.  도커 없이 네트워크 네임스페이스 환경에서 통신 구성   ]

1.1 RED ↔ BLUE 네트워크 네임스페이스 간 통신
  • 결론 : 네트워크 네임스페이스 생성 시 호스트 네트워크와 구별된다
  • 실습 : 터미널1~3 모두 관리자로 실습 진행
    # 터미널1~3 관리자
    sudo su -
    whoami
    
    
    # veth (가상 이더넷 디바이스) 생성, man ip-link
    ip link add veth0 type veth peer name veth1
    
    # veth 생성 확인(상태 DOWN), ifconfig 에는 peer 정보 확인 안됨
    # very pair 정보 확인 : ({iface}@if{pair#N})
    ip -c link
    ip -c addr  # 축약 ip -c a
    ifconfig -a
    
    # 네트워크 네임스페이스 생성 , man ip-netns
    ip netns add RED
    ip netns add BLUE
    
    # 네트워크 네임스페이스 확인 
    ip netns list
    
    # veth0 을 RED 네트워크 네임스페이스로 옮김
    ip link set veth0 netns RED
    ip netns list
    ## 호스트의 ip a 목록에서 보이지 않음, veth1의 peer 정보가 변경됨
    ip -c link
    ## RED 네임스페이스에서 ip a 확인됨(상태 DOWN), peer 정보 확인, link-netns RED, man ip-netns
    ip netns exec RED ip -c a
    
    # veth1 을 BLUE 네트워크 네임스페이스로 옮김
    ip link set veth1 netns BLUE
    ip -c link
    ip netns exec BLUE ip -c a
    
    # veth0, veth1 상태 활성화(state UP)
    ip netns exec RED ip link set veth0 up
    ip netns exec RED ip -c a
    ip netns exec BLUE ip link set veth1 up
    ip netns exec BLUE ip -c a
    
    # veth0, veth1 에 IP 설정
    ip netns exec RED ip addr add 11.11.11.2/24 dev veth0
    ip netns exec RED ip -c a
    ip netns exec BLUE ip addr add 11.11.11.3/24 dev veth1
    ip netns exec BLUE ip -c a
    
    # 터미널1 (RED 11.11.11.2)
    ## nsenter : 네임스페이스에 attach 하여 지정한 프로그램을 실행
    tree /var/run/netns
    nsenter --net=/var/run/netns/RED
    ip -c a
    ## neighbour/arp tables management , man ip-neighbour
    ip -c neigh
    ## 라우팅 정보, iptables 정보
    ip -c route
    iptables -t filter -S
    iptables -t nat -S
    
    # 터미널2 (호스트)
    lsns -t net  # nsenter 실행 후 TYPE(net) CMD(-bash) 생성 확인
    ip -c a
    ip -c neigh
    ip -c route
    iptables -t filter -S
    iptables -t nat -S
    
    # 터미널3 (BLUE 11.11.11.3)
    nsenter --net=/var/run/netns/BLUE
    ip -c a
    ip -c neigh
    ip -c route
    iptables -t filter -S
    iptables -t nat -S
    
    # ping 통신 확인
    # 터미널3 (BLUE 11.11.11.3)
    tcpdump -i veth1
    ip -c neigh
    exit
    
    # 터미널1 (RED 11.11.11.2)
    ping 11.11.11.3 -c 1
    ip -c neigh
    exit
    
    # 삭제
    ip netns delete RED
    ip netns delete BLUE

 

  • ## RED 네임스페이스에서 ip a 확인됨(상태 DOWN), peer 정보 확인, link-netns RED, man ip-netns
  • # 터미널2 (호스트)
  • # 터미널3 (BLUE 11.11.11.3)
1.2 RED ← Bridge(br0) → BLUE 간 통신

결론 : arp table, route table, iptables 와 호스트의 bridge fdb 를 통하여 통신

 

  • 기본 환경 설정 및 확인
    # 네트워크 네임스페이스 및 veth 생성
    ip netns add RED
    ip link add reth0 type veth peer name reth1
    ip link set reth0 netns RED
    ip netns add BLUE
    ip link add beth0 type veth peer name beth1
    ip link set beth0 netns BLUE
    
    # 확인
    ip netns list
    ip -c link
    ip netns exec RED ip -c a
    ip netns exec BLUE ip -c a
    
    # 브리지 정보 확인
    brctl show
    
    # br0 브리지 생성
    ip link add br0 type bridge
    
    # br0 브리지 정보 확인
    brctl show br0
    brctl showmacs br0
    brctl showstp br0
    
    # reth1 beth1 을 br0 연결
    ip link set reth1 master br0
    ip link set beth1 master br0
    brctl show br0
    brctl showmacs br0
    ip -br -c link
    
    # reth0 beth0 에 IP 설정 및 활성화, br0 활성화
    ip netns exec RED  ip addr add 11.11.11.2/24 dev reth0
    ip netns exec BLUE ip addr add 11.11.11.3/24 dev beth0
    ip netns exec RED  ip link set reth0 up; ip link set reth1 up
    ip netns exec BLUE ip link set beth0 up; ip link set beth1 up
    ip link set br0 up
    ip -br -c addr
    
    
    # 터미널1 (RED 11.11.11.2)
    nsenter --net=/var/run/netns/RED
    ip -c a;echo; ip -c route;echo; ip -c neigh
    ## 현재 네트워크 네임스페이스 정보 확인
    ip netns identify $$
    RED
    
    # 터미널2 (호스트)
    brctl showmacs br0
    bridge fdb show
    bridge fdb show dev br0
    
    iptables -t filter -S
    iptables -t filter -L -n -v
    
    # 터미널3 (BLUE 11.11.11.3)
    nsenter --net=/var/run/netns/BLUE
    ip -c a;echo; ip -c route;echo; ip -c neigh
    ## 현재 네트워크 네임스페이스 정보 확인
    ip netns identify $$
    BLUE
    
    ==============================================================
    # 터미널2 (호스트)
    # ping 통신 전 사전 설정
    ## iptables 정보 확인
    iptables -t filter -S | grep '\-P'
    	-P INPUT ACCEPT
    	-P FORWARD DROP
    	-P OUTPUT ACCEPT
    	
    iptables -nvL -t filter
    
    ## Ubuntu 호스트에서 패킷 라우팅 설정 확인 : 커널의 IP Forwarding (routing) 기능 확인 - 0(off), 1(on)
    ## echo 1 > /proc/sys/net/ipv4/ip_forward
    cat /proc/sys/net/ipv4/ip_forward
    1
    
    ==============================================================
    # ping 통신 테스트
    # 터미널1 (RED 11.11.11.2) >> ping 왜 실패했을까요?
    ping -c 1 11.11.11.3
    
    # 터미널2 (호스트)
    tcpdump -l -i br0
    watch -d 'iptables -v --numeric --table filter --list FORWARD'
    watch -d 'iptables -v --numeric --table filter --list FORWARD;echo;iptables -v --numeric --table filter --list DOCKER-USER;echo;iptables -v --numeric --table filter --list DOCKER-ISOLATION-STAGE-1'
    
    # 터미널3 (BLUE 11.11.11.3)
    tcpdump -l -i beth0

  • RED → BLUE ping failed 분석
    • IPtables : Basic firewall software
      • Interacting with the packet filtering hooks in the kernel’s network stack
    • Netfilter : These kernel hooks are known as the netfilter framework
      • 5 hooks : INPUT, OUTPUT, PREROUTING, FORWARD, POSTROUTING
      • Chain
        Chain : INPUT - mangle, filter
        Chain : OUTPUT - mangle , nat , filter
        Chain : FORWARD - mangle , filter
        Chain : PPEROUTING - mangle , nat
        Chain : POSTROUTING - mangle , nat
      • Table
        Filter : 필터링. 패킷 전송 여부
        NAT : Network Address Translation. src/dst. 주소의 수정/방법 여부 결정
        Mangle : 헤더 변조 (TTL조정, 홉 수 조정). 추가 처리를 위한 커널 마킹
        Raw : connection tracking을 위한 패킷마킹 메커니즘 제공
        Security : 패킷에 SELinux(보안) context 마킹
      • Chain Rules
        Chain Rules : matching
        Chain Rules : targets (action - ACCEPT, DROP, REJECT, LOG, RETURN, JUMP)
        targets (action) : Jump - 다른 체인으로 점프!
      • 주요 설정
        -A : append, 해당 chain 끝 행에 룰 추가
        -I [chain] [number] : insert, 해당 [chain] [number] 행에 룰 삽입
        -D : delete, 행 번호 지정하여 룰 삭제
        -R : replace, 행 번호 지정하여 룰 치환
        -F : flush, 해당 체인의 모든 룰 삭제
        -L : list, 룰 리스트 출력
        -P : policy, 기본(default) 정책 설정. 체인의 모든 룰에 매칭되지 않으면 적용
        -p : protocol,  예) tcp, udp, icmp, ...
        -s : source ip, 지정 안할 경우 any 
        -d : destination ip, 지정 안할 경우 any
        -sport : source port
        -dport : destination port
        -i : input interface 예) eth0
        -o : output interface 예 eth0
      • Connection Tracking 과 State
        Stateful Operations : ~ Check packets and Update states , ~ Add a new connection
        States : NEW, ESTABLISHED, RELATED, INVALID, UNTRACKED, SNAT, DNAT

        Netfilter : 커널 모듈로 네트워크 패킷을 처리하는 프레임워크 - 링크
         - 네트워크 연산을 핸들러 형태로 처리할 수 있도록 hook 지점을 제공
         - 패킷이 어떻게 전송될 지에 대한 결정 방법을 제공
         - INPUT, OUTPUT

         - FORWARD : 호스트 입장에서 '네트워크 네임스페이스'도 지나가는 패킷 처리(FORWARD)를 한다

        NetfilterIPtables
        패킷은 netfliter(일종의 백엔드) 에서 파놓은 여러 hook 를 통과하는데 hook 별로 iptables 에서 정의한 각 체인룰을 점검
         - iptables(일종의 프런트엔드 혹은 애플리케이션) : Netfileter 가 파놓은 hook 에 룰을 등록하고 관리하는 방법을 제공하는 툴

        hook 에 정의된 체인은 테이블 순서대로 등록된 룰을 체크하고 조건을 만족하면 action(target)을 트리거합니다.
         - table : 목적/용도별 rules 모음 → 예) filter, nat, mangle ...
         - chain : 패킷이 지나가는 hook 별로 존재 → 예) PREROUTING, FORWARD, INPUT ... (넷필터의 hook 에 매핑됩니다)
         - rule : table 과 chain matrix 에 대해서 정의 → 예) protocol type, dest/src.address, headers ...
         - action(target) : 패킷이 룰에 매칭되면 트리거됨 → 예) ACCEPT, DROP, REJECT ... * -j : jump
  • RED → BLUE ping 허용 설정 - 링크
    • 호스트 입장에서는 "외부(RED, src) → 외부(BLUE, dst)" 패킷이므로 FORWARD 체인의 filter 테이블 룰을 봐야합니다 → 허용 정책 추가하자 - 링크
      # 터미널2 (호스트)
      # iptables 설정 정보 확인
      iptables -t filter -S
      iptables -t nat -S  | grep '\-P'
      
      # iptables 설정 추가 -t(table), -I(insert chain), -j(jump to - ACCEPT 허용)
      iptables -t filter -I DOCKER-USER -j ACCEPT
      iptables -nvL -t filter
      iptables -t filter -S
      iptables -t nat -S  | grep '\-P'
      watch -d 'iptables -v --numeric --table filter --list FORWARD;echo;iptables -v --numeric --table filter --list DOCKER-USER;echo;iptables -v --numeric --table filter --list DOCKER-ISOLATION-STAGE-1'
      tcpdump -l -i br0
      
      ==============================================================
      # ping 통신 테스트
      # 터미널1 (RED 11.11.11.2)
      ping -c 1 11.11.11.3
      ip -c neigh
      
      # 터미널2 (호스트)
      watch -d 'iptables -v --numeric --table filter --list FORWARD;echo;iptables -v --numeric --table filter --list DOCKER-USER;echo;iptables -v --numeric --table filter --list DOCKER-ISOLATION-STAGE-1'
      tcpdump -l -i br0
      
      ## 정보 확인
      ip -c neigh
      
      # 터미널3 (BLUE 11.11.11.3)
      tcpdump -l -i beth0
      ip -c neigh
      
      ==============================================================
      # (옵션) 추가 방안1 : 출발지 IP 11.2, 11.3 허용
      ## -t(table), -A(APPEND chain rule), -s(출발지), -j(jump to - ACCEPT 허용)
      iptables -t filter -A FORWARD -s 11.11.11.2/32 -j ACCEPT
      iptables -t filter -A FORWARD -s 11.11.11.3/32 -j ACCEPT
      ## 추가 정책 삭제 시
      iptables -t filter -D FORWARD -s 11.11.11.2/32 -j ACCEPT
      iptables -t filter -D FORWARD -s 11.11.11.3/32 -j ACCEPT
      
      # (옵션) 추가 방안2 : 11.11.11.0/24 대역 출발지 허용
      iptables -t filter -A FORWARD -s 11.11.11.0/24 -j ACCEPT
      ## 추가 정책 삭제 시 
      iptables -t filter -D FORWARD -s 11.11.11.0/24 -j ACCEPT
      
      # (옵션) 추가 방안3 : FORWARD 기본 정책 허용으로 변경
      iptables -t filter -P FORWARD ACCEPT
      ## 추가 정책 삭제 시 
      iptables -t filter -P FORWARD DROP

1.3 RED/BLUE → 호스트 & 외부(인터넷) 통신

결론 : 호스트에 RED/BLUE와 통신 가능한 IP 설정 및 라우팅 추가, iptables NAT 를 통하여 통신

ip netns add RED
ip link add reth0 netns RED type veth peer name reth1

ip netns add BLUE
ip link add beth0 netns BLUE type veth peer name beth1

ip link add br0 type bridge
ip link set reth1 master br0
ip link set beth1 master br0

ip netns exec RED ip addr add 11.11.11.2/24 dev reth0
ip netns exec BLUE ip addr add 11.11.11.3/24 dev beth0

ip netns exec RED ip link set reth0 up; ip link set reth1 up;
ip netns exec BLUE ip link set beth0 up;  ip link set beth1 up;
ip link set br0 up

# iptables -t filter -A FORWARD -s 11.11.11.0/24 -j ACCEPT
iptables -t filter -I DOCKER-USER -j ACCEPT
  • 호스트에서 RED 나 BLUE 로 ping 통신RED 에서 외부로 통신
    # 터미널1 (RED 11.11.11.2)
    nsenter --net=/var/run/netns/RED
    tcpdump -i any
    
    # 터미널3 (호스트)
    exit
    tcpdump -i br0 -n
    
    # 터미널2 (호스트) >> 호스트에서 RED 로 통신이 안되는 이유가 무엇일까요?
    ping -c 1 11.11.11.2
    ip -c route
    ip -c addr
    
    ==============================================================
    # 터미널2 (호스트) >> br0 에 IP 추가(라우팅 정보)
    ip addr add 11.11.11.1/24 dev br0
    ping -c 1 11.11.11.2
    ping -c 1 11.11.11.3
    
    # 터미널1 (RED 11.11.11.2) >> 192.168.50.10 와 통신이 안되는 이유는 무엇일까요?
    ping -c 1 11.11.11.1
    ping -c 1 192.168.50.10
    ip -c route
    ip -c addr
    
    ==============================================================
    # 터미널3 (호스트)
    tcpdump -i any icmp -n
    
    # 터미널1 (RED 11.11.11.2)
    ip route add default via 11.11.11.1
    ping -c 1 192.168.50.10
    ip -c route
    ping -c 1 8.8.8.8 >> 외부 대역(인터넷)과 통신이 안되는 이유가 무엇일까요?
    
    # 터미널2 (호스트)
    iptables -S -t nat
    iptables -nvL -t nat
    ## POSTROUTING : 라우팅 Outbound or 포워딩 트래픽에 의해 트리거되는 netfilter hook
    ## POSTROUTING 에서는 SNAT(Source NAT) 설정
    iptables -t nat -A POSTROUTING -s 11.11.11.0/24 -j MASQUERADE
    watch -d 'iptables -v --numeric --table nat --list POSTROUTING'
    iptables -nvL -t nat
    conntrack -L --src-nat
    
    # 터미널1 (RED 11.11.11.2)
    ping -c 1 8.8.8.8
    exit
    
    # 터미널3 (BLUE 11.11.11.3)
    nsenter --net=/var/run/netns/BLUE # 주의, 꼭 실행 후 아래 진행 할 것
    ip route add default via 11.11.11.1
    ping -c 1 8.8.8.8
    exit
    
    # 삭제
    ip netns delete RED
    ip netns delete BLUE
    ip link delete br0
    
    iptables -t filter -D DOCKER-USER -j ACCEPT
    iptables -t nat -D POSTROUTING -s 11.11.11.0/24 -j MASQUERADE


* 네트워크 네임스페이스만으로도 직접 수동으로 설정할 경우 복잡 합니다.
도커는 컨테이너 실행(run) 시 자동으로 해당 컨테이너의 네임스페이스 (네트워크, 마운트, PID 등)를 생성(삭제 등)하여 호스트와 격리해줍니다.