25년 5월 기준, localhost 서비스를 공개하는 방법은 크게 2가지가 있다.

  1. 공유기 DDNS, 포트포워딩 사용
  2. cloudflared 사용 (최신방법)

두번째 방법은 25년 5월 기준으로 아직은 신규 서비스라 잘 알려지지 않았다

그래서 cloudflared 를 이용하는 방법과, 이것이 공유기를 이용하는 것보다 권장되는 이유를 설명한다

요약하자면, 서버의 IP를 공개하지 않고 웹서비스를 제공할 수 있기 때문에, L3 L4 공격을 원천적으로 차단할 수 있다. 심지어 서버의 ip가 바뀌어도 cloudflared 만 켜면 오픈이 되니까 공유기에 접속해서 설정을 해야하는 과정도 필요없다.

간단하고, 무료이고, 무엇보다 안전하다. 안 쓸 이유가 없다.


기존에 홈서버의 서비스를 제공하기 위해서는 ip를 오픈해야 했다. 이렇게 localhost를 넘어보면, 초대하지 않은 공격을 먼저 마주하게 된다. 아마 여러분들도 겪어봤거나, 겪게 될 것이다.

(아래는 공격사례)

서버의 IP와 포트를 외부에 노출하는 순간, 포트스캔부터 시작해 여러가지 공격들에 노출된다. 만약 ssh 포트를 열어둔 상태로 ip를 공개한다면? 나만의 홈서버가 해커들의 놀이터가 되는 것은 한순간이다.

Cloudflared 는 무엇을 해주는가?

웹서버의 IP를 숨겨서 웹서비스를 제공할 수 있게 해준다. 대체 어떻게?

아래 그림을 보면 직관적으로 이해할 수 있을 것이다.

Cloudflared 를 통한 서비스 제공 구조

서버에 cloudflared를 설치하고 구동시키면 cloudflared Cloudflare Network 에 접속해 터널을 맺는다.

그러면 사용자가 발생시킨 요청부터 서버까지 브라우저Cloudflare Edge ServerTunnelcloudflaredWeb server 순서로 연결성이 생긴다

더 자세한 내용을 알고 싶은 분들을 위해 아래 링크를 남겨둔다.

Cloudflare Tunnel
Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address. With Tunnel, you do not send traffic to an external IP — instead, a lightweight daemon in your infrastructure (cloudflared) creates outbound-only connections to Cloudflare’s global network. Cloudflare Tunnel can connect HTTP web servers, SSH servers, remote desktops, and other protocols safely to Cloudflare. This way, your origins can serve traffic through Cloudflare without being vulnerable to attacks that bypass Cloudflare.

IP 공개방식과 cloudflared 비교

구조가 이렇다 보니, 다른 방법(DDNS, 공유기 등)으로 웹서비스를 제공하는 것보다 아래와 같은 장점이 있다.

장점

  • 보안성 향상
    포트스캔 등 L3, L4 등의 공격을 원천적으로 차단할 수 있다. DNS 에는 Cloudflare의 IP만 보인다. 따라서 다른 방법으로 서버에 접근할 방법이 아예 없어지는 것이다. (원격 관리가 필요하면 tailscale을 쓰면 된다)
  • 편리성 증가
    외부 환경의 변화에서 상당히 자유로워진다. 특히 이사를 하거나 통신사를 변경하거나 컴퓨터를 바꾸거나 공유기를 바꾸는 경우에도, 웹서비스를 외부에 제공하기 위한 별도의 인프라 조치가 필요없다. 그저 cloudflared 를 켜기만 하면 그 즉시 웹서비스가 제공된다.
  • 신규 생성 용이
    새로운 서비스를 만들고 이를 공개하기가 매우 용이하다. 새로운 웹서비스를 오픈할 때마다 cloudflared 컨테이너를 새로 만들면 된다.
    cloudflared 를 추가하는 작업시간은 약 5~10분정도다. (새로 학습하는데 걸리는 시간은 그보다는 길다)

단점

  • 이 구조를 이해하고 필요한 설정을 학습해야 한다.
  • cloudflared 서비스에 종속성이 생긴다. 또한 cloudflare 를 사용한적이 없다면 신규 가입을 해야한다. (하지만 25년 기준으로, 웹서비스를 하려고 한다면, Cloudflare 는 가급적 배우도록 하자. AWS 만큼이나 중요한 서비스니까.)

cloudflared 를 홈서버에 띄우는 2가지 방법

위 서비스를 써서 서비스를 제공할 수 있는 방법은 크게 2가지로 나뉜다

  1. daemon 형태로 켜기
  2. container 로 켜기 (👍추천)

TIP
컨테이너를 다룰 줄 안다면 컨테이너를 쓰길 권장드린다. 컨테이너를 모르거나 잘 안될 때만 1번을 해보라.

1번은 os daemon 으로 여러 터널을 생성하는 경우, 그 중 1개만 os service 로 등록되는 제약이 있다. 나머지 터널은 서버가 재부팅 할 경우, 매번 수동으로 열어주어야 한다. 실제 운영시에는 쓰기 어려운 특성이다.

2번은 서버가 재시작하면, 서비스별로 컨테이너가 자동으로 뜨게 설정할 수 있다. 그러면 서비스가 몇개든 충돌 없이 즉시 복구된다.

