SSH 멀티플렉싱(ControlMaster)은 이미 열려 있는 SSH 연결 하나를 재사용해, 같은 서버로 향하는 새 세션들을 인증·핸드셰이크 없이 곧바로 얹는 기능입니다. 첫 연결이 만든 소켓(control socket)을 통해 이후 접속들이 그 통로에 무임승차하는 셈이죠. 결과는 단순합니다 — 두 번째부터의 ssh·scp·git push가 눈에 띄게 빨라집니다.
왜 빠른가? SSH 접속 한 번에는 TCP 연결, 키 교환, 사용자 인증이 매번 붙습니다. 서버가 지구 반대편이면 이 왕복만으로 1~2초가 날아가죠. 멀티플렉싱은 이 비싼 과정을 처음 한 번만 치르게 합니다.
체감 순간 — 툴이 SSH를 반복 호출할 때
혼자 터미널에서 한 번 접속할 땐 별 차이를 못 느낍니다. 진가는 SSH를 반복 호출하는 도구에서 나옵니다. 예를 들어:
- Ansible이 서버 한 대에 태스크 수십 개를 SSH로 밀어 넣을 때
- rsync·scp로 파일을 여러 번 주고받을 때
- Git이 원격 작업마다 SSH를 새로 여는 모노레포 워크플로
ssh로 원격 명령을 루프 돌며 계속 실행하는 스크립트
나는 예전에 원격 서버 상태를 1초마다 폴링하는 스크립트를 짰다가, 매 반복이 새 SSH 핸드셰이크를 하느라 서버 sshd 부하가 치솟는 걸 본 적이 있습니다. ControlMaster를 켜자 접속 로그가 뚝 끊기고 CPU가 조용해지더군요.
설정 방법 — ~/.ssh/config 세 줄
매번 옵션을 치는 대신 ~/.ssh/config에 넣어두는 게 정석입니다.
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
각 줄의 의미를 뜯어보면:
| 항목 | 역할 |
|---|---|
ControlMaster auto | 없으면 마스터 생성, 있으면 재사용 |
ControlPath | 공유 소켓 파일 경로(%r 사용자, %h 호스트, %p 포트) |
ControlPersist 10m | 마지막 세션 종료 후 10분간 마스터 유지 |
ControlPersist가 특히 실용적입니다. 이걸 켜두면 원래 접속을 끊어도 백그라운드에 마스터가 잠시 살아 있어서, 곧바로 다시 접속할 때 즉시 붙습니다. ControlPath의 %r@%h:%p 조합은 "사용자+호스트+포트별로 별도 소켓"을 만들어 충돌을 막아줍니다.
제어 명령 — 살아있는 마스터 다루기
-O 옵션으로 마스터 연결을 직접 조작할 수 있습니다. 이게 없으면 "왜 설정을 바꿨는데 그대로지?" 하고 한참 헤맵니다. 마스터가 옛 설정으로 살아 있기 때문이죠.
# 마스터가 살아있는지 확인
ssh -O check myserver
# 마스터를 즉시 종료(설정 바꿨을 때 필수)
ssh -O exit myserver
# 소켓만 열어두는 마스터를 백그라운드로 미리 띄우기
ssh -MNf myserver
개인적으로 제일 많이 데인 게 이겁니다.~/.ssh/config를 고쳤는데 접속 동작이 안 바뀌어서 한참 디버깅했더니, 옛 설정으로 만들어진 마스터 소켓이 아직 살아 있던 거였죠. 설정을 바꿨으면ssh -O exit로 마스터를 한 번 끊어주는 습관을 들이세요.
주의할 점
- NFS·공유 파일시스템 위의 소켓 —
ControlPath를 여러 머신이 공유하는 홈 디렉터리에 두면 소켓이 꼬입니다. 로컬 디스크 경로를 쓰세요. - 모든 세션이 한 연결에 얹힌다 — 마스터 TCP가 죽으면 얹혀 있던 세션이 함께 끊깁니다. 불안정한 회선에선 오히려 취약할 수 있어요.
- 포트 포워딩 상속 — 마스터에 걸어둔 터널을 나중 세션이 물려받는 등, 기대와 다르게 동작할 수 있으니 포워딩을 쓸 땐 동작을 확인하세요.
자주 묻는 질문
정말 얼마나 빨라지나요?
원격이 가까우면 수십 ms, 지연이 큰 원거리 서버나 다단계 인증(2FA 포함)이 있으면 접속당 1초 이상 절약되기도 합니다. 접속을 N번 반복하는 작업이면 그 절약이 그대로 N배로 쌓입니다. Ansible처럼 SSH를 수백 번 여는 도구에서 체감이 가장 큽니다.
"ControlSocket ... already exists" 오류가 나요.
이전 마스터의 소켓 파일이 남아 있는데 프로세스는 죽은 경우입니다. ssh -O exit 호스트로 정리하거나, 그래도 안 되면 ControlPath가 가리키는 소켓 파일을 직접 지우면 됩니다. 소켓 파일이 있다고 마스터가 반드시 살아있는 건 아니라는 점을 기억하세요.
특정 호스트만 멀티플렉싱을 끄고 싶어요.
Host 블록에서 ControlMaster no를 주면 됩니다. SSH config는 먼저 매칭된 값이 이기므로, 예외 호스트 블록을 Host * 위에 두면 그 호스트만 멀티플렉싱을 비활성화할 수 있습니다.
Git이나 rsync에도 자동으로 적용되나요?
네. Git·rsync·scp는 내부적으로 ssh를 호출하므로 ~/.ssh/config의 ControlMaster 설정을 그대로 따릅니다. 별도 설정 없이도 같은 호스트로의 반복 작업이 마스터 연결을 재사용합니다. 그래서 config에 한 번만 넣어두면 전방위로 이득을 봅니다.

댓글 0