# macOS에서 49.7일 후 TCP 네트워킹이 중단되는 버그 발견

> Clean Markdown view of GeekNews topic #28321. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=28321](https://news.hada.io/topic?id=28321)
- GeekNews Markdown: [https://news.hada.io/topic/28321.md](https://news.hada.io/topic/28321.md)
- Type: GN+
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2026-04-09T06:29:49+09:00
- Updated: 2026-04-09T06:29:49+09:00
- Original source: [photon.codes](https://photon.codes/blog/we-found-a-ticking-time-bomb-in-macos-tcp-networking)
- Points: 1
- Comments: 1

## Topic Body

- macOS의 **TCP 타임스탬프 카운터(`tcp_now`)** 가 부팅 후 약 49.7일이 지나면 32비트 오버플로로 인해 내부 **TCP 시계가 정지**함
- 이로 인해 **TIME_WAIT 상태의 연결이 만료되지 않고 누적**되어 임시 포트가 해제되지 않음
- 시간이 지나면 **임시 포트 고갈**로 인해 새로운 TCP 연결이 모두 실패하고, 기존 연결만 유지됨
- ICMP(ping)은 정상 작동하지만, **TCP 전체 기능이 마비**되어 재부팅 외에는 복구 불가
- 장기 가동되는 **macOS 서버·빌드 머신·CI 환경**은 49일 17시간 주기로 이 문제에 노출되며, 커널 수정 전까지 **주기적 재부팅 필요**

---

### 배경: TCP의 기본 개념
- TCP 연결은 종료 시 즉시 사라지지 않고 **TIME_WAIT 상태**에 들어가며, 이는 지연된 패킷 처리와 신뢰성 있는 종료를 위한 단계임
  - 오래된 패킷이 새 연결로 잘못 해석되는 것을 방지하고, 마지막 ACK 손실 시 재전송을 처리하기 위함
- TIME_WAIT 지속 시간은 **2 × MSL(Maximum Segment Lifetime)** 로 정의되며, macOS에서는 약 **30초**로 설정되어 있음
- **MSL**은 TCP 세그먼트가 네트워크에서 생존할 수 있는 최대 시간으로, RFC 793에서는 2분으로 정의되었으나 현대 시스템에서는 훨씬 짧게 설정됨
- **32비트 부호 없는 정수 오버플로**는 값이 최대치(4,294,967,295)를 넘으면 0으로 되돌아가는 현상이며, macOS의 TCP 타임스탬프(`tcp_now`)는 부팅 이후 밀리초 단위로 증가하는 32비트 카운터로, **49일 17시간 2분 47.296초** 후 오버플로 발생

### 발견: 49.7일 후 TCP 연결 중단 현상
- Photon의 iMessage 모니터링용 Mac 서버들이 24/7로 운영되며, 2026년 3월 30일 **부팅 후 정확히 49.7일**이 지난 시점에 새 TCP 연결이 모두 실패하는 현상 발생
  - 기존 연결과 ICMP(ping)는 정상 작동했으나, 새로운 TCP 소켓 생성이 불가능
- 원인은 **XNU 커널의 TCP 타임스탬프 카운터(`tcp_now`) 오버플로**로, 단조 증가 검증 로직이 wraparound 이후 갱신을 차단하여 내부 TCP 시계가 **정지**
- TIME_WAIT 연결이 만료되지 않아 **임시 포트가 해제되지 않고 누적**, 결국 재부팅 외에는 복구 불가
- 재부팅 후 동일한 현상이 49.7일 주기로 반복됨

### 실험 설계: 오버플로 전후의 TCP 동작 비교
- 가설: 오버플로 이후 TIME_WAIT 가비지 컬렉션이 멈춘다면, 오버플로 전후의 단기 TCP 연결 생성 패턴에 차이가 나타남
  - 오버플로 전: TIME_WAIT 30초 후 정상 만료
  - 오버플로 후: TIME_WAIT 무한 지속
- 세 단계로 구성된 테스트 스크립트 실행
  1. **모니터링 단계**: 오버플로 35분 전부터 5분 전까지 TIME_WAIT 수를 10초 간격으로 기록
  2. **폭발 단계**: 오버플로 전후 10분 동안 2초마다 약 15개의 짧은 TCP 연결 생성
  3. **관찰 단계**: 연결 생성 중단 후 TIME_WAIT 변화를 모니터링

### 결과: 오버플로 이후 TIME_WAIT 정체
- 오버플로 전에는 TIME_WAIT 수가 0~200 사이에서 안정적으로 순환하며 **정상적인 회수 동작** 확인
- 오버플로 직후부터 TIME_WAIT 수가 **계속 증가**하며, 더 이상 만료되지 않음
- Machine B의 경우 2,828개의 TIME_WAIT 연결이 84초 후에도 하나도 회수되지 않았고, 이후에도 지속적으로 누적
- Machine A 또한 수동 확인 결과 TIME_WAIT 수가 단조 증가, 복구 불가 상태

### 근본 원인: XNU 커널의 `tcp_now` 32비트 오버플로
- `tcp_now`는 `bsd/netinet/tcp_var.h`에 정의된 **밀리초 단위 32비트 카운터**로, 부팅 이후 경과 시간을 추적
- `calculate_tcp_clock()` 함수에서 `(uint32_t)now.tv_sec * 1000` 연산이 49.7일 이후 최대값을 초과하며 **wraparound 발생**
- `if (tmp < current_tcp_now)` 조건문으로 인해, 오버플로 시 기존 값이 새 값보다 커져 **갱신이 차단**되고 `tcp_now`가 **영구 정지**
- TIME_WAIT 만료 검사는 `tcp_now`를 기준으로 수행되므로, 시계가 멈추면 만료 조건이 **항상 거짓**이 되어 회수 불가

### 연쇄 효과: TCP 전체 기능 정지로 확산
- **수 분 후**: TIME_WAIT 회수 중단, 단기 연결이 많은 워크로드에서 점진적 문제 발생
- **수 시간 후**: TIME_WAIT 수천 개 누적, **임시 포트 고갈**
- **포트 고갈 후**: 새로운 TCP 연결이 SYN_SENT 상태에서 실패, 기존 연결만 유지
- **CPU 부하 급증**: 커널이 TIME_WAIT 큐를 계속 스캔하며 부하 증가
- **결과적으로 TCP 완전 마비**, ICMP만 정상 작동
- 유일한 복구 방법은 **재부팅**, 이후 다시 49.7일 카운트 재시작

### 추가 증거 및 관련 사례
- **RFC 7323**은 1ms 단위 32비트 타임스탬프의 부호 비트 래핑이 약 24.8일마다 발생함을 명시
  - macOS의 경우 전체 32비트 오버플로(49.7일)로, RFC에서 다루는 원격 타임스탬프 문제와는 별개의 **로컬 커널 결함**
- Apple 커뮤니티 및 오픈소스 프로젝트에서 동일 증상 다수 보고
  - TCP 연결 불가, ping 정상, 재부팅만 해결, 수주간 가동 후 발생
  - Podman issue #12495 등에서 동일한 패턴 확인
- 공통점: **TCP만 실패**, **ICMP 정상**, **재부팅 필요**, **수주 단위 발생 주기**

### 영향 범위
- **49일 17시간 이상 연속 가동된 macOS 시스템**에서 발생 가능
- 일반 사용자는 주기적 업데이트로 재부팅되어 영향 적음
- 고위험 환경
  - 장기 가동 서버 플릿
  - macOS 기반 CI/CD 빌드 서버
  - Mac Pro 워크스테이션
  - 원격 관리형 코로케이션 Mac
  - 빌드 팜·테스트 인프라용 Mac mini 클러스터

### 재현 절차
- 부팅 시각으로부터 오버플로 예상 시점 계산
- 오버플로 전후 TIME_WAIT 수를 모니터링
- 오버플로 시점에 다수의 짧은 TCP 연결 생성
- 2분 후 TIME_WAIT 수가 감소하지 않으면 버그 재현 성공

### 9.5시간 후 관찰된 시스템 상태
- TIME_WAIT 연결이 단 한 개도 회수되지 않고 지속 증가
- SYN_SENT 상태의 실패 연결이 **3,000개 이상** 누적
- 기존 연결만 유지되고 신규 연결 불가
- Machine B의 평균 부하가 **49.74**까지 상승, 커널이 TIME_WAIT 큐 스캔에 과도한 CPU 사용

### 결론
- 단 하나의 32비트 정수와 `if (tmp < current_tcp_now)` 조건문이 **49.7일 후 TCP 전체를 정지시키는 시한폭탄**으로 작동
- 개발·테스트·코드 리뷰 단계에서는 발견되기 어려운 유형의 결함이며, 실제 운영 환경에서만 드러남
- Photon은 여러 서버에서 동일 현상을 재현했고, **오버플로 전에는 정상 회수, 이후에는 TIME_WAIT 누적**이 명확히 확인됨
- `tcp_now`가 멈추면 커널의 TCP 시계가 정지하며, 시스템은 겉보기엔 정상이나 TCP 포트가 모두 소진됨
- 장기 가동 macOS 시스템 관리자는 **49일 17시간 2분 47초**를 기억해야 하며,
  **재부팅 주기 조정 또는 커널 수정 전까지 주기적 재부팅**이 필요
- Photon은 현재 **재부팅 없이 `tcp_now`를 복구하는 우회 해결책**을 개발 중임

## Comments



### Comment 54950

- Author: neo
- Created: 2026-04-09T06:29:49+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47666488)   
- 내 iMac이 가끔 아무 연결도 안 되던 이유가 이제야 이해됨  
  **업타임(uptime)** 때문이었다는 걸 전혀 몰랐음  
  
- 글을 읽다 보니 AI가 쓴 느낌이 너무 강해서, Apple에 실제로 문의했는지 궁금했음  
  물론 버그는 중요하지만, **과장된 표현**이 많다고 느낌  
  대부분의 사용자는 영향을 거의 받지 않을 것 같음  
  Mac을 잠자기 모드로 두면 TCP 스택이 리셋되기 때문에 문제를 피할 수도 있을 듯함  
  결국 Apple이 수정하겠지만, 지금 당장 **패닉할 일은 아님**  
  - 나도 이 문제를 겪은 것 같음  
    자동 절전이 꺼진 MacBook이 약 50일 정도 켜져 있었는데, **ping은 되지만 TCP 연결이 전혀 안 되는 현상**이 있었음  
    Wi-Fi를 바꾸거나 유선 연결을 해도 해결 안 됐고, 재부팅하니 바로 정상으로 돌아왔음  
  - Apple에 문의는 안 했고, 블로그 작성자가 직접 고치려는 듯함  
    “재부팅보다 나은 **대체 해결책**을 개발 중이며, 그 전까지는 주기적으로 재부팅하라”고 했다고 함  
  - 나도 Mac Mini를 24시간 켜두는데, 가끔 네트워크가 멈추면 Wi-Fi 어댑터를 껐다 켜면 해결됨  
    그럴 때가 **재부팅하기 좋은 타이밍**임  
  - 실제로 Apple에 보고했고, 내부 시스템에 등록되었다고 함  
  
- 요즘 AI가 쓴 블로그 글은 읽기가 너무 힘듦  
  문체가 **부자연스럽고 핵심에 도달하기까지 너무 오래 걸림**  
  - 나도 같음. AI가 쓴 글은 읽는 게 피곤하고 집중이 안 됨  
  - AI가 요약한 내용만 보면 간단함 — Mac이 **tcp_now 시계가 오버플로우될 때** 롤오버를 허용하지 않는다는 문제임  
  
- “50일 동안 테스트할 개발자는 없다”는 말에 동의하지 않음  
  실제로는 **시간을 가속해 시뮬레이션 테스트**를 하면 됨  
  - Linux 커널에서는 이런 문제를 잡기 위해 **jiffies 카운터**를 부팅 시점에 오버플로우 직전 값으로 초기화한다고 함  
  - macOS는 하드웨어 시계를 사용해서 슬립 중에는 멈춤  
    이런 경우엔 `calculate_tcp_clock` 같은 함수를 수정해 **업타임을 인자로 전달**하면 검증이 가능함  
  - 이런 방식은 **비디오 게임 테스트**에서도 흔히 사용됨  
  
- 이 버그는 OpenClaw뿐 아니라 **모든 TCP 연결**에 영향을 미침  
  - 개별 연결이 오래 지속될 필요는 없음  
    macOS 업타임이 49.7일을 넘으면 모든 TCP 연결이 영향을 받기 시작함  
  - “이제 OpenClaw가 세상에서 제일 중요한 것처럼 보인다”는 농담도 있었음  
  
- 내 여러 macOS 장비는 600~1000일 이상 켜져 있는데, TCP 연결이 정상적으로 만료되고 있음  
  커널 버전은 각각 20.6.0과 17.7.0임  
  그래서 이 버그가 **특정 버전 이후에만 발생**하는 듯함  
  - 분석을 보니 `tcp_now` 값이 오버플로우 직전에서 멈추고, **타이머 계산이 잘못된 wraparound**로 인해 음수가 되어 비교가 실패함  
    잠깐의 기간 동안 TIME_WAIT 연결이 쌓일 수는 있지만, 원문은 과도하게 반응했고 **LLM이 쓴 글 같음**  
  - 실제로 이 버그는 작년 macOS 26에서 새로 도입된 코드에서 생겼다고 함  
    [관련 GitHub 링크](https://github.com/apple-oss-distributions/xnu/blame/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/netinet/tcp_subr.c#L3753)  
  
- 이런 문제는 다양한 소프트웨어에서 반복됨  
  예전에 **Guild Wars 서버**에서도 비슷한 일이 있었는데, 오버플로우를 빨리 유도하기 위해 `GetTickCount()`에 특정 값을 더해 테스트했음  
  - 오버플로우를 다루는 시스템은 **시작 직후 바로 오버플로우를 유도해 테스트**해야 함  
  
- 이 버그는 **Windows 95의 49.7일 버그**를 떠올리게 함  
  [관련 글](https://pipiscrew.github.io/posts/why-window/)  
  - 나도 그 마법 같은 숫자를 어디서 봤는지 기억하려고 했음  
  - 말 그대로 “**새로운 옛날 문제**” 같음  
  - [Boeing 787의 51일 전원 재부팅 이슈](https://www.theregister.com/2020/04/02/boeing_787_power_cycle_51_days_stale_data)도 비슷한 사례임  
  - 그래서 49.7일이라는 숫자가 익숙했던 것임  
  
- OpenClaw와 이 버그가 무슨 관련이 있는지 궁금함  
  
- 이 문제는 **Linux 커널 스케줄러의 208일 버그**를 떠올리게 함  
  [참고 링크](https://www.claudiokuenzler.com/blog/247/linux-virtual-serve...)  
  - 그리고 [Boeing 787의 전원 주기 문제](https://airguide.info/boeing-787s-must-be-turned-off-every-5...)도 같은 맥락임
