[서버 침해 대응기 시리즈] 1인 개발자가 크립토재킹 당하고, 서버를 통째로 새로 만든 5일간의 기록
- 1편.내 서버가 6주째 몰래 채굴당하고 있었습니다
- 2편. docker.sock을 Jenkins한테도 AI한테도 주지 마세요 (socket-proxy) ← 지금 글
- 3편. 7개 도메인 무중단 HTTPS 이전기 (nginx + certbot)
- 4편. Jenkins 자동배포, 보안이랑 403 싸운 이야기
- 5편. 그래서 보안과 편의 사이, 어디에 서야 할까
지난 편에서 제 서버가 6주간 채굴당한 얘기를 했어요.
범인은 Jenkins였고.
정확히는 Jenkins한테 물려준 docker.sock이었죠.
그래서 새 서버를 만들면서 결심했어요.
이번엔 docker.sock을 아무한테도 안 줄 거라고.
근데 문제가 있어요.
안 주면 빌드를 못 하거든요.
docker.sock을 왜 줘야 했냐면
잠깐 복습할게요.
Jenkins가 하는 일이 뭐죠?
코드 받아서, 이미지 빌드하고, 컨테이너 띄우는 거예요.
이걸 하려면 도커를 조종해야 합니다.
그 조종 리모컨이 docker.sock이에요.
그래서 다들 Jenkins한테 docker.sock을 그냥 물려줍니다.
저도 그랬고요.
대부분의 블로그 글이 그렇게 알려줘요.
근데 지난 편에서 봤듯이.
docker.sock = 호스트 서버 전체 권한이거든요.
Jenkins가 뚫리면.
그게 곧 서버가 뚫리는 거예요.
실제로 그렇게 당했고요.
그래서 "중간에 문지기"를 세웁니다
여기서 socket-proxy가 등장합니다.
이름 그대로예요.
docker.sock 앞에 세우는 프록시(중간 대리인)입니다.
비유를 들어볼게요.
원래는 Jenkins가 도커 금고 열쇠를 통째로 들고 있었어요.
뭐든 다 할 수 있는 마스터키요.
socket-proxy는 그 사이에 문지기를 한 명 세우는 거예요.
Jenkins가 "이거 해줘" 하면.
문지기가 봅니다.
"이미지 빌드? 통과."
"컨테이너 안에 들어가겠다고? 안 돼. 거절."
이런 식으로요.

여기가 진짜 중요해요.
socket-proxy는 도커 기능을 하나씩 켜고 끌 수 있어요.
켜면 통과, 끄면 거절이에요.
저는 이렇게 정했습니다.
빌드는 해야 하니까 → IMAGES, BUILD 켬
컨테이너 띄워야 하니까 → CONTAINERS, 시작/정지 켬
근데 딱 하나.
EXEC은 무조건 껐어요.
EXEC이 뭐길래 무조건 막았냐면
지난 편 기억나세요?
공격자가 컨테이너 만들고 이 명령 쳤다고 했죠.
chroot /mnt sh
컨테이너 안에 들어가서 호스트를 장악한 그거요.
이때 쓰는 게 바로 EXEC입니다.
"컨테이너 안에 들어가서 명령 실행해" 하는 기능이에요.
이게 이번 침해의 진짜 무기였어요.
컨테이너를 만드는 것 자체는 사실 별 거 아니에요.
문제는 그 안에 들어가서(EXEC) 호스트로 탈출하는 거였거든요.
그래서 EXEC만 확실히 막으면.
설령 또 뚫려도.
컨테이너 안으로 들어가 chroot 치는 그 경로가 막힙니다.
한마디로.
이번에 당한 그 수법을 정확히 차단하는 거예요.
솔직히 이게 완벽한 건 아니에요
여기서 솔직하게 말할게요.
socket-proxy 쓴다고 100% 안전한 건 아닙니다.
문지기한테 "이건 통과시켜" 항목이 많아질수록.
막는 의미가 줄어들거든요.
실제로 저도 자동배포 하려다가.
이거 열고, 저거 열고...
(이 삽질은 4편에서 제대로 풀게요. 403 에러랑 한참 싸웁니다.)
근데 그래도 핵심은 지켰어요.
EXEC은 끝까지 안 열었거든요.
도커 금고를 통째로 주느냐.
문지기 세우고 위험한 것만 막느냐.
이 차이는 큽니다.
특히 한 번 당해본 입장에선요.
AI 에이전트도 똑같아요
이 얘기 어디서 들어본 것 같지 않으세요?
맞아요.
제가 전에 Claude Code, Codex 글에서 했던 얘기랑 같아요.
AI 코딩 에이전트도 결국 도커 위에서 돌거든요.
"AI한테 docker.sock 주면 편하긴 한데."
그게 AI가 뚫리면 서버 전체가 뚫리는 거랑 같아요.
Jenkins든.
AI든.
자동화 도구한테 도커 권한을 줄 때는.
항상 같은 질문을 해야 합니다.
"얘가 뚫리면, 어디까지 내줄 건가?"
docker.sock 통째로 = 서버 전체
socket-proxy + EXEC 차단 = 위험한 건 막힘
저는 이번에 후자를 택했어요.
비싼 수업료 내고 배운 거죠.
결국 핵심은 격리예요
자동화는 편합니다.
push 한 번에 배포까지 되니까요.
근데 그 편함의 대가가.
"도구한테 너무 많은 권한을 주는 것"이면 안 돼요.
편한 만큼.
뚫렸을 때 잃을 것도 커지거든요.
그래서 중간에 문지기 하나 세우는 거예요.
조금 번거롭더라도.
이게 6주 채굴당하는 것보단 훨씬 낫습니다.
다음 편 예고
자, docker.sock은 막았어요.
이제 서비스를 새 서버로 옮겨야죠.
저는 도메인이 7개예요.
이걸 하나씩, 끊김 없이 HTTPS로 옮겨야 합니다.
운영 중인 서비스를 옮기는 거라.
잘못하면 사용자한테 에러 페이지 보여주거든요.
다음 편에서는 nginx랑 certbot으로.
7개 도메인을 무중단으로 옮긴 이야기를 풀게요.
컨테이너 이름으로 라우팅하는 깔끔한 방법도 같이요.
'서버, 인프라' 카테고리의 다른 글
| 7개 도메인을 무중단으로 HTTPS 이전한 이야기 (0) | 2026.06.19 |
|---|---|
| 내 서버가 6주째 몰래 채굴당하고 있었습니다 (0) | 2026.06.18 |
| Docker 안에서 Claude Code, Codex 쓰다가 git push 막힌 분들 보세요 (0) | 2026.06.03 |
| Ubuntu 서버에 Claude Code + Codex 올려봤더니, 개발 방식이 달라졌어요 (0) | 2026.06.02 |
| [Claude 블로그 자동화] 블로그 글감 자동화 완성 — 수집부터 티스토리 발행까지 5편 (0) | 2026.05.31 |