# SSH가 키 입력마다 100개의 패킷을 보내는 이유

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

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=26065](https://news.hada.io/topic?id=26065)
- GeekNews Markdown: [https://news.hada.io/topic/26065.md](https://news.hada.io/topic/26065.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-01-23T17:33:25+09:00
- Updated: 2026-01-23T17:33:25+09:00
- Original source: [eieio.games](https://eieio.games/blog/ssh-sends-100-packets-per-keystroke/)
- Points: 9
- Comments: 1

## Summary

SSH의 **키 입력 타이밍 난독화** 기능이 활성화된 환경에서 단일 키 입력마다 수백 개의 패킷이 전송되는 현상이 보고되었습니다. 사용자의 타이핑 패턴을 숨기기 위해 주기적으로 **‘chaff’ 패킷**을 보내는 보안 메커니즘이 원인이며, 이를 비활성화하면 CPU와 대역폭 사용량이 절반 이하로 줄어듭니다. 보안 강화를 위한 설계가 **실시간 성능이 중요한 애플리케이션**에서는 오히려 병목으로 작용할 수 있음을 보여주는 사례입니다.

## Topic Body

- SSH 세션에서 단일 키 입력 시 **수백 개의 패킷이 전송되는 현상**이 발견되어 원인을 추적한 사례  
- `tcpdump` 분석 결과, 대부분의 패킷이 **36바이트 크기의 반복 메시지**로 구성되어 있었으며, 약 20ms 간격으로 발생  
- 원인은 2023년 SSH에 추가된 **‘키 입력 타이밍 난독화(keystroke timing obfuscation)’ 기능**으로, 사용자의 입력 타이밍을 숨기기 위해 다수의 **‘chaff’ 패킷(SSH2_MSG_PING)** 을 전송함  
- 이 기능을 비활성화하거나 서버가 `[email protected]` 확장을 광고하지 않도록 수정하면 **CPU 사용률과 대역폭이 절반 이하로 감소**  
- SSH의 보안 기능이 **실시간 성능이 중요한 애플리케이션(예: 게임)** 에서는 큰 부하로 작용할 수 있음을 보여주는 사례  

---

### 문제 발견
- SSH를 통해 실행되는 **고성능 게임의 TUI**를 테스트하던 중, 단일 키 입력에도 **270개의 패킷**이 발생하는 현상 확인  
  - `tcpdump` 결과, 66%가 36바이트 메시지, 33%가 TCP ACK, 나머지는 소량의 기타 데이터  
  - 평균 **90패킷/초**, 약 **11ms 간격**으로 데이터 전송  
- 테스트 중 서버가 “your screen is too small” 메시지만 보내도록 잘못 설정되었는데, 이때 **CPU와 대역폭 사용량이 절반으로 감소**  
  - 게임 데이터가 전송되지 않아야 CPU 사용이 0%에 가까워야 하지만, 여전히 50% 수준 유지  
  - 이로 인해 SSH 자체의 **통신 오버헤드** 가능성 제기  

### 조사 과정
- `tcpdump`를 이용해 정상 동작과 오류 상태의 SSH 트래픽을 비교  
  - 오류 상태에서도 **36바이트 패킷이 20ms 간격으로 지속 발생**  
  - MacOS 기본 SSH 클라이언트에서도 동일한 패턴 확인  
- Claude Code를 이용해 pcap 파일을 분석한 결과  
  - 전체 413,703개 패킷 중 66%가 36바이트, 34%가 0바이트 ACK  
  - SSH 클라이언트가 주도적으로 패킷을 생성하고 있었음  

### 근본 원인
- SSH 디버그 로그(`ssh -vvv`)에서 다음 메시지 확인  
  ```
  obfuscate_keystroke_timing: starting: interval ~20ms
  obfuscate_keystroke_timing: stopping: chaff time expired (101 chaff packets sent)
  ```
  - **20ms 간격**과 **수십~백여 개의 chaff 패킷**이 실제 관찰된 패턴과 일치  
- 2023년 SSH에 추가된 **키 입력 타이밍 난독화 기능**이 원인  
  - 사용자의 타이핑 속도 패턴이 노출되는 것을 막기 위해 **무작위 ‘chaff’ 패킷**을 전송  
  - 보안에는 유용하지만, **지연(latency)** 이 중요한 환경에서는 과도한 부하 발생  

### 해결 방법
- 클라이언트 측에서 `ObscureKeystrokeTiming=no` 옵션으로 기능 비활성화 가능  
  - 적용 후 CPU 사용률과 대역폭이 크게 감소, 데이터 전송 정상 유지  
- 서버 측 대응을 위해 Go의 SSH 라이브러리에서 `[email protected]` 확장 광고를 제거  
  - 관련 커밋을 되돌린 후 테스트한 결과  
    - **CPU 사용률 29.9% → 11.6%** ,  
      **시스템 호출 3.10s → 0.66s**,  
      **암호화 연산 1.6s → 0.11s**,  
      **대역폭 6.5Mbit/s → 3Mbit/s**  
  - 성능이 **50% 이상 향상**  

### LLM을 활용한 디버깅 경험
- Claude Code를 이용해 `tcpdump`, `tshark` 분석을 자동화하며 문제 원인을 빠르게 좁힘  
  - 명령 실행 과정을 실시간으로 관찰하며 **정신적 모델 유지** 가능  
- ChatGPT는 SSH의 동작을 “정상”이라 잘못 판단하는 등 **모델 간 차이**도 경험  
- LLM이 문제 해결의 전 과정을 대체하지는 않지만, **보조 분석 도구로서 높은 효율성**을 보임  
- 인간의 추론과 LLM의 분석을 결합해 **복잡한 네트워크 성능 문제를 해결한 사례**

## Comments



### Comment 49772

- Author: neo
- Created: 2026-01-23T17:33:25+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46723990) 
- go의 **crypto 라이브러리**를 포크하는 건 좀 무섭게 느껴짐  
  내 작은 패치를 안전하게 유지할 방법을 고민 중임  
  사실 이런 기능은 ssh 라이브러리의 옵션으로 **upstream**되는 게 맞다고 생각함  
  신뢰되지 않은 환경에서는 chaff(잡음) 패킷을 보내는 게 기본값으로 좋지만, 대역폭을 아끼고 싶은 경우도 많음
  - 기능을 광고하지 않는 방식으로 제어하는 건 너무 **불안정한 접근법**임  
    서버가 클라이언트에 “필요 없다”는 신호를 보낼 수 있는 옵션을 추가하고, 클라이언트는 이를 수락하거나 경고하도록 하는 게 올바른 해결책임
  - 사실 이미 비슷한 동작이 있음  
    TTY 세션에서만 적용되고, 클라이언트가 비활성화할 수 있음  
    다만 이번 케이스는 서버가 미리 중요하지 않은 연결임을 알고 있어서 생긴 예외적인 상황임  
    대부분의 경우 클라이언트는 **ObscureKeystrokeTiming** 설정이 지켜지길 기대함
  - 그래도 이 변경은 **거절될 가능성**이 높다고 봄  
    crypto 라이브러리는 매우 **의견이 강한 코드베이스**라, TLS cipher suite 순서조차 바꿀 수 없게 되어 있음
  - 신뢰된 환경에서도 **위협**은 존재함  
    이건 SSH의 매우 **특수한 사용 사례**로 보임  
    너무 넓게 노출되면 “설정하고 잊는” 상황이 생겨 오히려 보안이 약화될 수 있음
  - 예전엔 1KB RAM의 ZX80을 쓰던 시절이 있었음  
    1200bps 모뎀으로 통신하던 때도 있었고, 56K 모뎀은 사실상 과장이었음  
    1994년쯤엔 영국 군사대학에서 일하며 **WWW**를 처음 접했는데, 그땐 “좀 별로네”라고 생각했음  
    지금 생각하면 참 **시대의 변화**가 놀라움

- 이 **obfuscation 기능**은 처음 들어봤는데 흥미로웠음  
  ssh의 동작을 디버깅할 때 “None” cipher를 패치해서 패킷 내용을 직접 보는 것도 좋은 방법임  
  보안이 중요하지 않고 성능이 중요한 **터미널 게임**이라면 그냥 telnet을 쓰는 것도 고려할 만함
  - 이 기능이 추가됐을 때 [HN 메인 페이지에 올라왔음](https://news.ycombinator.com/item?id=37307708)

- SSH가 이런 걸 한다는 걸 몰랐음  
  기본값으로 켜져 있는 게 이해는 되지만, 내 환경에서는 끄는 게 맞을 듯함  
  1) SSH로 비밀을 직접 타이핑할 일이 거의 없음  
  2) 국가 수준의 공격자가 내 키 입력을 sniffing할 이유도 없음  
  3) 대륙 간 연결이라 **대역폭 절약**이 중요함  
  그래서 `ObscureKeystrokeTiming=no`로 설정하려 함. 혹시 이걸 하면 안 되는 이유가 있을까?
  - 낙관적인 보안 태도는 위험함  
    (1) 사람이 언제 비밀을 입력하는지 항상 구분하기 어렵고, 활동 전체가 **패턴 분석**될 수 있음  
    (2) 이건 대학 연구실 수준에서도 가능한 공격임 — [USENIX 논문](https://www.usenix.org/conference/10th-usenix-security-symposium/timing-analysis-keystrokes-and-timing-attacks-ssh)과 [연구 사례](https://crzphil.github.io/posts/ssh-obfuscation-bypass/) 참고  
    (3) 비디오 트래픽이 지배적인 인터넷에서 키 입력 몇 바이트 절약하려고 보안을 포기하는 건 의미 없음
  - tty SSH 연결에서 자주 입력하는 비밀은 **sudo 비밀번호**임  
    공격자가 키 입력 타이밍을 분석하면 명령어와 암호화된 비밀번호 패턴을 추정할 수도 있음  
    물론 세션 키가 매번 달라서 복호화는 어렵겠지만, 가능성은 있음  
    나도 대부분의 비밀번호는 **패스워드 매니저에서 복사**해서 붙여넣음
  - 어떤 평문이 유출돼도 공격자에게 쓸모가 없을 거라 확신할 수 없음  
    대부분의 사람은 SSH의 **보안 기능을 끄고도** 아무 문제 없다고 느끼지만, 그건 단지 운이 좋았을 뿐임  
    진짜 성능이 필요하면 Telnet, 진짜 보안이 필요하면 **ContainerSSH + OAuth2** 조합을 쓰는 게 좋음

- 2004년에 SSH 세션의 **키 입력 간 지연 분석**으로 명령어를 추정하는 연구를 했었음  
  [당시 분석 자료](https://www.brendangregg.com/sshanalysis.html) 참고  
  2023년 패치가 드디어 그 문제를 해결한 셈임
  - HAL2001 해킹 컨퍼런스에서 **Dug Song**과 **Solar Designer**가 SSH 타이밍 분석을 발표하던 게 기억남  
    [발표 자료](https://download.openwall.net/pub/advisories/OW-003-ssh-traffic-analysis/OW-003-ssh-traffic-analysis.txt)  
    세월이 정말 빠름

- Claude가 디버깅에 실제로 도움이 된 건 잘 모르겠음  
  작성자가 이미 방향을 알고 있었고, Claude는 그냥 맞장구친 느낌이었음  
  Claude가 “Holy Cow!” 같은 말을 하는 건 좀 **거슬림**
  - 그래도 **Rubber Duck Debugging**처럼 생각을 정리하는 데 도움을 줬다면 가치가 있음  
    나도 Claude로 시스템 동작을 디버깅할 때, 직접적인 답은 없어도 **이해를 정리하고 동기 유지**에 도움이 됨  
    [Rubber Duck Debugging 위키](https://en.wikipedia.org/wiki/Rubber_duck_debugging)
  - Claude는 **pcap 필드 추출**이나 awk 처리 속도가 나보다 훨씬 빠름
  - AI는 텍스트에서 **성격을 감지**하는 데 뛰어남  
    작성자가 “holy cow” 반응을 좋아해서 블로그에 넣은 걸 보면, Claude가 분위기를 잘 읽은 듯함
  - 개발 도구에 **인격**을 부여하는 건 좋은 생각이 아니었을지도 모름

- **TCP_CORK**을 사용하면 지연 없이 패킷 수를 줄일 수 있음  
  TCP_NODELAY를 끄는 것도 방법이지만, 그건 **지연 증가**라는 대가가 있음
  - TCP_CORK를 처음 들어봤는데 흥미로움  
    소켓을 cork하면 커널이 데이터를 버퍼링하다가 uncork하거나 MSS에 도달하면 전송함  
    즉, **패킷을 묶어서 전송**하는 방식임  
    [참고 자료](https://catonmat.net/tcp-cork)
  - TCP_CORK를 몰랐는데 정말 유용해 보임  
    ping은 그대로 받겠지만, pong 전송 횟수를 줄일 수 있을 듯함  
    TCP_NODELAY는 이미 써봤는데, **지연이 커져서** 내 게임엔 맞지 않았음  
    [이전 HN 글](https://news.ycombinator.com/item?id=46359120)
  - 다만 chaff 패킷이 20ms 간격으로 전송되므로, TCP_CORK가 그걸 묶을 수 있을지는 의문임  
    obfuscation 목적상 **지연 합치기(coalescing)** 는 불가능할 듯함

- “The smoking gun!” 표현이 웃겼음  
  영어 원어민이 아닌데 Claude가 자주 써서 처음 배웠음  
  이제는 진짜 **유행어처럼 퍼지고 있음**

- LLM 의존이 아쉬움  
  이건 그냥 **Wireshark**로 패킷 캡처를 보면 더 빨리 해결됐을 듯함  
  SSH dissector가 꽤 성숙함
  - 나도 LLM을 좋아하진 않지만, Wireshark로 SSH 패킷을 보면 대부분 **암호화된 패킷**뿐이라 유용한 정보가 없음  
    tcpdump로 한 키 입력만 캡처해도 수백 개의 암호화된 패킷이 나옴  
    결국 LLM 덕분에 작성자가 흥미로운 걸 배우고 공유했으니 의미 있었음
  - SSH dissector는 완벽하지 않음  
    **NEWKEYS** 메시지 이후엔 파싱이 안 되고, `none` 암호화로 패치해도 흐름을 완전히 해석하진 못함  
    개선 여지는 있음
  - “Wireshark만 보면 됐지”라는 태도는 **게이트키핑**처럼 들림  
    도구를 활용해서 배우는 것도 충분히 가치 있음
  - SSH는 이름부터 **보안 프로토콜**임  
    단순 패킷 캡처로는 유의미한 정보를 얻기 어려움
  - 저자는 SSH 패킷 분석기를 몰랐고, 대신 **일반 도구(LLM)** 를 활용했을 뿐임  
    그게 왜 불행한 일인지 모르겠음

- 2023년에 SSH가 **키 입력 타이밍 난독화** 기능을 추가했음  
  키 입력 속도로 문자를 추정할 수 있어서, SSH가 **chaff 패킷**을 섞어 공격자가 구분 못 하게 함  
  하지만 이건 잘못된 접근 같음  
  정말 원한다면 모든 키 입력을 **50ms 간격**으로 전송하면 됨
  - 50ms 지연은 **입력 체감이 매우 불쾌**할 것 같음
  - 50ms 간격으로 보낸다는 게 20ms 대신 50ms로 바꾸자는 건지, 아니면 **지속적인 일정 간격 전송**인지 애매함  
    현재 구현은 20ms 단위로 묶되, 일정 시간 입력이 없으면 chaff 전송을 멈추는 방식임

- SSH의 핵심은 **보안**이지만, 보안이 필요 없다면 왜 SSH를 쓰는지 의문임  
  예를 들어 **netcat(nc)** 은 대부분의 플랫폼에 기본 설치되어 있음
  - “보안이 1순위”라고 해서 그게 전부는 아님  
    SSH에는 성능, 편의성 등 **다른 고려사항**도 있음  
    작성자는 단지 **키 입력 난독화(privacy)** 기능이 불필요하다고 한 것뿐임  
    여전히 암호화나 무결성 보장은 유지하고 싶을 수 있음  
    즉, SSH의 보안 기능 대부분은 그대로 두되 일부만 끄는 선택임
  - Windows에도 이제 SSH가 포함되어 있어서, “모든 플랫폼에 nc가 있다”는 말은 **정확하지 않음**