터널을 생성하는 2가지 방법

  1. 웹 Dashboard 로 생성 (👍추천)
  2. cloudflared CLI 로 생성

TIP
1번이 새로 터널을 여는 난이도가 쉽고 관리도 용이하다. 2번 방식은 수정이 필요한 경우 관리가 어렵다.

각 항목마다 사진에 붉은색 박스 혹은 화살표를 통해 어떤 부분을 봐야하는지 작성해두었으니 참고하시길.

1. 터널 생성

cloudflare zero trust 대쉬보드 > 네트워크 > tunnels > 터널생성

2. 터널 유형 선택

Cloudflared 로 선택

3. 터널 이름 지정

예시에서는 blog 로 지정

4. 터널 구성

  • 환경 선택에서 Docker를 선택
  • 제안되는 docker run 항목을 그대로 복붙
    (compose 를 쓰고있다면 그에 맞게 구성. 이는 6. docker-compose.yml 작성 파트에서 설명)
연결에 성공할 경우 Connectors 에 상태 "연결됨" 으로 확인할 수 있다.

터널에 복사된 내용을 붙이면 아래와 같이 container 이미지를 받고 바로 컨테이너로 뜨는 걸 확인할 수 있다.
(* 여기서 받은 토큰값은 절대 github에 올리면 안된다!)

여기까지는 연결성 테스트에 성공한 것
작업을 완료하면, 설정화면 하단에 커넥터 ID상태가 연결됨 으로 보인다.

5. 트래픽 라우팅 설정

다음 버튼을 누르면 <트래픽 라우팅 설정> 페이지로 온다.
예시 설정으로 설명한다.

  • 서브도메인을 blog.hamsterapp.net 으로 설정
  • 설정 이후 외부에서 https://blog.hamsterapp.net 으로 유저가 접속하면, 해당 요청은 클라우드 플레어의 터널을 통해 PC 내부로 들어와 http://localhost:8080 에 도달하게 된다. 즉 PC 내부에서 localhost:8080 으로 제공하는 서비스와 연결될 것으로 기대할 수 있다.
  • 다만, 지금은 위 4번 작업 수행시 docker run 명령을 붙여넣을 때 network 옵션을 host로 지정해야 한다. 만약 host로 지정하지 않았다면 cloudflared 는 host network 가 아닌 docker container 의 분리된 network 를 사용하므로, 이 경우localhost:8080 으로 제공하는 서비스가 있어도 연결이 안된다.

내부에서는 http://localhost:8080 으로 연결

6. docker-compose.yml 작성

기존의 docker-compose.yml 파일에, 아래의 tunnel 서비스를 추가한다. 이건 복사해서 쓰시라.

  tunnel:
    container_name: cloudflared-tunnel
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel --no-autoupdate run
    environment:
      - TUNNEL_TOKEN=<위에서 복사된 token>

아래는 frontend 라는 서비스가 이미 구성되어있던 docker-compose.yml 파일을 예시로, tunnel 서비스를 추가하면 다음과 같이 보인다.

이 경우, docker compose 의 frontend 서비스는 같은 compose 네트워크 내에서 http://frontend:80 으로 연결할 수 있다.
그러므로 같은 compose 네트워크 안에 속한 tunnel 서비스가 접근하기 위해, 앞에서 트래픽 라우팅으로 설정한 http://localhost:8080 값을 http://frontend:80로 변경해야 한다.

예시에서는 environment 에 토큰을 직접 적어넣었지만, docker compose로 운영할 땐 .env 파일을 통해 해당 값을 동적으로 주입할 수 있다. 그러면 docker-compose.yml 도 소스코드에 포함시켜 업로드해도 안전하다.

7. 터널 라우팅 수정하기

6에서 라우팅을 http://localhost:8080 에서 http://frontend:80 으로 수정하자

이후 공개호스트이름 > 메뉴 > 편집 을 통해 편집메뉴로 들어가면

cloudflare zero trust 대쉬보드 > 네트워크 > tunnels > 터널 > blog > 우측 메뉴판 > 구성 으로 들어간다

8. 최종확인하기

위에서 설정한 서브도메인에 접속하여, 내가 제공하는 서비스가 제대로 연결되는지 확인해보자.

연결이 안될 때 - 디버깅하기

제대로 연결이 되었다면 내 서비스가 보일 것이다.
연결이 안되는 경우라면 아래 2가지를 먼저 점검하자

  1. cloudflared 가 제대로 뜨긴 했지만, 내부 서비스 연결에 실패한 경우:
    내부에서 서비스를 제공하는 포트를 잘못입력하는 경우가 대부분으로 5,6,7 번 과정을 다시 보면서 내 웹서비스가 어느 포트로 서비스를 제공하고 있는지, cloudflared 가 그 포트를 바라보고 있는지 점검한다.
  2. 홈서버의 cloudflared 가 제대로 뜨지 못한 경우:
    이 경우에는 cloudflared 가 제대로 떠있는지 확인하고 조치하면 된다.

자 이제 홈서버에서 웹서비스를 안전하고 간편하게 제공하자.

중요하니까 마지막으로 다시 말하자면, 토큰은 절대로 github 등에 업로드하지 마라. .env 파일도 당연히 업로드하면 안된다.