AI와 개발을 쉽게 이해하는 실험실

비개발자도 따라오는 AI 도구, 자동화, 개발 실험 기록

개발 & 기술/DevOps·인프라

Cloudflare Tunnel 끊김, 원인 진단과 재연결 자동화 정리

루민 Lumin 2026. 7. 30. 09:48
반응형

Cloudflare Tunnel 끊김은 일부 환경에서는 네트워크 경로, 인증서 만료, cloudflared 프로세스 관리 중 한 곳에서 시작됩니다. 이 글은 터널이 자꾸 죽거나 재시작 후 살아나지 않을 때 어디부터 확인해야 할지, 그리고 사람 손이 없어도 다시 붙게 만드는 방법 다섯 가지를 정리합니다. 처음엔 "재부팅하면 되지"로 넘기기 쉽지만, 반복되는 끊김은 대체로 설정 한두 줄과 감시 스크립트로 해결됩니다. 반대로 원인 진단을 건너뛰면 자동 재시작이 로그만 지저분하게 만드는 경우도 있습니다.

Cloudflare Tunnel 끊김, 원인 진단과 재연결 자동화 정리의 핵심 개념을 단순한 테크 일러스트로 표현한 대표 이미지

먼저 용어 하나만 짚고 갑니다. Cloudflare Tunnel은 내 서버(집·회사 안에 있는 컴퓨터)와 Cloudflare 네트워크 사이에 암호화된 통로를 뚫어주는 서비스입니다. 이 통로를 만드는 프로그램이 cloudflared(클라우드플레어드)라는 작은 실행 파일이고, 이게 계속 살아 있어야 외부에서 내 서버로 접속할 수 있습니다.

끊김이 발생했을 때 먼저 볼 세 가지

터널이 끊겼다고 느껴지면 로그·네트워크·프로세스 상태 세 가지를 순서대로 확인합니다. 이 셋 중 어디에 흔적이 남았는지에 따라 원인이 완전히 갈립니다.

로그부터 봅니다. 리눅스 서버에서 cloudflared를 서비스로 돌리고 있다면 아래 명령으로 최근 로그를 볼 수 있습니다.

journalctl -u cloudflared -n 200 --no-pager

이 명령은 "cloudflared라는 서비스의 최근 로그 200줄을 보여줘"라는 뜻입니다. 여기서 ERR, connection refused, context deadline exceeded, failed to serve tunnel connection 같은 문구를 찾습니다.

로그가 깨끗한데도 접속이 안 된다면 네트워크 쪽입니다. 공유기 재시작, ISP의 유동 IP 변경, DNS 캐시 문제 등이 흔한 원인입니다.

프로세스는 살아 있는데 터널만 죽어 있는 경우도 있습니다. 이때는 cloudflared가 실행 중이라도 Cloudflare 엣지와의 연결이 끊긴 상태라, 재시작이 필요합니다.

증상 유력한 원인 위치 첫 확인 명령
접속 자체가 안 됨, 로그에 오류 다수 cloudflared 자체 문제 journalctl -u cloudflared
로그는 정상인데 외부에서만 안 됨 네트워크·DNS dig, curl로 외부 확인
잠깐 되다가 환경과 절차에 따라마다 끊김 커넥션 유지·타임아웃 라우터/방화벽 설정
서버 재부팅 후 안 살아남 서비스 자동 시작 미설정 systemctl is-enabled

자주 나오는 원인 패턴

Cloudflare Tunnel이 자꾸 끊기는 원인은 크게 네트워크 경로 문제, 인증·설정 문제, 리소스 문제 세 갈래로 나뉩니다. 원인 갈래를 먼저 알면 해결 방법을 고르는 시간이 훨씬 짧아집니다.

네트워크 경로 문제가 가장 흔합니다. 가정용 공유기가 오래 켜져 있으면 NAT 테이블(외부-내부 주소 변환 기록장)이 꽉 차거나, ISP가 UDP 트래픽을 간헐적으로 끊는 경우가 있습니다. Cloudflare Tunnel은 기본적으로 QUIC(UDP 기반의 최신 프로토콜)로 통신하기 때문에 UDP가 불안정한 회선에서는 끊김이 잦습니다.

