이 글의 목차

Tailscale Funnel은 MagicDNS와 HTTPS 인증서를 켜고 정책 파일에 funnel 노드 속성을 둔 뒤, 서버에서 tailscale funnel --bg 3000을 실행하면 됩니다. 그러면 로컬 3000번 서비스가 https://<기기이름>.<tailnet이름>.ts.net으로 인터넷에 공개됩니다. 공유기 포트포워딩도, 공인 IP도, 인증서 발급 작업도 필요 없습니다.

Tailscale은 원래 내 기기끼리만 연결하는 메시 VPN입니다. Funnel은 그중 한 서비스를 Tailscale을 설치하지 않은 사람에게도 열어 주는 기능입니다. 이 글은 이미 서버에 Tailscale을 설치하고 로그인까지 마친 분을 대상으로 합니다. 설치와 기본 개념은 Tailscale 메시 VPN 입문 글을 먼저 보세요. 명령과 옵션은 2026년 10월 기준 Tailscale 문서와 클라이언트 v1.104 소스로 확인했습니다.

한눈에 보는 Tailscale Funnel 조건

항목내용
필요 조건MagicDNS 켜기, HTTPS 인증서 켜기, 정책 파일의 funnel 노드 속성
최소 버전v1.38.3 이상이 필요하지만, 현재 CLI 문법은 v1.52부터 쓰였으므로 최신 버전을 권장
공개 주소https://<기기이름>.<tailnet이름>.ts.net (커스텀 도메인 불가)
공개 가능한 포트443, 8443, 10000 세 개뿐
프로토콜TLS로 암호화된 연결만 가능 (HTTPS, TLS 종료 TCP 등)
대역폭따로 설정할 수 없는 한도가 있으며 수치는 공개되지 않음
요금제공식 문서상 모든 플랜에서 사용 가능, 상태는 베타

Serve와 Funnel은 무엇이 다른가요

둘은 같은 설정 체계를 공유합니다. 차이는 누가 접속할 수 있느냐입니다.

구분tailscale servetailscale funnel
접속 가능한 사람내 tailnet에 연결된 기기만인터넷의 누구나
접속하는 쪽 준비물Tailscale 앱 필요브라우저만 있으면 됨
정책 요구사항HTTPS 인증서HTTPS 인증서 + funnel 노드 속성
대표 용도가족만 쓰는 대시보드, NAS 관리 화면웹훅 수신, 데모, 외부 공유 페이지

한 포트를 Serve와 Funnel에 동시에 쓸 수는 없습니다. 같은 포트에 마지막으로 실행한 명령이 공개 여부를 정합니다. 즉 serve로 띄운 443을 funnel로 다시 실행하면 그 순간 인터넷에 공개됩니다. 반대로 하면 다시 tailnet 전용이 됩니다.

1단계: MagicDNS와 HTTPS 인증서 켜기

  1. 관리 콘솔의 DNS 페이지로 이동합니다.
  2. MagicDNS가 꺼져 있으면 켭니다.
  3. HTTPS Certificates 항목에서 Enable HTTPS를 누르고 공개 기록 안내에 동의합니다.

tailnet 이름(tail1234.ts.net 같은 부분)은 DNS 페이지에서 바꿀 수 있습니다. 다만 원하는 문자열을 직접 입력하는 방식은 아닙니다. 무작위로 생성된 후보 가운데 하나를 고릅니다.

2단계: 정책 파일에 funnel 노드 속성 추가

Funnel을 쓸 수 있는 사람이나 기기는 tailnet 정책 파일의 nodeAttrs로 정해집니다. 서버에서 처음 tailscale funnel을 실행하면 승인 페이지 링크가 나옵니다. 그 페이지에서 승인하면 Tailscale이 HTTPS 인증서 설정과 아래 속성 추가를 자동으로 처리합니다. 직접 넣고 싶다면 관리 콘솔 Access controls 페이지에서 Add Funnel to policy를 누르거나 아래 블록을 추가하세요.

"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"]
}
]

autogroup:member는 tailnet의 모든 멤버라는 뜻입니다. 혼자 쓰는 tailnet이면 이 기본값으로 충분합니다. 가족이나 동료가 함께 있다면 공개 권한을 좁히는 편이 안전합니다. 정책 파일에 이미 nodeAttrs가 있으면 배열 안에 항목만 추가합니다.

