E-앰비언트 ztunnel 트래픽 경로 분석
개요
앰비언트 모드를 세팅한 이후, 전체적인 흐름을 알아보기 위해 iptables를 분석하고 패킷을 까보았다.
E-앰비언트 모드 헬름 세팅에서 먼저 세팅을 진행한다.
keti debug -- curl productpage:9080
ztunnel 레벨의 경로만 분석하면, 웨이포인트는 그저 한 홉이 증가하는 것에 불과하다.
그래서 그다지 어려운 레벨은 아니라 ztunnel 쪽에서 일어나는 위주로 정리한다.
간단한 트래픽에 대한 ztunnel 로그는 다음과 같이 나타난다.
출발지(debug)의 ztunnel의 로그는 다음과 같다.
목적지가 15008, 즉 hbone 포트였고 그 안 속 패킷은 9080 포트를 가리키고 있다.
또한 출발지 측에서 "나가는" 트래픽에 대한 로그이기 때문에 direction=outbound
로 찍히는 것이 확인된다.
반대로 목적지(productpage)의 ztunnel 로그는 이렇게 남는다.
표시되는 src, dst 자체의 정보는 비슷한데, 눈 여겨 볼 지점 중 하나는 출발지의 임시 포트가 다르다는 것이다.
출발지에서 찍힌 임시 포트는 앱 컨테이너가 날린 트래픽에 대한 포트 정보이나, 목적지에서 찍히는 임시 포트는 출발지의 ztunnel이 날린 트래픽에 대한 포트 정보가 남기 때문에 이러한 결과가 나온다.
추가로 트래픽이 들어온 측의 로그라 direction=inbound
가 나오고 있다.
iptables 분석
세팅은 이런 식으로 해서 패킷 카운트를 확인했다.
TABLE="mangle nat"
CHAIN="PREROUTING ISTIO_PRERT OUTPUT ISTIO_OUTPUT"
watch -d "for i in $TABLE ; do for j in $CHAIN ; do iptables -t \$i -n -v -L \$j; echo; done; echo; done"
먼저 mangle 테이블은 이렇게 생겼다.
Chain PREROUTING (policy ACCEPT 675 packets, 158K bytes)
pkts bytes target prot opt in out source destination
675 158K ISTIO_PRERT 0 -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_PRERT (1 references)
pkts bytes target prot opt in out source destination
48 3749 CONNMARK 0 -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x539/0xfff CONNMARK xset 0x111/0xfff
Chain OUTPUT (policy ACCEPT 688 packets, 107K bytes)
pkts bytes target prot opt in out source destination
688 107K ISTIO_OUTPUT 0 -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
346 75875 CONNMARK 0 -- * * 0.0.0.0/0 0.0.0.0/0 connmark match 0x111/0xfff CONNMARK restore
이 테이블 정보를 이해하기 위한 몇 가지 지식이 있다.
iptables에서 match a / b
의 의미는 패킷 c에 대해 c & b == a
를 묻는 것이다.
즉 AND연산을 하는 것인데, 0xfff(1로 채워진 12비트)에 AND 연산을 한다는 건 그냥 하위 12 비트가 a와 같냐고 묻는 것과 같다.
connmark와 mark가 구제적으로 다르다는 사실에 유의해야 한다.
connmark는 컨트랙 모듈이 관리하는 커넥션 엔트리에 마킹되는 값으로, 커널 내부에서 패킷 구조체에 마킹되는 값과 다르다.
룰 해석 자체는 그렇게 어렵지는 않다.
들어오는 트래픽에 대해서는 마크가 0x539일 경우 커넥션 마크를 0x111로 세팅한다.
그리고 나가는 트래픽의 커넥션 마크에 0x111이 세팅되어 있다면 해당 값을 일반 마크에도 세팅한다.
이 마킹 정보들은 이후 nat 테이블에서 사용된다.
여기에서 0x539는 ztunnel측에서 세팅해주는 값으로 십진수로는 1337이다.
다음으로 nat 테이블은 이런 식으로 구성된다.
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ISTIO_PRERT 0 -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_PRERT (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT 6 -- * * 169.254.7.127 0.0.0.0/0 tcp
0 0 REDIRECT 6 -- * * 0.0.0.0/0 !127.0.0.1 tcp dpt:!15008 mark match ! 0x539/0xfff redir ports 15006
Chain OUTPUT (policy ACCEPT 1 packets, 60 bytes)
pkts bytes target prot opt in out source destination
49 3756 ISTIO_OUTPUT 0 -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT 6 -- * * 0.0.0.0/0 169.254.7.127 tcp
24 2256 REDIRECT 17 -- * !lo 0.0.0.0/0 0.0.0.0/0 mark match ! 0x539/0xfff udp dpt:53 redir ports 15053
0 0 REDIRECT 6 -- * * 0.0.0.0/0 !127.0.0.1 tcp dpt:53 mark match ! 0x539/0xfff redir ports 15053
0 0 ACCEPT 6 -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x111/0xfff
0 0 ACCEPT 0 -- * lo 0.0.0.0/0 !127.0.0.1
24 1440 REDIRECT 6 -- * * 0.0.0.0/0 !127.0.0.1 mark match ! 0x539/0xfff redir ports 15001
이전 사이드카 모드 때의 iptables와 비교하면 꽤나 간결한 편이다.
테이블이 두 개 뿐이라 해석 자체는 상대적으로 쉽다.
먼저 들어오는 패킷에 대해 169.254.7.127에서 왔다면 무조건 통과시킨다.
해당 주소는 kubelet에서 오는 헬스체크 프로브에 대해 ztunnel이 SNAT 시키는 주소로, 이를 통해 헬스체크 패킷은 정상적으로 동작하게 만든다.
그리고 다음은 15006으로 리다이렉트를 시키는 조건이 적혀있는데, 간단하게 말하자면 그냥 앱 컨테이너에서 나가는 요청을 낚아채는 것이다.
사이드카 모드와 달리, 이제는 룰에 명시되지 않은 나머지 패킷들이 그냥 통과한다는 것을 유의할 필요가 있다.
패킷 확인
다음으로는 실제로 패킷을 캡쳐해서 어떻게 동작이 일어나는지 확인한다.
패킷을 실제로 뜯어보면 어떻게 트래픽이 이동했는지 감을 잡는데 도움된다.
아래 명령어는 전부 각 파드의 네임스페이스에 들어간 뒤에 캡쳐를 떴다.
참고로 productpage 파드에 들어가면 tcpdump 패키지를 설치해야 한다.
# curl to same node
tcpdump -i any -c 100 -w /pcap/same-node.pcap
# dump from debug pod
tcpdump -i any -c 100 -w /pcap/outbound-to-pod.pcap
# dump from productpage pod
tcpdump -i any -c 100 -w /pcap/inbound-from-pod.pcap
아웃바운드 트래픽
먼저 debug 파드 쪽에서 아웃바운드 트래픽을 캡쳐한 결과이다.
해당 트래픽을 포트를 기준으로 단계적으로 보자.
- 44862->15053
- 앱 컨테이너의 DNS 질의가 iptables를 통해 경로가 수정된 것이 인터페이스를 지날 때 잡혔다.
- 물론 ztunnel은 DNS 응답이 정상 경로에서 돌아온 것마냥 53 포트인 척 응답한다.
- 56432->15001
- 앱 컨테이너의 HTTP 요청이 iptables를 통해 경로가 수정돼 ztunnel의 인바운드 핸들러 포트로 리다이렉트됐다.
- 46048->15008 (길어질까봐 15008 포트 부분까지는 캡쳐하지 않음)
- 가장 마지막 46048포트에서 나가는 트래픽은 본격적으로 ztunnel이 HBONE 통신을 하는 부분이다.
- TLS 암호화가 돼있어 해당 내용은 뜯어볼 수 없다.
결국 앱 컨테이너의 요청은 ztunnel로 들어가고, ztunnel이 실제 요청을 날리는데 이 요청은 목적지 파드가 있는 곳의 ztunnel인 것이다.
그리고 그 요청은 15008 포트, HBONE을 통해 이뤄진다.
재밌는 것은 46048포트로 나가는 트래픽은 ztunnel이 날리는 트래픽인데, 파드의 네임스페이스에서 찍힌다는 것이다.
HBONE으로 한창 트래픽이 오가고, 이후에 ztunnel은 앱 컨테이너에 응답을 돌려준다.
물론 응답은 원래 목적지인 productpage 9080포트에서 온 것처럼 표시된다.
인바운드 트래픽
다음은 요청을 받았던 productpage에서 뜬 덤프이다.
이쪽은 플로우 그래프가 훨씬 단순하다.
- 46048->15008
- 아웃바운드 측에서 봤던 그 트래픽으로, 출발지 ztunnel이 목적지 ztunnel에 HBONE 통신을 수립했다.
- 46739->9080
- 그 이후, 도착지 ztunnel이 요청을 받을 앱 컨테이너에 요청을 보낸다.
- 전형적인 프록시 기능이 수행되는 것이다.
최종적으로 정리하자면 현재 트래픽의 흐름은 이런 식으로 진행됐다.
- 출발지 컨테이너:56432 to 출발지 ztunnel:15001
- 출발지 ztunnel:46048 to 도착지 ztunnel:15008 (HBONE)
- 도착지 ztunnel:46739 to 도착지 컨테이너:9080
ztunnel이 어떻게 워크로드 간 트래픽을 전달하는지 이제 명확하게 알 수 있다!
마지막으로 HBONE이 왜 터널인지 살짝 알 수 있는 대목으로, 반복적으로 요청을 보낸 패킷의 모습을 담아본다.
단순하게 위의 패킷을 뜨기 위해 debug 에서 productpage로 요청을 날린 것을 두어 번 반복했다.
앱 컨테이너에서의 요청 자체는 56436 임시 포트로 아무거나 부여받은 것이 확인된다.
그러나 15008로 향하는 출발지 ztunnel은 이전에 사용했던 46048포트를 그대로 사용하고 있다.
이는 HBONE 연결이 지속적으로 연결돼있으며, 추가적인 통신에 그대로 재사용된다는 것을 의미한다.
(conntrack -L
을 찍어보면 만료 기한이 어마무시하게 길게 잡혀 있다..)
이후 트래픽은 원래도 0x539 마킹이 돼 있어 iptables에 영항을 받지 않겠지만 아예 컨트랙을 통해 추적되는 트래픽이기 때문에 iptables의 nat 테이블은 아예 거치지 않는 결과가 나오게 될 것이다.
하위 문서
이름 | is-folder | index | noteType | created |
---|---|---|---|---|
E-서버리스 실습 | - | - | topic/explain | 2024-06-27 |
E-도커 파일 구조 탐색 | - | - | topic/explain | 2024-08-05 |
E-로컬 ssh 서버 세팅 | - | - | topic/explain | 2024-07-13 |
E-쿠버네티스 클러스터 구축 | - | - | topic/explain | 2024-07-29 |
E-레디네스 프로브와 레디네스 게이트 | - | - | topic/explain | 2024-08-15 |
E-initialDelaySeconds가 아니라 스타트업 프로브가 필요한 이유 | - | - | topic/explain | 2024-08-25 |
E-초기화 컨테이너보다 앞서는 사이드카 컨테이너 | - | - | topic/explain | 2024-08-30 |
E-디플로이먼트 조작 | - | - | topic/explain | 2024-09-14 |
E-NFS 볼륨, 스토리지 클래스 설정 | - | - | topic/explain | 2024-10-17 |
E-AWS KRUG 핸즈온 실습 - ECS | false | - | topic | 2024-11-03 |
E-컨테이너 오라클 dbms 설치 | false | - | topic/explain | 2024-11-26 |
E-리눅스 dbeaver 설치 | false | - | topic/explain | 2024-11-26 |
E-오라클 사용자 및 테이블 스페이스 생성 | false | - | topic/explain | 2024-11-26 |
E-파드의 readinessProbe와 디플로이먼트의 minReadySeconds의 차이 | false | - | topic/explain | 2024-12-26 |
E-잡 패턴 실습 | false | - | topic | 2024-12-28 |
E-iptables와 nftables의 차이 | false | - | topic/explain | 2024-12-30 |
E-바인딩과 하드 링크의 차이 | false | - | topic/explain | 2025-01-16 |
E-emptyDir 제한 | false | - | topic/explain | 2025-01-16 |
E-쿠버네티스 인증 실습 | false | - | topic/explain | 2025-01-21 |
E-api 서버 감사 | false | - | topic/explain | 2025-01-21 |
E-파드 마운팅 recursiveReadOnly | false | - | topic/explain | 2025-02-27 |
E-projected 볼륨 - 동적 업데이트, 중복 활용 | false | - | topic/explain | 2025-03-10 |
E-쿠버 RBAC 권한 상승 방지 실습 | false | - | topic/explain | 2025-03-16 |
E-Kyverno 기본 실습 | false | - | topic/explain | 2025-03-17 |
E-검증 승인 정책 실습 | false | - | topic/explain | 2025-03-17 |
E-nodeName으로 스케줄링 실습 | false | - | topic/explain | 2025-03-19 |
E-openssl을 이용한 인증서 생성 실습 | false | - | topic/explain | 2025-03-22 |
E-buildKit을 활용한 멀티 플랫폼, 캐싱 빌드 실습 | false | - | topic/explain | 2025-03-30 |
E-이스티오의 데이터 플레인 트래픽 세팅 원리 | false | 1 | topic/explain | 2025-05-27 |
E-이스티오 가상머신 통합 | false | 1 | topic/explain | 2025-06-01 |
E-이스티오 설정 트러블슈팅하기 | false | 2 | topic/explain | 2025-05-18 |
E-deb 파일 뜯어보기 | false | 2 | topic/explain | 2025-06-01 |
E-앰비언트 모드 헬름 세팅 | false | 2 | topic/explain | 2025-06-03 |
E-이스티오 컨트롤 플레인 성능 최적화 | false | 3 | topic/explain | 2025-05-18 |
E-이스티오 DNS 프록시 동작 | false | 3 | topic/explain | 2025-06-01 |
E-앰비언트 ztunnel 트래픽 경로 분석 | false | 3 | topic/explain | 2025-06-07 |
E-이스티오 컨트롤 플레인 메트릭 | false | 4 | topic/explain | 2025-05-18 |
E-앰비언트 모드에서 메시 기능 활용 | false | 5 | topic/explain | 2025-06-07 |
관련 문서
지식 문서, EXPLAIN
이름3 | is-folder | 생성 일자 |
---|---|---|
E-앰비언트 모드에서 메시 기능 활용 | false | 2025-06-07 20:56 |
E-앰비언트 모드 헬름 세팅 | false | 2025-06-03 19:27 |
앰비언트 모드 | false | 2025-06-02 14:51 |
기타 문서
Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완이름4 | 코드 | 타입 | 생성 일자 |
---|---|---|---|
I-ztunnel이 다른 네임스페이스에서 요청 보내는 코드 분석 | Z1 | topic/idea | 2025-06-07 20:44 |
I-다른 네임스페이스 같은 포트 리스닝 서버 구현 | Z1 | topic/idea | 2025-06-07 19:39 |
9W - 앰비언트 모드 구조, 원리 | Z8 | published | 2025-06-07 19:17 |
9W - 앰비언트 헬름 설치, 각종 리소스 실습 | Z8 | published | 2025-06-07 19:27 |