인증·설정 문제는 초기 구축 후 몇 달~몇 년 지났을 때 나타납니다. 터널 자격 증명 파일(*.json)이 손상되거나, config.yml에 지정한 로컬 서비스 주소가 바뀐 경우가 대표적입니다.

리소스 문제는 라즈베리파이나 저사양 VM에서 흔합니다. 메모리가 부족해 OOM Killer(메모리 부족 시 프로세스를 강제 종료하는 리눅스 기능)가 cloudflared를 죽이는 사례가 자주 보고됩니다.

[원인 갈래]

네트워크
  ├─ UDP 차단
  ├─ NAT 테이블 만료
  └─ 공유기 재시작

인증/설정
  ├─ 자격 증명 손상
  ├─ config 경로 오류
  └─ 대상 서비스 다운

리소스
  ├─ 메모리 부족
  └─ CPU 스로틀링

해결책 1 — QUIC에서 HTTP2로 프로토콜 바꾸기

UDP가 불안정한 회선이라면 cloudflared의 전송 프로토콜을 HTTP2로 바꾸는 것만으로 끊김이 크게 줄어드는 경우가 많습니다. HTTP2는 TCP 기반이라 방화벽·공유기와 훨씬 잘 맞습니다.

config.yml 파일(보통 /etc/cloudflared/config.yml 또는 ~/.cloudflared/config.yml)을 열어 아래 한 줄을 추가합니다.

protocol: http2

이 설정은 "터널을 열 때 QUIC 대신 HTTP2를 쓰겠다"는 의미입니다. 저장 후 서비스를 재시작합니다.

sudo systemctl restart cloudflared

여기서 systemctl restart는 "이 서비스를 껐다가 다시 켜라"는 리눅스 명령입니다.

💡 QUIC과 HTTP2 중 어느 쪽이 더 나은지는 회선마다 다릅니다. Cloudflare 공식 문서는 기본값 auto를 권장하지만, 잦은 끊김이 있는 환경에서는 http2로 고정하는 게 안정적이라는 사용자 후기가 많습니다.

해결책 2 — systemd로 자동 재시작 걸기

cloudflared가 어떤 이유로 죽었을 때 자동으로 살아나게 하려면 systemd(리눅스의 서비스 관리자)에 재시작 정책을 지정합니다. 이걸 안 걸어두면 프로세스가 죽은 채로 방치됩니다.

cloudflared를 공식 설치 스크립트로 설치했다면 이미 systemd 유닛 파일이 있습니다. 아래 명령으로 확인합니다.

sudo systemctl cat cloudflared

[Service] 섹션에 Restart=on-failure가 있으면 죽었을 때만 다시 켜집니다. 좀 더 공격적으로 재시작하려면 아래처럼 바꿉니다.

파일 위치가 /etc/systemd/system/cloudflared.service라고 가정하면:

[Service]
Restart=always
RestartSec=10
StartLimitInterval=0
  • Restart=always: 어떤 이유로 죽든 환경에 따라 다시 시작
  • RestartSec=10: 10초 기다렸다가 재시작 (너무 빠르면 Cloudflare 쪽에서 속도 제한이 걸릴 수 있음)
  • StartLimitInterval=0: 재시작 횟수 제한 해제

수정 후 반영:

sudo systemctl daemon-reload
sudo systemctl restart cloudflared
sudo systemctl enable cloudflared

마지막 줄 enable은 "서버가 재부팅되어도 이 서비스를 자동으로 켜라"는 뜻입니다. 이걸 빼먹으면 정전이나 재부팅 후 터널이 안 살아납니다.

해결책 3 — 헬스체크 스크립트로 감시하기

systemd만으로는 잡히지 않는 상황이 있습니다. 프로세스는 살아 있는데 실제 터널 연결이 죽은 좀비 상태입니다. 이때는 외부에서 실제 응답을 확인하는 헬스체크가 필요합니다.

간단한 감시 스크립트 예시입니다.

