포트 포워딩을 구글링하느라 몇 시간을 보냈다. 그리고 Cloudflare Tunnel을 찾았다
Source: Dev.to

저는 NAT 뒤에 있는 서버에서 내부 서비스를 실행하고 있습니다. 사설 IP이고, 외부에서 접근할 수 없습니다. 전형적인 악몽이죠.
제 ISP는 정적 IP를 제공하지 않습니다. 라우터의 포트‑포워딩 UI는 2003년에 만든 것처럼 보입니다. 그리고 마침내 작동시키면 IP가 바뀌면서 모든 것이 깨집니다.
그때 Cloudflare Tunnel을 발견했습니다. 맞춤 도메인으로 서비스를 인터넷에 노출하는 데 10 분밖에 걸리지 않았습니다. 포트 포워딩이 필요 없고, 정적 IP도 필요 없습니다. 무료입니다.
제가 정확히 어떻게 했는지 알려드리겠습니다.
문제
나는 192.168.39.231:8088에서 서비스를 실행하고 있었다. 자체 서명된 인증서를 사용한 HTTPS. 어디서든 접근할 수 있어야 했으며, 가능하면 myapp.mydomain.com 같은 멋진 도메인으로 접근하고 싶었다.
전통적인 접근 방식:
- 고정 IP를 얻는다 (비용이 든다)
- 라우터에서 포트를 포워딩한다 (귀찮다)
- 동적 DNS를 설정한다 (추가 관리가 필요함)
- SSL 인증서를 처리한다 (Let’s Encrypt도 작동하지만 여전히 번거롭다)
또는 Cloudflare Tunnel을 사용한다.
Quick Tunnel (The Fast Way)
만약 빠르게 뭔가를 테스트하고 싶다면, 설정이 전혀 필요 없는 옵션이 있습니다:
cloudflared tunnel --url https://192.168.39.231:8088 --no-tls-verify
Cloudflared는 alice-ion-married-knights.trycloudflare.com 와 같은 무작위 URL을 제공합니다. 이제 여러분의 서비스가 공개됩니다.
--no-tls-verify 플래그는 원본 서버가 자체 서명 인증서를 사용하고 있을 때 중요합니다. 이 플래그가 없으면 cloudflared가 인증서를 검증할 수 없어서 연결을 거부합니다.
무작위 URL은 이상적이지 않으므로, 적절한 커스텀 도메인을 설정해 보겠습니다.
Named Tunnel (The Right Way)
You need a Cloudflare account and your domain added to Cloudflare.
Step 1: Login
cloudflared tunnel login
A browser window opens; authenticate. Cloudflared downloads a cert to ~/.cloudflared/cert.pem.
Step 2: Create the tunnel
cloudflared tunnel create my-app
Output example:
Tunnel credentials written to /root/.cloudflared/8a0b7c44-4677-421e-810b-f5e6de9d0555.json
Created tunnel my-app with id 8a0b7c44-4677-421e-810b-f5e6de9d0555
Save that tunnel ID; you’ll need it later.
Step 3: Route your domain
cloudflared tunnel route dns my-app app.yourdomain.com
This creates a CNAME record in Cloudflare pointing your subdomain to the tunnel.
Step 4: Create the config file
Create ~/.cloudflared/config.yml:
tunnel: my-app
credentials-file: /root/.cloudflared/8a0b7c44-4677-421e-810b-f5e6de9d0555.json
ingress:
- hostname: app.yourdomain.com
service: https://192.168.39.231:8088
originRequest:
noTLSVerify: true
- service: http_status:404
Replace the tunnel ID and hostname with your own values. The noTLSVerify: true line is the config‑file equivalent of --no-tls-verify and is required for self‑signed certificates. The final ingress rule catches everything else and returns a 404; it’s mandatory.
Step 5: Run the tunnel
cloudflared tunnel run my-app
Your service is now live at https://app.yourdomain.com.
흔히 겪는 문제
“Unable to reach the origin service”
서비스가 실행 중이 아니거나 cloudflared가 접근할 수 없습니다. 로컬에서 테스트해 보세요:
curl -k https://192.168.39.231:8088
curl이 접근하지 못한다면 cloudflared도 접근할 수 없습니다.
“tls: failed to verify certificate”
원본 서버가 자체 서명 인증서를 사용하고 있습니다. 빠른 터널을 위해 --no-tls-verify를 추가하거나, 명명된 터널의 설정에 noTLSVerify: true를 넣으세요.
“credentials file doesn’t exist”
config.yml에서 자리표시자 경로를 Step 2에서 만든 실제 자격 증명 파일 경로로 교체하지 않았을 가능성이 높습니다. 경로가 정확히 일치하는지 확인하세요.
서비스로 실행하기
터미널을 영원히 열어 두고 싶지는 않을 겁니다. cloudflared를 시스템 서비스로 설치하세요:
cloudflared service install
systemctl start cloudflared
systemctl enable cloudflared
이제 부팅 시 자동으로 실행되며, 충돌 시 자동으로 재시작됩니다.
Why This Is Better
- 포트‑포워딩 고민 없음
- 고정 IP 불필요
- 동적 DNS 관리 필요 없음
- Cloudflare의 무료 SSL
- 엄격한 NAT와 방화벽 뒤에서도 작동
- 터널이 아웃바운드로 연결되므로 인바운드 포트가 차단돼도 작동
몇 년 전에 이걸 알았어야 했는데.
요점
내부 서비스를 기존 방식으로 인터넷에 노출하고 있다면, 그만두세요. Cloudflare Tunnel은 설정하는 데 약 10 분 정도 걸리며, 바로 작동합니다.
빠른 터널은 테스트에 아주 좋습니다. 맞춤 도메인이 있는 명명된 터널은 프로덕션‑급 모든 경우에 적합합니다.
어떤 내부 서비스를 노출하고 계신가요? 자유롭게 공유해주세요—다른 사람들이 터널을 통해 어떤 서비스를 실행하고 있는지 궁금합니다.