{
"groups": {
"group:can-funnel": ["you@example.com"]
},
"nodeAttrs": [
{
"target": ["group:can-funnel"],
"attr": ["funnel"]
}
]
}

3단계: tailscale funnel 명령으로 서비스 공개

서버에서 로컬 3000번 포트의 웹 앱을 공개하는 가장 기본 형태입니다.

Terminal window
# 포그라운드 실행: 터미널을 닫거나 Ctrl+C를 누르면 공개가 끝남
sudo tailscale funnel 3000
# 백그라운드 실행: 재부팅이나 tailscale down/up 이후에도 유지됨
sudo tailscale funnel --bg 3000

실행하면 공개 URL과 / proxy http://127.0.0.1:3000 같은 라우팅 정보가 출력됩니다. 기본 포트는 HTTPS 443이므로 주소는 https://homeserver.tail1234.ts.net처럼 포트 번호 없이 나옵니다. 상시 운영할 서비스라면 꼭 --bg를 붙이세요. --bg 없이 띄운 Funnel은 명령을 종료하거나 터미널을 닫는 순간 꺼지고, 재부팅 후에도 남지 않습니다.

자주 쓰는 옵션과 대상 형식

하고 싶은 일명령
8443 포트로 두 번째 서비스 공개 (예: Jellyfin 8096)tailscale funnel --bg --https=8443 8096
하위 경로로 공개tailscale funnel --bg --set-path=/app 3000
자체 서명 HTTPS 백엔드tailscale funnel --bg https+insecure://localhost:8443
파일이나 디렉터리 공개tailscale funnel --bg /srv/share (절대 경로)
간단한 텍스트 응답tailscale funnel --bg text:"Hello, world!"
확인 프롬프트 생략--yes 추가
  • 공개 포트(--https, --tcp, --tls-terminated-tcp의 값)는 443, 8443, 10000 중 하나여야 합니다. 로컬 서비스 포트(3000, 8096 등)는 제한이 없습니다.
  • 대상은 3000처럼 포트 번호만 쓰면 127.0.0.1:3000으로 해석됩니다. 공식 문서는 리버스 프록시 대상으로 로컬호스트를 기준으로 설명합니다. 최신 CLI는 다른 IP도 받지만 macOS 앱 버전 등 일부 환경에서는 경고를 냅니다. 같은 기기의 서비스를 localhost로 가리키는 방식이 가장 확실합니다.
  • --set-path는 앱이 하위 경로(base URL)를 지원할 때만 쓰세요. 지원하지 않는 앱은 CSS와 JS 경로가 깨집니다. 그럴 때는 서비스마다 포트를 따로 쓰는 편이 낫습니다.
  • 파일과 디렉터리 공개는 macOS의 App Store·Standalone 버전에서는 샌드박스 제약으로 안 됩니다. 리눅스 서버에서는 문제없습니다.

상태 확인과 끄기

Terminal window
# 현재 Serve/Funnel 설정 확인
tailscale funnel status
tailscale funnel status --json
# 특정 Funnel만 끄기: 켤 때 쓴 플래그를 똑같이 붙이고 끝에 off
sudo tailscale funnel --https=443 off
sudo tailscale funnel --https=8443 off
sudo tailscale funnel --https=443 --set-path=/app off
# 전부 초기화 (Serve 설정까지 모두 지워짐)
sudo tailscale funnel reset

reset은 Funnel만이 아니라 같은 기기의 Serve 설정까지 빈 상태로 되돌립니다. tailnet 전용으로 띄워 둔 서비스가 있다면 off로 하나씩 끄세요.

Docker로 Funnel 쓰기: TS_SERVE_CONFIG

서버 호스트에 Tailscale을 설치하지 않고 컨테이너마다 독립된 tailnet 기기를 두고 싶다면 사이드카 방식을 씁니다. Tailscale 컨테이너가 네트워크를 맡고, 앱 컨테이너는 network_mode: service:로 그 네트워크를 공유합니다. Funnel 설정은 TS_SERVE_CONFIG가 가리키는 JSON 파일로 넣습니다. 아래는 Tailscale 공식 예제 저장소(tailscale-dev/docker-guide-code-examples)의 구조를 따른 정적 사이트 예시입니다.