#!/bin/bash
URL="https://my-tunnel-domain.example.com/health"
if ! curl -fsS --max-time 10 "$URL" > /dev/null; then
  logger "cloudflared health check failed, restarting"
  systemctl restart cloudflared
fi

이 스크립트는 "지정한 URL에 환경과 절차에 따라 응답이 없으면 로그를 남기고 cloudflared를 재시작하라"는 뜻입니다. curl -fsS는 조용히 실패를 감지하는 옵션 조합입니다.

이 파일을 /usr/local/bin/tunnel-check.sh로 저장하고 실행 권한을 준 뒤, cron(정해진 시간마다 명령을 실행하는 리눅스 스케줄러)에 등록합니다.

* * * * * /usr/local/bin/tunnel-check.sh

*는 "매분마다 실행"이라는 표기입니다.

감시 방식 장점 주의점
systemd Restart=always 별도 설정 없이 간단 좀비 연결은 못 잡음
cron + curl 헬스체크 실제 응답 확인 헬스체크용 엔드포인트 필요
외부 모니터링 서비스 서버 자체가 죽어도 감지 별도 계정·비용

해결책 4 — 라우터/방화벽 설정 다듬기

가정용 회선이라면 공유기 설정이 원인일 가능성이 큽니다. 특히 SIP ALG, IPv6 방화벽 자동 차단, UPnP 자동 정리 같은 기능이 터널 연결을 끊는 흔한 범인입니다.

  • 공유기 관리 페이지에서 SIP ALG 비활성화 확인
  • UDP 아웃바운드 차단 규칙이 없는지 확인
  • MTU(패킷 최대 크기) 설정이 회선에 맞는지 확인
  • 공유기 펌웨어를 최신 버전으로 업데이트

여러 공유기 문제가 겹친다면 protocol: http2 설정과 병행하는 게 가장 안전합니다.

해결책 5 — 리소스 모니터링과 로그 로테이션

저사양 서버에서 반복적으로 죽는다면 리소스 문제일 가능성이 큽니다. 메모리가 남아도는지, 로그 파일이 디스크를 다 채우고 있지는 않은지 확인합니다.

free -h
df -h

free -h는 메모리 상태를, df -h는 디스크 사용량을 사람이 읽기 편한 단위로 보여줍니다.

로그가 계속 쌓이면 디스크가 꽉 차 cloudflared가 로그를 못 써서 죽는 경우도 있습니다. journald(리눅스 로그 관리자)에 크기 제한을 걸어둡니다. /etc/systemd/journald.conf에서:

SystemMaxUse=200M

이 설정은 "시스템 로그가 200MB를 넘지 않게 자동으로 오래된 것부터 지워라"는 뜻입니다.

라즈베리파이처럼 SD카드 기반 장비라면 로그를 tmpfs(램 위에 만드는 임시 파일 시스템)에 두는 것도 방법이지만, 재부팅 시 로그가 사라진다는 점은 감안해야 합니다.

다음에 또 끊기면 확인할 순서

한 번 세팅해두면 일부 환경에서는의 끊김은 자동으로 복구됩니다. 그래도 또 문제가 생기면 아래 순서로 짧게 훑는 게 가장 빠릅니다.

  1. journalctl -u cloudflared -n 100 — 최근 오류 메시지 확인
  2. systemctl status cloudflared — 서비스가 살아 있는지 확인
  3. curl 로 헬스체크 URL 직접 호출 — 실제 응답 여부 확인
  4. 공유기 재시작 — 네트워크 계층 초기화
  5. 그래도 안 되면 자격 증명 파일 재발급 검토

끊김이 특정 시간대에 몰린다면 ISP 회선 문제일 가능성이 높고, 무작위로 발생한다면 리소스나 프로세스 관리 쪽을 다시 봐야 합니다. 원인 갈래만 좁혀도 해결까지의 거리가 훨씬 짧아집니다. 자세한 옵션과 최신 설정 키는 Cloudflare 공식 문서에서 확인하는 걸 권장합니다.

함께 보면 좋은 글

반응형