본문 바로가기

개발/Linux & DevOps

집에 홈서버 만들어서 외부 접속 가능하게 만들기 (ft. Cloudflared, nginx)

홈서버 ㅎ

로컬 개발 환경 외부 공개 및 보안 강화 설정 가이드

1. 개요 (Overview)

이 문서는 macOS (Apple Silicon) 환경에서 실행 중인 다수의 로컬 웹

애플리케이션을 Nginx 리버스 프록시와 Cloudflare Tunnel을 사용하여 외부

인터넷에 안전하게 공개하는 방법을 기술합니다. 서버의 실제 IP를 노출하지 않고,

각 프로젝트를 고유한 서브도메인으로 접근할 수 있도록 설정하며, 기본적인 웹

공격에 대한 보안을 강화하는 것을 목표로 합니다.


2. 시스템 아키텍처 (System Architecture)

사용자의 요청은 다음의 흐름에 따라 처리됩니다.

1 외부 사용자 -> Cloudflare DNS -> Cloudflare 네트워크 (DDoS 방어, WAF) ->

 Cloudflare Tunnel -> 로컬 Nginx (8080 포트) -> 로컬 프로젝트 (300x 포트)

- Cloudflare Tunnel: 로컬 서버의 인바운드 포트를 열 필요 없이 Cloudflare

네트워크와 안전한 터널을 생성하여 트래픽을 수신합니다.

- Nginx: 로컬에서 리버스 프록시 역할을 수행하며, 요청된 서브도메인에 따라

적절한 포트에서 실행 중인 프로젝트로 트래픽을 라우팅합니다.


3. 사전 준비 (Prerequisites)

- macOS (Apple Silicon) 운영체제

