Cloudflare Tunnel로 HTTPS 오리진 트러블슈팅하기
Cloudflare Tunnel이 Healthy인데도 app.example.com이 실패한다면, 경로의 Service URL, 오리진 인증서, SSL/TLS 암호화 모드를 확인해요.
Healthy 상태는 cloudflared가 Cloudflare에 연결된다는 것만 확인해줘요. 경로의 서비스나 로컬 오리진을 테스트하지는 않아요.
출처: 문서
본문
이 가이드는 이미 Let's Encrypt 인증서로 HTTPS를 제공하는 오리진을 다뤄요. 기존 인증서를 설치한 채로 유지할 수 있어요.
HTTP를 HTTPS로 리다이렉트하는 Apache 오리진에는 다음 설정을 사용해요:
- Service URL:
cloudflared가 Apache 호스트에서 실행될 때https://localhost:443 - Origin Server Name: 인증서가 커버하는 호스트 이름(예:
app.example.com) - Disable TLS certificate verification: 꺼짐
- Encryption mode: Automatic SSL/TLS (recommended) 를 선택한 채로 두거나 Full (Strict) 를 선택해요
경로 이해하기(Understand the route)
공개 호스트 이름은 방문자가 요청하는 URL이에요. Service URL은 cloudflared가 도달할 수 있는 주소, 프로토콜, 포트예요. 이 두 값은 서로 바꿔 쓸 수 없어요. 그 호스트 이름이 Tunnel CNAME을 가리킬 때는 공개 호스트 이름을 서비스 URL로 사용하지 마세요.
예를 들어 http://localhost:80은 로컬 연결에 HTTP를 사용하고, https://localhost:443은 HTTPS를 사용해요. 이 예시를 여러분의 오리진이 사용하는 주소와 포트로 바꿔요.
Cloudflare와 cloudflared 사이의 연결은 존 SSL/TLS 모드와 독립적으로 암호화돼요. cloudflared는 오리진 매개변수를 통해 로컬 오리진 인증서를 검증해요.
존 SSL/TLS 모드는 Service URL을 변경하지 않아요. 경로에서 로컬 프로토콜을 구성한 다음 originServerName과 다른 오리진 매개변수로 인증서 검증을 구성해요.
originServerName이 비어 있으면 cloudflared는 인증서가 Service URL의 호스트를 커버하길 기대해요. localhost를 사용하는 서비스 URL에서는 originServerName을 인증서가 커버하는 호스트 이름으로 설정해요. 이 값은 TLS 연결의 Server Name Indication(SNI)도 제공해요.
경로 및 SSL/TLS 설정 선택하기
로컬 프로토콜과 인증서 설정을 선택하려면 다음 결정 트리를 사용해요:
flowchart TD
accTitle: Service URL and SSL/TLS mode decision tree
accDescr: Choose the Service URL from the origin protocol, then configure certificate validation for HTTPS origins.
A{Origin accepts HTTPS?}
A -->|No| B{HTTP redirects to HTTPS?}
B -->|No| C[Use HTTP service URL]
B -->|Yes| D{Keep the redirect?}
D -->|No| C
D -->|Yes| E[Configure an HTTPS listener]
A -->|Yes| F[Use HTTPS service URL]
E --> F
F --> G{Certificate covers service host?}
G -->|Yes| H[Keep TLS verification on]
G -->|No| I[Set Origin Server Name and keep verification on]
오리진에 HTTPS 리스너가 없다면 HTTP Service URL을 유지하기 전에 리다이렉트를 제거하거나 조정해요. HTTPS Service URL을 HTTP 리스너에 지정하지 마세요.
다음 표로 일반적인 오리진 및 존 설정을 비교해요:
| Origin behavior | Service URL | Origin parameters | Zone SSL/TLS guidance |
|---|---|---|---|
| HTTP only, with no redirect | http://127.0.0.1:80 |
No TLS parameters | Automatic, Flexible, Full, and Full (strict) do not change the local HTTP connection. |
| HTTP redirects to HTTPS | https://localhost:443, or remove the redirect and use HTTP |
Configure the route as HTTPS | Do not use Flexible to solve the redirect loop. |
HTTPS with a valid Let's Encrypt certificate for app.example.com |
https://localhost:443 |
Set originServerName: app.example.com. Keep Disable TLS certificate verification turned off and omit caPool. |
Choose the zone mode separately. It does not validate the local certificate. |
| HTTPS with a private certificate authority (CA) | https://localhost:443 |
Set originServerName and caPool. Keep Disable TLS certificate verification turned off. |
Choose the zone mode separately. Fix certificate trust first. |
공개 HTTPS 호스트 이름의 경우 Full (strict) 가 이 구성과 호환돼요. 하지만 cloudflared는 로컬 Let's Encrypt 인증서를 독립적으로 검증해요. 존 모드는 경로의 Service URL이나 originServerName 설정을 대체하지 않아요.
Full도 Tunnel 서비스 프로토콜을 변경하거나 오리진 인증서 오류를 고치지 않아요. 두 문제 모두에 Flexible로 전환하지 마세요. 대신 경로의 Service URL 또는 오리진 매개변수를 업데이트해요.
원격 관리 경로 업데이트하기
원격 관리 터널의 경우 대시보드에서 경로와 오리진 매개변수를 업데이트해요:
-
Cloudflare 대시보드 ↗︎에서 Networking > Tunnels로 이동한 뒤 터널을 선택해요. Tunnels로 이동 ↗
-
Routes에서
app.example.com에 대해 Edit route를 선택해요. -
Service URL에 오리진이 HTTPS를 제공할 때
https://localhost:443을 입력해요. 서비스가 HTTP를 사용하고 HTTPS로 리다이렉트하지 않을 때만http://127.0.0.1:80을 사용해요. -
Additional application settings를 펼쳐요. TLS 아래에서, 인증서가 그 호스트 이름을 커버할 때 Origin Server Name을
app.example.com으로 설정해요.Disable TLS certificate verification은 꺼두어요. 공개적으로 신뢰되는 Let's Encrypt 인증서에는 CA Pool을 비워 두어요. 오리진이 프라이빗 CA를 사용할 때만 설정해요.
-
Save changes를 선택해요.
경로는 기존 Let's Encrypt 인증서를 제거할 것을 요구하지 않아요. 오리진 이름과 서비스 프로토콜이 일치하면 cloudflared가 그 인증서를 검증할 수 있어요.
SSL/TLS 모드를 분리해서 유지하기
존 SSL/TLS 모드는 Tunnel 경로와 별개예요. 로컬 프로토콜을 선택하거나 cloudflared와 오리진 사이의 인증서 불일치를 고치지 않아요.
존 모드를 검토하거나 변경하려면:
- Cloudflare 대시보드 ↗︎에서 SSL/TLS > Overview로 이동해요. Overview로 이동 ↗
- SSL/TLS Overview에서 Configure를 선택해요.
- Encryption mode에서 선택된 옵션을 검토해요. Automatic SSL/TLS (recommended) 가 선택되어 있다면 이 Tunnel 경로를 트러블슈팅하는 동안 그대로 두어요. Automatic 모드는 경로의 Service URL을 변경하지 않아요.
- 특정 모드를 사용하려면 Full (Strict) 를 선택한 뒤 Save를 선택해요. 이 존 설정은
cloudflared의 인증서 검증을 대체하지 않아요. - 로컬 오리진 인증서 불일치를 해결하려고 Flexible을 선택하지 마세요. 대신 Tunnel 경로의 Service URL 또는 오리진 매개변수를 업데이트해요.
사용 가능한 모드에 대한 자세한 내용은 SSL/TLS 암호화 모드를 참고해요. 오리진이 HTTP를 HTTPS로 리다이렉트한다면 HTTP Service URL이 리다이렉트 루프를 일으킬 수 있어요. 다른 리다이렉트 원인은 ERR_TOO_MANY_REDIRECTS를 참고해요.
로컬 관리 터널 구성하기
로컬 관리 터널의 경우 config.yml에 같은 설정을 넣어요:
tunnel: <TUNNEL_UUID>
credentials-file: /path/to/<TUNNEL_UUID>.json
ingress:
- hostname: app.example.com
service: https://localhost:443
originRequest:
originServerName: app.example.com
- service: http_status:404
이 예시는 TLS 검증을 켠 채 유지해요. 표준 Let's Encrypt 인증서는 공개적으로 신뢰되므로 caPool을 생략해요. 프라이빗 CA의 경우 originRequest 아래에 caPool: /path/to/ca.pem을 추가해요.
Windows에서 cloudflared가 시스템 루트 인증서 풀을 로드할 수 없다고 보고하면 caPool을 인증 기관이 들어 있는 로컬 PEM 번들로 설정해요.
noTLSVerify: true는 인증서 신뢰나 오리진 이름을 고치는 동안에만 임시 최후 수단으로 사용해요. 근본 문제를 해결한 뒤에는 꺼두어요.
파일 끝에 catch-all http_status:404 규칙이 필요해요. config.yml을 편집한 뒤 인그레스 규칙을 검증해요:
cloudflared tunnel ingress validate
진단 실행하기(Run diagnostics)
공개 인터넷과 cloudflared와 같은 호스트에서 이 검사를 실행해요:
-
공개 호스트 이름과 DNS를 확인해요. Cloudflare 대시보드에서
example.com에 대해 DNS > Records로 이동해요.app.example.com이<TUNNEL_ID>.cfargotunnel.com을 가리키는CNAME인지 확인해요. Records로 이동 ↗터미널에서 정확한 호스트 이름을 조사해요:
dig CNAME app.example.com +short dig A app.example.com +short dig AAAA app.example.com +short프록시된 레코드는
CNAME대상 대신 Cloudflare 주소를 반환할 수 있어요. 그런 경우 대시보드로 대상을 확인해요. Cloudflare는 Tunnel에서A또는AAAA레코드로 조용히 폴백하지 않아요. 터널이 중지되면 DNS 레코드는 남고 방문자는1016오류를 받아요. 자세한 내용은 Tunnel DNS 레코드를 참고해요. 트래픽이 오리진으로 직접 가는 것처럼 보이면 정확한 호스트 이름에 기대한 CNAME 대신A또는AAAA레코드가 있는지, 또는 명시적인 로드 밸런서나 다른 경로가 이를 서빙하는지 확인해요. -
리다이렉트 헤더와 상태를 조사해요. 클라이언트에서 공개 호스트 이름을 요청하고 제한된 수의 리다이렉트를 따라가요:
curl -sS -D - -o /dev/null https://app.example.com/ curl -sS -D - -o /dev/null -L --max-redirs 5 https://app.example.com/반복되는
Location헤더와301,302,307,308상태 코드를 찾아봐요.cloudflared호스트에서 HTTP 리스너를 직접 테스트해요:curl -sS -D - -o /dev/null -H "Host: app.example.com" http://127.0.0.1:80/오리진이 HTTPS
Location헤더를 반환하면 HTTPSService URL을 사용하거나 오리진 리다이렉트 정책을 바꿔요. HTTPService URL은 모든 요청을 HTTP로 오리진에 보내므로 리다이렉트를 무한히 반복할 수 있어요. -
오리진 인증서와 SNI를 확인해요.
cloudflared가 실행되는 호스트에서 실행해요:openssl s_client -connect 127.0.0.1:443 -servername app.example.com -verify_hostname app.example.com -verify_return_error </dev/null인증서에
app.example.com이 포함되고 출력에Verify return code: 0 (ok)가 있는지 확인해요. 서비스 URL이localhost를 사용하는데 인증서가app.example.com을 커버한다면 Origin Server Name을app.example.com으로 설정해요. -
Tunnel 로그를 스트리밍해요. 터널 상세 페이지에 Live logs 탭이 있으면 열고 Live를 선택해요. 원격 로그 스트리밍을 사용하거나 인증된 머신에서 이 명령을 실행할 수도 있어요:
cloudflared tail <TUNNEL_UUID>connection refused, 잘못된 HTTP 응답,x509오류, TLS 핸드셰이크 오류를 찾아봐요. 이 메시지들은 Tunnel 상태가Healthy로 유지되더라도cloudflared와 로컬 오리진 사이의 실패를 식별해요.
프로토콜 세부 정보는 지원되는 Tunnel 프로토콜을, 모든 오리진 설정은 Tunnel 오리진 매개변수를 참고해요.
더 알아보기 (Learn more)
Healthy 상태는 Cloudflare 연결만 확인하므로, HTTPS 오리진 문제는 Service URL·originServerName·인증서 검증을 분리해서 점검해요. 존 SSL/TLS 모드는 Tunnel 경로와 별개라는 점을 기억하세요.