compose.yaml
services:
ts-site:
image: tailscale/tailscale:latest
container_name: ts-site
hostname: site # 공개 주소가 site.<tailnet>.ts.net 이 됨
environment:
- TS_AUTHKEY=tskey-auth-xxxxx
- TS_STATE_DIR=/var/lib/tailscale
- TS_SERVE_CONFIG=/config/serve.json
- TS_USERSPACE=false
volumes:
- ./ts-state:/var/lib/tailscale
- ./ts-config:/config # 파일이 아니라 디렉터리로 마운트
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
restart: unless-stopped
site:
image: nginx:alpine
network_mode: service:ts-site
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- ts-site
restart: unless-stopped
{
"TCP": {
"443": {
"HTTPS": true
}
},
"Web": {
"${TS_CERT_DOMAIN}:443": {
"Handlers": {
"/": {
"Proxy": "http://127.0.0.1:80"
}
}
}
},
"AllowFunnel": {
"${TS_CERT_DOMAIN}:443": true
}
}

위 JSON을 ./ts-config/serve.json으로 저장합니다. ${TS_CERT_DOMAIN}은 Compose 변수가 아닙니다. 컨테이너 안의 containerboot가 파일을 읽을 때 그 기기의 실제 ts.net 이름으로 바꿉니다. AllowFunnel을 false로 두거나 이 블록을 빼면 tailnet 전용 Serve가 됩니다. JSON을 손으로 쓰기 어렵다면 일반 서버에서 CLI로 원하는 구성을 만든 뒤 tailscale serve status --json 출력을 가져다 쓰면 됩니다.

Funnel vs Cloudflare Tunnel vs 포트포워딩

항목Tailscale FunnelCloudflare Tunnel포트포워딩
공유기 설정불필요불필요필요
CGNAT·이중 NAT 환경동작동작사실상 불가
도메인*.ts.net 고정내 도메인 (Cloudflare DNS)내 도메인 또는 DDNS
공개 포트443, 8443, 10000호스트 이름 단위자유
TLS 종료 위치내 서버 (릴레이는 복호화 불가)Cloudflare 엣지내 리버스 프록시
앞단 인증직접 구성Cloudflare Access 연동 가능직접 구성
트래픽 제약공개되지 않은 대역폭 한도약관, 무료 플랜 업로드 크기 제한회선 속도
잘 맞는 용도웹훅, 데모, 소규모 공유상시 운영하는 공개 웹 서비스스트리밍, 게임 서버

Funnel의 장점은 준비가 거의 없다는 점입니다. 도메인을 사지 않아도 되고, 이미 Tailscale을 쓰고 있다면 명령 한 줄이면 끝납니다. 트래픽은 Tailscale의 Funnel 릴레이 서버를 거치지만 TLS는 내 서버에서 종료됩니다. 그래서 릴레이가 내용을 볼 수 없습니다. 반면 도메인을 고를 수 없고, 대역폭 한도가 있으며, WAF 같은 엣지 보호도 없습니다. 내 도메인으로 상시 서비스를 운영할 계획이라면 Cloudflare Tunnel 가이드가 더 맞습니다. 세 방식과 VPN·SSH 터널까지 함께 비교하려면 원격 접속 방식 비교 글을 참고하세요. 지금 포트포워딩이 막혀서 Funnel을 찾았다면 CGNAT·이중 NAT 점검 글로 원인부터 확인해 보는 것도 방법입니다.

공개하기 전 보안 점검

Funnel URL은 추측하기 어려운 비밀 주소가 아닙니다. 기기 이름과 tailnet 이름은 CT 로그에 공개되므로 누군가 스캔해서 찾아올 수 있다고 보고 설정하세요.

  • 관리 화면은 Funnel로 열지 마세요. Portainer, Nginx Proxy Manager의 관리 포트(81), 공유기·NAS 관리 페이지, Home Assistant 관리 화면 등은 serve로 tailnet 안에서만 쓰는 것이 원칙입니다.
  • 로그인이 없는 앱 앞에는 인증을 두세요. 앱 자체 로그인이 없다면 Basic Auth를 건 리버스 프록시나 인증 프록시를 거쳐 공개합니다. 리버스 프록시 구성은 Nginx Proxy Manager 가이드를 참고하세요.
  • 공개 범위를 경로 단위로 줄이세요. API의 웹훅 엔드포인트만 필요하다면 --set-path로 해당 경로만 Funnel에 올립니다.
  • 쓰지 않으면 끄세요. 임시 공유가 끝나면 tailscale funnel status로 확인하고 off로 닫습니다.
  • 클라이언트를 최신으로 유지하세요. 2026년 10월 28일 배포된 v1.104.4에는 Serve 관련 보안 수정 두 건이 들어갔습니다.

