제공해주신 pwru 트레이스 분석 결과와 상황을 종합해 볼 때, 이전 모델의 분석은 커널 내부의 흐름(Function Call Path) 관점에서는 정확하지만, 인프라 운영 측면에서는 '왜' 이런 일이 발생하는지에 대한 근본 원인(Root Cause)을 더 좁힐 필요가 있습니다.
플랫폼 엔지니어링 리드로서 대규모 클러스터를 운영하시는 상황임을 고려하여, 실무적인 관점에서 다음과 같이 판단하고 추가 조언을 드립니다.
이전 모델의 분석 중 tcp_check_req에서 드랍된다는 점이 핵심입니다. 이 단계는 TCP Handshake 과정에서 SYN을 받고 SYN-ACK을 보낸 후, 클라이언트로부터 오는 마지막 ACK를 검증하는 단계입니다. 여기서 드랍된다는 것은 서버가 "나는 이 ACK를 받을 준비가 안 됐거나, 기대하던 ACK가 아니다"라고 판단한 것입니다.
tcpdump에는 안 찍힐까? (중요)pwru에는 찍히는데 tcpdump에 안 찍히는 이유는 크게 두 가지입니다.
tcpdump(libpcap)는 보통 NIC 드라이버 레벨에서 패킷을 가로챕니다. 반면 pwru는 커널 함수에 직접 훅을 겁니다. 패킷이 물리 NIC로 들어왔더라도 Bonding, VLAN, 혹은 Cilium의 eBPF 프로그램이 패킷을 처리하는 방식에 따라 tcpdump가 바라보는 인터페이스에는 패킷이 통과하지 않을 수 있습니다.bpf-host-routing을 사용 중이라면 일반적인 네트워킹 스택을 우회(Bypass)하여 스택의 더 깊은 곳으로 바로 패킷을 주입할 수 있습니다.단순히 "상태 불일치"를 넘어, 실제 환경에서 흔히 발생하는 시나리오는 다음과 같습니다.
SSH 연결 시 SYN, SYN-ACK까지는 크기가 작아 잘 넘어가다가, 세션 수립 직후나 특정 데이터가 실린 ACK 패킷이 MTU 제한으로 인해 조각나거나 드랍될 때 tcp_check_req에서 문제가 발생할 수 있습니다.
간헐적으로 발생한다면, 서버(수신측)의 request_sock(SYN을 받고 기다리는 소켓)이 타임아웃되어 삭제된 후에 클라이언트의 ACK가 도착했을 가능성이 큽니다.
Cilium은 자체적인 eBPF 기반 conntrack 테이블을 관리합니다. 커널의 tcp_check_req와 Cilium의 상태 관리가 어긋날 때(예: 비대칭 라우팅) 드랍이 발생할 수 있습니다.
더 명확한 답을 드리기 위해 다음 정보가 필요합니다.
native-routing인가요, 아니면 tunnel(VXLAN/Geneve) 모드인가요?pwru 실행 시 -sh (show help) 옵션 등을 활용해 드랍된 패킷의 TCP Flags(ACK인지 RST인지)와 Sequence Number를 확인할 수 있나요?이전 답변에서 제안한 cat /proc/net/bonding/bond1 확인 외에 다음을 먼저 시도해 보세요.
tcpdump -i any port 22 -nnvv로 캡처해 보시고, 그래도 안 나온다면 eth0, eth1 등 물리 슬레이브 인터페이스 각각을 지정해서 다시 확인해 보세요.cilium monitor --type drop
# 혹은 특정 IP에 대해
cilium monitor --related-to <클라이언트_IP>Cilium 레벨에서 policy denied나 ct_trunc 등의 드랍 사유가 찍히는지 확인해야 합니다.netstat -s | grep -i drop 혹은 nstat -az | grep -i TcpExtListenDrops 명령어를 통해 커널 스택 수준의 드랍 카운트가 올라가는지 보십시오.제 판단은 이렇습니다: "이것은 단순한 설정 오류라기보다, 네트워크 경로상의 MTU 불일치나 비대칭 라우팅(Asymmetric Routing)으로 인해 커널이 유효하지 않은 ACK를 받았다고 판단했을 확률이 90% 이상입니다."
추가 정보를 주시면 더 구체적으로 디버깅해 드릴 수 있습니다. 어떻게 진행해 볼까요?
===
추가 정보 감사합니다. Native Routing을 사용 중이고 Cilium monitor drop에 아무것도 찍히지 않는다면, 이는 Cilium의 BPF Datapath(보안 정책, 라우팅 로직 등) 문제가 아니라 리눅스 커널의 표준 TCP 스택 수준에서 패킷이 거부되고 있음을 강력하게 시사합니다.
pwru 트레이스에서 tcp_check_req 단계에서 드랍이 발생한다는 것은, 커널이 TCP Handshake의 마지막 단계인 ACK 패킷을 받았으나 이를 유효한 연결 요청으로 인정하지 않았다는 뜻입니다. L3 스위치만 있는 환경에서 발생할 수 있는 구체적인 원인과 점검 포인트를 정리해 드립니다.
Cilium monitor에 왜 안 찍힐까?Cilium Monitor는 eBPF 프로그램이 명시적으로 drop 결정을 내릴 때(예: Policy Denied, LB 관련 오류 등) 이벤트를 발생시킵니다. 하지만 현재 상황은 패킷이 Cilium의 BPF 로직을 무사히 통과하여 커널의 TCP 서브시스템(tcp_v4_rcv)으로 전달된 후, 커널 함수 내부 검증 로직에서 드랍된 것이기 때문에 Cilium 레벨의 로그에는 남지 않는 것이 정상입니다.
tcp_check_req 드랍의 핵심 원인 분석이 단계에서 패킷이 버려지는 가장 흔한 이유는 다음과 같습니다.
net.ipv4.tcp_syncookies)수신측 노드에 순간적으로 많은 연결 요청이 들어와 SYN Queue가 가득 찼을 때, 커널은 SYN Cookie를 발행합니다. 클라이언트가 보낸 ACK 패킷에 포함된 쿠키 값이 서버의 계산 결과와 일치하지 않으면 tcp_check_req에서 드랍됩니다.
sysctl net.ipv4.tcp_syncookies 값이 1인지 확인하고, nstat -az | grep -i SyncookiesFailed 카운트가 올라가는지 보십시오.서버가 SYN을 받고 SYN-ACK를 보낸 뒤 클라이언트의 ACK를 기다리는 동안 사용하는 것이 request_sock입니다. 네트워크 지연(L3 스위치 구간의 일시적 혼잡 등)으로 인해 클라이언트의 ACK가 너무 늦게 도착하여 서버 쪽의 대기 시간이 만료되면, 커널은 이 패킷을 "알 수 없는 연결의 ACK"로 취급하여 버립니다.
nstat -az | grep -i TcpExtListenDrops 또는 TcpExtTCPMinisocksDrop 카운트를 확인하십시오.rp_filterNative Routing 환경에서 L3 스위치가 ECMP 등으로 인해 나가는 경로와 들어오는 경로를 다르게 잡을 수 있습니다. 만약 패킷이 서버에 들어올 때 예상치 못한 인터페이스(예: bond1이 아닌 다른 인터페이스)로 들어오면 커널의 rp_filter가 작동하여 드랍될 수 있습니다.
sysctl -a | grep rp_filter 값이 1(Strict)인지 확인해 보십시오. 테스트를 위해 임시로 0으로 설정하고 현상이 재발하는지 확인해 볼 수 있습니다.현재 상황에서 문제를 확정 짓기 위해 다음을 실행해 보시길 권장합니다.
커널 정밀 통계 확인 (가장 추천)
문제가 발생한 직후 다음 명령어를 실행하여 어떤 카운터가 올라가는지 확인하십시오.
nstat -az | grep -E 'TcpExtListenDrops|TcpExtTCPMinisocksDrop|Syncookies|TcpExtTCPACKSkipped'
물리 인터페이스 직접 캡처
tcpdump -i any 보다는 물리 NIC(예: ens...)를 각각 지정해서 캡처해 보십시오. L3 스위치에서 오는 패킷이 본딩된 슬레이브 중 어느 쪽으로 들어오는지, 그리고 그 패킷의 Sequence Number와 ACK Number가 서버가 보낸 SYN-ACK와 일치하는지 대조해야 합니다.
MTU 확인
Native Routing이라도 하단 물리 망의 MTU가 1500 미만으로 설정된 구간이 있다면, SSH 인증 과정에서 큰 패킷이 오갈 때 tcp_check_req 이후 단계에서 문제가 될 수 있습니다. (다만, 현재 pwru상 드랍 지점은 Handshake 단계에 더 가깝습니다.)
결론적으로 제 판단은:
방화벽이 없는 Native Routing 환경이므로, "L3 스위치 구간의 일시적 지연으로 인한 SYN 대기 소켓(request_sock) 타임아웃" 또는 "커널의 SYN Cookie 오작동"일 가능성이 가장 높습니다.
위의 nstat 결과값 중 카운트가 유독 높은 항목이 있다면 알려주세요. 바로 다음 단계를 짚어드리겠습니다.
===
이번 트레이스는 같은 플로우(10.111.43.21:11180 -> 10.111.43.38:22)에 대해 “PREROUTING/LOCAL_IN(넷필터) -> 라우팅/소스검증 -> 로컬 딜리버리 -> RAW 소켓 검사 -> TCP 수신 -> 요청 검증(tcp_check_req) -> 드롭”까지의 세부 경로를 보여줍니다. 핵심은 마지막에 TCP 계층에서 해당 패킷이 처리 중 “요청 검증 단계에서 드롭”되었다는 점입니다.
핵심 흐름 해석
무엇이 드롭을 유발했을 가능성이 큰가?
중요한 점
진단을 확정하려면 필요한 것
tcpdump -i bond1 -nnvv 'host 10.111.43.21 and port 22'ss -lnt sport = :22로 큐 상태, somaxconn, tcp_max_syn_backlog 설정 확인.conntrack -L | grep '10.111.43.21.*22'로 세션 상태를 살펴보고, SYN-RECV/SYN-SENT/ESTABLISHED로 전이되는지 확인.정리
sysctl -a | egrep 'tcp_syncookies|somaxconn|tcp_max_syn_backlog' 출력, ss -lnt sport = :22 결과를 공유해 주세요.상황 정리
왜 tcpdump가 안 보일 수 있나(가능성)
1) 본딩 인터페이스에서 캡처함
2) 잘못된 캡처 인터페이스/네임스페이스
3) 필터/오프로드 영향
먼저 확인할 것
cat /proc/net/bonding/bond1
ip netns identify $$
ip -d link show bond1
권장 캡처 방법(하나씩 시도)
1) 슬레이브 NIC에서 캡처
sudo tcpdump -i ens5f1np1 -nnvv -Q in 'host 10.111.43.21 and port 22'
2) 모든 인터페이스에서 캡처(네임스페이스/인터페이스 문제 회피)
sudo tcpdump -i any -nnvv 'host 10.111.43.21 and port 22'
3) VLAN 가능성 고려(캡처 출력에 VLAN 헤더 표시)
sudo tcpdump -i ens5f1np1 -nnvv -e -Q in 'vlan and host 10.111.43.21 and port 22'
4) 패킷 손실/오프로드 혼선 최소화(임시)
# 필요 시 일시적으로만 비활성화(테스트 후 원복)
sudo ethtool -K ens5f1np1 gro off lro off gso off tso off rxhash off
5) 캡처를 파일로 저장해 사후 분석
sudo tcpdump -i ens5f1np1 -nn -s 0 -U -w /tmp/ssh_rx.pcap 'host 10.111.43.21 and port 22'
보조 진단
ethtool -S ens5f1np1 | egrep 'rx_.*pack|rx_.*err|rx_.*drop'
sudo dropwatch -l kas
sudo conntrack -L | grep '10.111.43.21.*dport=22'
해석 가이드
cat /proc/net/bonding/bond1)과 실행 중인 tcpdump 명령 줄을 알려주세요. 환경에 맞춰 캡처 지점을 정확히 짚어 드리겠습니다.