- Homebrew (https://brew.sh/)) 설치

- Cloudflare에 등록된 개인 도메인


4. 설정 절차 (Setup Procedure)

1단계: 프로젝트 식별 및 포트 할당

먼저, 외부로 공개할 로컬 프로젝트와 각 프로젝트에 할당할 포트를 결정합니다.

- proj1: http://localhost:3001

- proj2: http://localhost:3002

- proj3: http://localhost:3003

- proj4: http://localhost:3004

2단계: 필수 패키지 설치

Homebrew를 사용하여 Nginx와 Cloudflare Tunnel 클라이언트(cloudflared)를

설치합니다.

   1 brew install nginx cloudflared

3단계: Nginx 리버스 프록시 설정

3.1. 설정 디렉토리 생성

Nginx가 추가 설정을 로드할 디렉토리를 생성합니다. (이미 존재할 수 있음)

   1 sudo mkdir -p /opt/homebrew/etc/nginx/servers/

3.2. Nginx 설정 파일 생성

각 서브도메인을 로컬 프로젝트 포트로 전달하고 보안 헤더를 추가하는 설정

파일을 작성합니다. 아래 내용을 projects.conf 파일로 저장합니다.

    1 \# /opt/homebrew/etc/nginx/servers/projects.conf
    2 
    3 server {
    4     listen 8080;
    5     server\_name proj1.01079991731.work;
    6 
    7     location / {
    8         proxy\_pass http://localhost:3001;
    9         proxy\_set\_header Host $host;
   10         proxy\_set\_header X-Real-IP $remote\_addr;
   11         proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
   12         proxy\_set\_header X-Forwarded-Proto $scheme;
   13         proxy\_http\_version 1.1;
   14         proxy\_set\_header Upgrade $http\_upgrade;
   15         proxy\_set\_header Connection "upgrade";
   16 
   17         \# Security Headers
   18         add\_header X\-Frame-Options "SAMEORIGIN" always;
   19         add\_header X\-Content\-Type-Options "nosniff" always;
   20         add\_header Strict-Transport-Security "max-age\=31536000; 
      includeSubDomains" always;
   21     }
   22 }
   23 
   24 server {
   25     listen 8080;
   26     server\_name proj2.01079991731.work;
   27 
   28     location / {
   29         proxy\_pass http://localhost:3002;
   30         \# ... (proxy\_set\_header 및 add\_header 내용은 위와 동일)
   31     }
   32 }
   33 
   34 server {
   35     listen 8080;
   36     server\_name proj3.01079991731.work;
   37 
   38     location / {
   39         proxy\_pass http://localhost:3003;
   40         \# ... (proxy\_set\_header 및 add\_header 내용은 위와 동일)
   41     }
   42 }
   43 
   44 server {
   45     listen 8080;
   46     server\_name proj4.01079991731.work;
   47 
   48     location / {
   49         proxy\_pass http://localhost:3004;
   50         \# ... (proxy\_set\_header 및 add\_header 내용은 위와 동일)
   51     }
   52 }

 

3.3. Nginx 서비스 재시작

새 설정을 적용하기 위해 Nginx를 재시작합니다.

   1 brew services restart nginx

4단계: Cloudflare Tunnel 설정

4.1. Cloudflare 인증

아래 명령을 실행하고, 열리는 브라우저 창에서 Cloudflare 계정에 로그인하여

인증을 완료합니다.

   1 cloudflared tunnel login

4.2. 터널 생성

터널을 식별할 이름(예: my-dev-tunnel)으로 새로운 터널을 생성합니다.

   1 cloudflared tunnel create my-dev-tunnel

이 명령은 터널의 UUID와 크리덴셜 파일 경로(~/.cloudflared/.json)를

출력합니다.

4.3. 터널 구성 파일 작성

~/.cloudflared/config.yml 파일을 생성하고 아래 내용을 작성합니다. tunnel:과

credentials-file:의 UUID는 이전 단계에서 출력된 값으로 대체해야 합니다.

    1 # ~/.cloudflared/config.yml
    2 tunnel: 123123123123123123123
    3 credentials-file: 
      /Users/user/.cloudflared/12312312312312123.json
    4 
    5 ingress:
    6   \- hostname: proj1.01079991731.work
    7     service: http://localhost:8080
    8   \- hostname: proj2.01079991731.work
    9     service: http://localhost:8080
   10   \- hostname: proj3.01079991731.work
   11     service: http://localhost:8080
   12   \- hostname: proj4.01079991731.work
   13     service: http://localhost:8080
   14   \- service: http\_status:404 \# 일치하는 호스트가 없는 경우 404 반환

4.4. Cloudflare DNS 설정

Cloudflare 대시보드에서 도메인의 DNS 레코드로 이동하여, 터널을 가리키는 CNAME

레코드를 추가합니다. 와일드카드(*)를 사용하면 모든 서브도메인을 한 번에

처리할 수 있습니다.

- Type: CNAME

- Name: *

- Content: 123123123123123.cfargotunnel.com (터널 생성 시 얻은 UUID)

- Proxy status: Proxied (주황색 구름 활성화)

4.5. Cloudflare Tunnel 실행

터미널 세션이 종료되어도 프로세스가 유지되도록 nohup을 사용하여 터널을

백그라운드에서 실행합니다.

1 nohup cloudflared tunnel run my-dev-tunnel > /dev/null 2>&1 &

5단계: 로컬 애플리케이션 실행

각 프로젝트를 백그라운드에서 지속적으로 실행합니다.

    1 # proj1
    2 cd /Users/jsy/dev/proj1
    3 npm install
    4 nohup npm run dev -- -p 3001 > /dev/null 2>&1 &
    5 
    6 # proj2
    7 cd /Users/jsy/dev/proj2
    8 npm install
    9 nohup npm run dev -- -p 3002 > /dev/null 2>&1 &
   10
   11 # proj3
   12 cd /Users/jsy/dev/proj3
   13 npm install
   14 nohup npm run dev -- -p 3003 > /dev/null 2>&1 &
   15 
   16 # proj4
   17 cd /Users/jsy/dev/proj4
   18 npm install
   19 nohup npm run dev -- -p 3004 > /dev/null 2>&1 &

5. 보안 강화 (Security Hardening)

Nginx 보안 헤더 (적용 완료)

- X-Frame-Options "SAMEORIGIN": 클릭재킹 공격 방지.

- X-Content-Type-Options "nosniff": MIME 타입 스니핑 방지.

- Strict-Transport-Security: 모든 연결을 HTTPS로 강제.

Cloudflare 보안 기능

- DDoS 방어: Cloudflare의 글로벌 네트워크를 통해 기본적으로 활성화됩니다.

- IP 마스킹: Cloudflare Tunnel을 사용하여 실제 서버 IP가 외부에 노출되지 않습니다.

- WAF (Web Application Firewall): 애플리케이션 취약점 공격 방어.

1. Cloudflare 대시보드 -> Security -> WAF -> Managed rules 탭으로이동합니다.

2. Cloudflare Managed RulesetOWASP Core Ruleset을 활성화("On")합니다.
(플랜에 따라 일부 제한될 수 있습니다.)

6. 관리 및 유지보수

- Nginx 재시작: brew services restart nginx

- Nginx 에러 로그: tail -f /opt/homebrew/var/log/nginx/error.log

- 실행 중인 터널 및 프로젝트 확인: ps aux | grep 'cloudflared\|node'

- 특정 포트 사용 프로세스 확인: lsof -i :<포트번호>

- 프로세스 종료: kill 또는 pkill <프로세스이름>

반응형