Funnel이 안 될 때 점검 순서

증상원인과 조치
Funnel not available; HTTPS must be enabled.DNS 페이지에서 HTTPS 인증서를 켜지 않았습니다. 1단계를 진행하세요.
Funnel not available; "funnel" node attribute not set.정책 파일에 funnel 속성이 없거나 target에 이 기기·사용자가 포함되지 않았습니다. 2단계를 확인하세요.
port 3000 is not allowed for funnel...공개 포트를 3000으로 지정했습니다. --https=443(기본값), 8443, 10000 중 하나를 쓰세요.
설정 직후 외부에서 주소가 안 열림공개 DNS 레코드 반영에 최대 10분 정도 걸립니다. 사용자 보고상 그보다 오래 걸린 사례도 있으니 조금 기다리세요.
내 폰에서는 열리는데 외부 사람은 못 엶tailnet에 연결된 기기는 MagicDNS로 내부 경로를 탈 수 있습니다. 시험할 때는 Tailscale을 끈 휴대폰 LTE 망에서 여세요.
첫 접속이 느리거나 인증서 오류인증서 발급과 반영에 시간이 걸릴 수 있습니다. 짧은 시간에 여러 번 재발급하면 Let’s Encrypt 발급 제한에 걸려 최대 34시간을 기다려야 할 수 있으니 기기 이름이나 tailnet 이름을 반복해서 바꾸지 마세요.
502 오류나 연결 거부백엔드가 127.0.0.1에서 듣고 있지 않습니다. Docker는 -p 3000:3000처럼 호스트에 포트를 게시했는지, 사이드카라면 network_mode를 공유하는지 확인하세요.
설정은 정상인데 외부 접속만 TLS 단계에서 끊김2026년 8월 v1.102.1에서 이 증상의 회귀가 보고됐고, v1.102.2에서 수정됐습니다. tailscale version으로 확인하고 최신으로 올리세요.

자주 묻는 질문

Tailscale Funnel은 무료로 쓸 수 있나요?

공식 문서에 따르면 Funnel은 모든 플랜에서 쓸 수 있으므로 무료 Personal 플랜에서도 됩니다. 다만 아직 베타 기능이고, 트래픽에는 수치가 공개되지 않은 대역폭 한도가 있습니다. 개인 홈서버의 데모나 웹훅, 소규모 공유 용도라면 문제가 될 일은 적습니다.

Tailscale Funnel에 내 도메인을 연결할 수 있나요?

안 됩니다. 2026년 10월 기준 문서는 Funnel이 tailnet 도메인(tailnet-name.ts.net) 안의 이름만 쓸 수 있다고 명시합니다. blog.example.com 같은 내 도메인으로 공개하려면 Cloudflare Tunnel이나 포트포워딩과 리버스 프록시 조합을 써야 합니다.

Tailscale Funnel로 Jellyfin을 외부에 공개해도 되나요?

기술적으로는 tailscale funnel --bg --https=8443 8096으로 공개할 수 있습니다. Jellyfin에는 자체 로그인도 있습니다. 하지만 Funnel에는 대역폭 한도가 있어 고화질 스트리밍에는 맞지 않습니다. 가족만 보는 용도라면 각 기기에 Tailscale을 설치하고 tailnet 안에서 접속하는 편이 빠르고 안전합니다. 미디어 서버 선택은 Plex·Jellyfin·Emby 비교를 참고하세요.

Tailscale Funnel을 완전히 끄려면 어떻게 하나요?

켤 때 쓴 플래그 그대로 끝에 off를 붙입니다. 예를 들어 sudo tailscale funnel --https=443 off입니다. 모든 Funnel과 Serve 설정을 한 번에 지우려면 sudo tailscale funnel reset을 씁니다. 특정 사용자나 기기가 다시 켜지 못하게 하려면 정책 파일의 nodeAttrs에서 funnel 속성을 빼면 됩니다.

참고 자료와 확인 범위

2026년 10월 31일 자료 확인. 명령과 오류 메시지는 Tailscale 클라이언트 v1.104.4 소스 기준입니다. Funnel은 베타 기능이라 허용 포트와 정책 형식, 대역폭 한도가 바뀔 수 있으니 적용 전에 공식 문서를 다시 확인하세요.

함께 보면 좋은 글

← 전체 글로 돌아가기