Tiny Star

IT

[Cloudflare Tunnel] 우리집 IP 노출 없이 노트북을 연결해보자

하얀지 2025. 7. 16. 15:53

왜 Cloudflare Tunnel을 알아보게 되었을까?

처음에는 Oracle Cloud Free Tier로 서버를 구성해보려 했다. 하지만 예상치 못한 문제가 있었는데, "Out of host capacity" 에러가 2주 넘게 지속되면서, 언제쯤 VM을 생성할 수 있을지 알 수 없었기 때문에 마냥 기다릴 수만은 없었다. [관련 글 보기]

그래서 대안을 고민하다가, 내부 서버를 직접 구축해보기로 했다. 라즈베리파이도 고려했지만 추가 비용이 들어 부담이 되었고, 결국 기존에 사용하던 노트북을 서버로 활용해보기로 했다.

하지만 여기에도 문제는 있었는데, 외부에서 접속하려면 내부 IP를 노출하고 포트를 개방해야 하기 때문에 보안 측면에서 불안했다.

그러던 중 Cloudflare Tunnel을 알게 되었고, 이걸 이용하면 공인 IP를 노출하지 않고도 도메인을 통해 안전하게 접속할 수 있다는 사실을 알게 되어 알아보게되었다.

 

 

Cloudflare Tunnel이란?

내부 네트워크나 로컬 환경에서 실행 중인 애플리케이션을 외부 인터넷에 노출시키지 않고도 안전하게 접속할 수 있게 해주는 서비스
간단히 말하면, 공인 IP 없이도 도메인을 통해 안전하게 내 서비스에 접속할 수 있게 해주는 역방향 터널(reverse tunnel)이다.

 

 

왜 필요한가?

기존 방식에서는 서비스를 외부에 공개하려면 보통 다음과 같은 절차가 필요

  1. 포트를 외부에 개방 (방화벽 설정)
  2. 공인 IP를 사용하거나 DDNS 설정
  3. 도메인 연결
  4. SSL 인증서 관리

하지만 이 과정은 보안 위협(해킹, DDoS 등)에 노출되기 쉽고, 설정도 번거롭다.
Cloudflare Tunnel은 이 복잡한 과정 없이, 단 한 줄의 명령어로 안전하게 서비스 연결을 만들 수 있다.

 

 

어떻게 작동하는가?

[클라이언트 브라우저] → [Cloudflare 도메인(외부 도메인 가능)] → [Cloudflare Edge] ←[터널]← [내 로컬 서버]
  1. 내부 서버에서 cloudflared라는 데몬(프로세스)을 실행
  2. 이 cloudflared는 Cloudflare Edge 네트워크에 터널을 생성
  3. 클라이언트가 도메인으로 접속하면, Cloudflare는 해당 트래픽을 이 터널을 통해 내 서버에 전달
  4. 내 서버의 IP는 공개되지 않고, 오직 Cloudflare를 통해서만 접근이 가능

 

 

IP가 왜 노출되지 않는가?

  • 클라이언트는 Cloudflare의 IP로만 접속한다. 내 서버는 수신 요청을 직접 받지 않고, 오히려 Cloudflare에 먼저 연결을 열고 요청을 기다리는 구조이다.
  • 즉, 내 서버는 외부에서 접근할 수 없는 상태이며, 모든 트래픽은 Cloudflare를 통해서만 전달된다.
  • 이 구조는 마치 "전화가 걸려오는 걸 기다리는 게 아니라, 내가 먼저 전화해놓고 상대의 요청을 듣는" 구조로 볼 수 있다.

 

 

어떻게 사용하는가? (요약)

1. Cloudflare 계정 생성 → 도메인 등록

2. cloudflared CLI 설치

3. 인증 및 터널 생성

 
cloudflared tunnel login
cloudflared tunnel create [my-tunnel]
cloudflared tunnel route dns [my-tunnel] [example.com]

4. 서비스 실행

cloudflared tunnel run [my-tunnel]

이후 클라이언트는 https://example.com 으로 접속하면 자동으로 내 로컬 서버로 트래픽이 전달된다.

 

 

연결 화면

도메인을 등록하고 상태가 "활성"으로 바뀌어야 정상이다.

 

 

외부 도메인을 사용하고 있다면, 도메인 이름 서버에 해당 값들을 제대로 넣어줘야 활성화된다.

 

 

ubuntu@DESKTOP:~/.cloudflared$ cat config.yml
tunnel: ssh-tunnel
credential-file: /home/ubuntu/.cloudflared/015b.json

ingress:
  - hostname: ssh.example.com
    service: ssh://localhost:22

  - hostname: mariadb.example.com
    service: tcp://localhost:3306

  - hostname: redis.example.com
    service: tcp://localhost:6379

  - hostname: kafka.example.com
    service: tcp://localhost:9092

  - hostname: api.example.com
    service: http://localhost:8080

  - hostname: newsgpt.example.com
    service: http://localhost:4173

  - service: http_status:404

이렇게 config.yml 에 원하는 서비스를 추가해주고 터널을 재실행하고 프론트 URL (위에서는 newsgpt.example.com)에 접속하면 접속이 된다.

Redis, Kafka, DB 등은 내부 IP 에서 연결하고 있기 때문에 프로젝트 내 연결 주소는 localhost:port 로 고정했다.

 

 

도메인으로 노트북으로 실행중인 프론트를 확인할 수 있다.

 

PS C:> nslookup api.[example.com]
서버:    kns.kornet.net
Address:  168.120.60.1

권한 없는 응답:
이름:    api.[example.com]
Addresses:  2606:1234:3030::6815:11b0
          2606:1234:3030::ac11:1a40
          172.67.154.73
          104.21.64.179

도메인을 nslookup 해보면 104.21.64.179, 172.67.154.73 과 같은 IP가 나타난다.
이 주소들이 Cloudflare 소유의 IP인지 확인하려면 https://bgp.he.net에서 조회해보면 된다.
실제로 이 IP들은 Cloudflare가 공식적으로 사용하는 프록시 서버용 IP 대역에 속해 있으며,
덕분에 내 서버의 실제 위치(IP)는 노출되지 않고, 오직 Cloudflare를 통해서만 접근이 이뤄지게 된 것을 확인할 수 있다.

 

 

사용 후기

도메인 1년 비용 1만원대로 서버를 구축하다니 저렴하다. (전기 비용은 별도...)

너무 많은 트래픽은 제한된다고하니 개인 프로젝트 용도로만 사용할만하다.

 

API의 백엔드 로그에는 1초로 찍히는 데, 실제로 응답 시간으로보면 2~3초가 걸리는 경우가 많다. 중간에 Cloudflare Tunnul 를 거치다 보니 생기는 딜레이로 보인다. 빠른 응답(Socket통신 같은)이 필요한 경우라면 부적합하다.

 

오라클 프리티어로 1RAM+1CORE로 4개 생성해서 서비스를 구성해볼까 하다가, 사양이 너무 작아서 후에 프로젝트가 무거워지면 면 안돌아갈 것 같아서 시도하지 않았다. 여전히 프리티어 인스턴스 생성을 시도하고 있는데, 생성되면 서버를 옮겨야겠다. (언젠가...ㅠ)

 

 

+ 재부팅되면 tunnel run 을 해줘야하는데, 해당 스크립트 구성한건 나중에 추가하겠다.

top