Tailscale 실전 가이드: 설치·SSH·Subnet Router·Exit Node·접근 제어
집이나 회사 밖에서 서버, NAS, PC, 스마트폰에 접속하려면 흔히 공유기 포트포워딩, 고정 공인 IP, 동적 DNS, 방화벽 규칙부터 떠올린다. 하지만 관리 화면과 SSH 포트를 인터넷에 직접 노출하면 공격 표면이 넓어지고, 장소가 바뀔 때마다 네트워크 설정을 다시 손봐야 한다.
Tailscale은 이런 장치에 전용 클라이언트를 설치하고 같은 계정으로 인증해, 인터넷 위에 암호화된 사설 메시 네트워크를 만든다. 가능한 경우 장치끼리 직접 연결하고, 직접 연결이 어려울 때만 암호화된 패킷을 릴레이한다. 이 글에서는 원리뿐 아니라 Linux 설치, 자동 업데이트, SSH, Docker, Subnet Router, Exit Node, 접근 제어와 장애 점검까지 서버 운영자의 관점에서 정리한다.
세 줄 요약
- Tailscale은 WireGuard를 기반으로 사용자와 장치의 신원을 결합한 사설 메시 네트워크를 만든다.
- 일반적인 원격 관리에는 공인 IP, 포트포워딩, 별도 VPN 게이트웨이가 필요하지 않으며 트래픽은 가능한 한 장치 사이를 직접 흐른다.
- 설치만으로 끝내지 말고 Grants·ACL, 장치 승인, 키 만료, 자동 업데이트, 공개 포트 정리까지 함께 설계해야 안전하다.
이 글의 지원 운영체제, 요금제, 베타 기능과 최소 버전 정보는 2026년 8월 26일 Tailscale 공식 문서를 기준으로 확인했다. 실제 적용 전에는 링크한 공식 문서에서 변경 사항을 다시 확인한다.
이 글에서 바로 찾기
- 5분 만에 연결 확인하기
- Tailscale의 구조와 연결 원리
- Subnet Router·Exit Node·Serve·Funnel
- SSH와 관리자 화면 보호
- Grants·장치 신뢰·Docker 운영
- 장애 점검과 자주 묻는 질문
먼저 5분 만에 연결 확인하기
Linux 장치 두 대가 있다면 한 대씩 다음 명령을 실행한다.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip
tailscale status
표시된 인증 URL에서 같은 tailnet으로 로그인한다. 그런 다음 한 장치에서 다른 장치의 MagicDNS 이름으로 연결을 확인한다.
tailscale ping server-name
ssh ubuntu@server-name
server-name과 ubuntu는 실제 장치 이름과 사용자로 바꾼다. macOS, Windows, iOS와 Android는 각 공식 앱을 설치해 같은 방식으로 로그인하면 된다. 여기까지 동작하면 기본 사설 연결은 완성된 것이다. 공개 SSH를 닫거나 라우팅 기능을 켜는 작업은 복구 경로와 접근 정책을 먼저 준비한 뒤 진행한다.
Tailscale은 정확히 무엇인가
Tailscale을 한 문장으로 표현하면 WireGuard 기반의 신원 중심 사설 오버레이 네트워크다. 같은 Tailscale 네트워크에 속한 노트북, 스마트폰, 클라우드 서버, NAS는 물리적으로 서로 다른 통신사와 공유기 뒤에 있어도 하나의 사설망에 있는 것처럼 통신할 수 있다.
이 사설 네트워크를 Tailscale에서는 tailnet이라고 부른다. tailnet은 단순한 IP 대역이 아니다. 어떤 사용자와 장치가 참여하는지, 서로 어떤 서비스와 포트에 접근할 수 있는지, 어떤 장치가 내부망이나 인터넷의 게이트웨이가 될지까지 포함하는 논리적 보안 경계다.
WireGuard만 직접 구성하는 것과 무엇이 다른가
WireGuard 자체는 빠르고 단순한 암호화 터널을 제공하지만, 여러 장치를 운영하려면 공개키 교환, 피어 목록, IP 할당, 방화벽, NAT 통과와 키 교체를 직접 관리해야 한다.
Tailscale은 WireGuard 데이터 통신 위에 다음 운영 기능을 더한다.
- Google, GitHub, Microsoft 또는 OIDC 호환 공급자를 이용한 사용자 인증
- 장치 등록과 공개키 배포
- NAT traversal과 동적 피어 검색
- 장치별 Tailscale IPv4·IPv6 주소
- 장치 이름으로 접속하는 MagicDNS
- 사용자·그룹·장치 역할에 따른 Grants·ACL
- 직접 연결 실패 시 Peer Relay 또는 DERP 대체 경로
- Subnet Router, Exit Node, Tailscale SSH, Serve와 Funnel
즉, Tailscale은 단순히 WireGuard 설치를 자동화한 앱이라기보다 WireGuard의 암호화된 데이터 평면과 신원·정책·연결 조정 기능을 결합한 플랫폼에 가깝다.
전통적인 VPN과 가장 큰 차이
전통적인 원격 접속 VPN은 대개 중앙 VPN 서버를 거친다. 사용자는 먼저 VPN 게이트웨이에 접속하고, 그 게이트웨이를 통해 내부 서버로 들어간다. 구조가 명확한 대신 모든 트래픽이 한곳에 모여 병목과 단일 장애 지점이 되기 쉽다.
Tailscale은 기본적으로 메시 구조다. 서울의 노트북과 클라우드 서버가 직접 통신할 수 있으면 두 장치 사이에 WireGuard 터널을 만들고, 중앙 조정 서비스는 실제 사용자 트래픽을 운반하지 않는다. 필요할 때는 Exit Node를 선택해 전통적인 전체 터널 VPN처럼 인터넷 트래픽까지 한 장치를 거치게 할 수 있다.
또 하나의 차이는 기본 동작이 분할 터널이라는 점이다. Tailscale을 켰다고 모든 웹 트래픽이 Tailscale로 이동하는 것은 아니다. 일반 인터넷 트래픽은 기존 네트워크를 사용하고, tailnet 주소와 승인된 서브넷 경로만 Tailscale을 지난다. 모든 인터넷 트래픽을 보내려면 Exit Node를 명시적으로 선택해야 한다.
연결이 만들어지는 과정: 직접 연결, Peer Relay, DERP
Tailscale 장치 사이의 연결은 보통 다음 순서로 결정된다.
- 각 장치는 조정 서비스에서 접근 가능한 피어와 연결 후보 정보를 받는다.
- UDP 기반 NAT traversal을 사용해 장치끼리 직접 연결을 시도한다.
- 직접 연결되면 암호화된 트래픽은 두 장치 사이를 곧바로 이동한다.
- 직접 연결이 안 되고 tailnet에 Peer Relay가 구성되어 있으면 해당 릴레이를 시도한다.
- Peer Relay도 사용할 수 없으면 Tailscale의 DERP 서버를 통해 패킷을 중계한다.
- 중계 중에도 더 좋은 직접 경로가 생겼는지 계속 확인한다.
DERP는 Designated Encrypted Relay for Packets의 약자다. 이름 그대로 이미 암호화된 패킷을 전달한다. 장치의 개인키는 로컬 장치를 떠나지 않으므로 DERP 서버는 패킷 내용을 복호화할 수 없다.
따라서 relay 연결이라고 보안이 약해지는 것은 아니다. 주된 차이는 성능이다. 직접 연결보다 지연 시간이 늘거나 처리량이 낮아질 수 있다. 반대로 “Tailscale을 쓰면 모든 트래픽이 Tailscale 회사 서버를 거친다”는 설명도 정확하지 않다.
제어 평면과 데이터 평면
Tailscale 구조를 이해하려면 두 영역을 구분해야 한다.
제어 평면
Tailscale 조정 서비스가 담당한다.
- 장치 등록, 제거와 인증 상태
- 사용자 신원과 접근 정책
- 장치 공개키, Tailscale IP와 DNS 설정 배포
- 피어 검색과 NAT 통과용 엔드포인트 교환
- Subnet Router와 Exit Node 경로 배포
- 적절한 DERP 리전 선택
사용자 비밀번호를 Tailscale이 직접 보관해 인증하는 구조는 아니다. 사용자가 선택한 신원 공급자가 인증하고, Tailscale은 그 신원을 tailnet 정책과 장치에 연결한다.
데이터 평면
각 장치의 Tailscale 클라이언트가 담당한다.
- WireGuard 터널 수립
- 패킷 암호화와 복호화
- 정책에 따른 패킷 필터링
- 직접 연결과 중계 경로 전환
- 실제 사용자 데이터 전송
조정 서비스가 일시적으로 중단되어도 이미 성립한 연결과 캐시된 정책은 계속 동작할 수 있다. 다만 새 연결 수립, 키 변경, 새 정책 수신은 서비스가 정상화될 때까지 제한될 수 있다.
Tailscale의 주요 구성 요소
MagicDNS
MagicDNS는 tailnet 장치를 자동으로 DNS에 등록한다. 숫자로 된 100.x.y.z 주소 대신 server-name 같은 장치 이름을 사용할 수 있다.
ssh ubuntu@server-name
전체 이름은 일반적으로 장치명.tailnet-이름.ts.net 형태다. 짧은 이름이 충돌하거나 다른 DNS 검색 도메인과 섞이는 환경에서는 전체 이름으로 먼저 확인하는 편이 좋다.
Subnet Router
Subnet Router는 Tailscale을 설치할 수 없는 기존 장치가 있는 사설망으로 가는 경로를 제공한다. 예를 들어 집의 한 Linux 장치가 192.168.10.0/24를 광고하면, 외부 노트북에서 그 장치를 게이트웨이로 사용해 프린터, NAS, 카메라에 접근할 수 있다.
sudo tailscale set --advertise-routes=192.168.10.0/24
경로 광고만으로 끝나지 않는다. 관리자 콘솔에서 경로를 승인하고, Grants·ACL에서 해당 서브넷 접근을 허용해야 한다. Linux에서는 IP forwarding을 활성화하되, 그 전에 호스트 방화벽의 forwarding 기본 정책이 거부 상태인지 확인한다.
Android, iOS, macOS, tvOS와 Windows 클라이언트는 승인된 서브넷 경로를 자동 수락한다. Linux 클라이언트는 다음 설정을 별도로 적용해야 한다.
sudo tailscale set --accept-routes
경로 승인은 “이 장치를 라우터로 신뢰한다”는 뜻이고, Grants·ACL은 “누가 그 경로를 사용할 수 있는가”를 정한다. 둘은 별개다. 편하다는 이유로 /16처럼 넓은 대역을 광고하지 말고 실제 필요한 최소 CIDR만 지정한다. 기본 SNAT를 끄고 원본 클라이언트 IP를 보존하려면 내부망의 반환 경로도 별도로 구성해야 한다.
Exit Node
Exit Node는 tailnet 장치의 일반 인터넷 트래픽까지 특정 장치를 거치게 한다. 카페 Wi-Fi에서 집 서버를 Exit Node로 선택하면 외부 사이트에는 집 서버의 공인 IP에서 접속한 것처럼 보인다.
Subnet Router가 특정 내부 대역으로 가는 길을 제공한다면, Exit Node는 기본 인터넷 경로를 제공한다. Exit Node는 장치가 기능을 광고하고, 관리자가 승인하고, 클라이언트가 사용을 선택해야 동작한다.
sudo tailscale set --advertise-exit-node
사용자 정의 접근 정책을 적용했다면 Exit Node 사용을 허용할 사용자나 그룹에서 autogroup:internet으로 가는 별도 Grant도 필요하다. Exit Node 장치의 태그나 주소를 목적지로 허용하는 규칙은 SSH처럼 그 장치 자체에 접속할 권한만 주며, 인터넷 게이트웨이 사용 권한을 대신하지 않는다.
Exit Node 사용 중에는 기본적으로 현재 장소의 LAN 접근이 제한될 수 있다. 프린터나 공유기 관리 화면도 함께 써야 한다면 클라이언트의 Allow LAN access 옵션을 확인한다.
Exit Node 운영자는 일반 인터넷 게이트웨이처럼 접속 목적지와 같은 메타데이터, 그리고 암호화되지 않은 애플리케이션 트래픽을 볼 수 있다. HTTPS의 암호화된 본문까지 자동으로 해독하는 것은 아니지만, 반드시 신뢰할 수 있는 장치만 Exit Node로 선택한다.
Tailscale Serve와 Funnel
두 기능은 이름이 비슷하지만 공개 범위가 완전히 다르다.
- Serve는 로컬 서비스를 tailnet 안에서만 공유한다.
- Funnel은 로컬 서비스를 Tailscale을 사용하지 않는 사람까지 접속할 수 있도록 인터넷에 공개한다.
관리자 페이지, 데이터베이스, Portainer, NAS 관리 화면에는 기본적으로 Serve 또는 사설 tailnet 접근을 사용한다. Funnel은 공개가 목적일 때만 사용해야 한다. Funnel을 켜는 순간 “Tailscale 안에서만 보이는 서비스”가 아니므로 애플리케이션 인증, 업데이트, 속도 제한과 로그 점검이 별도로 필요하다.
같은 포트에 Serve와 Funnel을 동시에 적용할 수 없으며 마지막 명령이 공개 상태를 바꿀 수 있다. 배포 전후에 tailscale serve status와 tailscale funnel status를 모두 확인한다. Serve가 백엔드에 전달하는 신원 헤더를 인증에 활용한다면 백엔드는 localhost에만 바인딩해야 한다. 백엔드 포트를 0.0.0.0이나 LAN에 함께 열어 두면 공격자가 헤더를 위조해 Tailscale 경계를 우회할 수 있다.
또한 *.ts.net 인증서에 사용한 장치 이름은 Certificate Transparency 공개 로그에 남을 수 있다. 고객명, 프로젝트 암호명처럼 민감한 정보를 호스트 이름에 넣지 않는다. Serve·Funnel 명령 문법은 클라이언트 1.52에서 변경됐으므로 오래된 블로그의 명령을 그대로 복사하기보다 현재 공식 문서를 확인한다.
2026년 8월 기준 요금제
개인·가정의 비상업적 용도를 위한 Personal 플랜은 공식 가격표에서 월 0달러로 제공된다.
- 최대 6명
- 사용자 소유 장치 수 무제한
- ACL 그룹 최대 3개
- 태그 기반 리소스 50개 포함
- ephemeral 리소스 월 1,000분
회사나 상업 서비스는 Personal 플랜의 대상이 아니다. Standard와 Premium의 사용자당 가격, 포함 기능과 제한은 바뀔 수 있으므로 실제 도입 전에는 Tailscale 공식 가격표를 다시 확인해야 한다.
운영체제별 설치
Linux
Ubuntu, Debian, RHEL 계열, Fedora, Raspberry Pi OS, Amazon Linux, openSUSE, SUSE, Oracle Linux 등 주요 배포판은 공식 설치 스크립트를 사용할 수 있다.
curl -fsSL https://tailscale.com/install.sh | sh
설치 스크립트를 셸에 바로 전달하는 방식이 정책에 맞지 않는 환경이라면, 공식 패키지 저장소 페이지에서 배포판별 저장소와 서명 키를 직접 구성한다.
설치 후 장치를 tailnet에 연결한다.
sudo tailscale up
터미널에 표시된 인증 URL을 열어 로그인한 뒤 주소와 상태를 확인한다.
tailscale ip
tailscale status
systemctl status tailscaled --no-pager
macOS
2026년 8월 기준 현재 클라이언트는 macOS 12 Monterey 이상을 요구한다. Tailscale은 공식 패키지 서버의 Standalone 버전을 권장하며 Mac App Store 버전도 제공한다. 두 변형의 시스템 확장, 업데이트 방식과 기능 차이가 있으므로 한 장치에서 여러 변형을 섞어 설치하지 않는 것이 좋다.
Windows
현재 Windows 10 이상 또는 Windows Server 2016 이상에서 공식 .exe와 MSI 설치 방식을 제공한다. 설치 후 시스템 트레이의 Tailscale 아이콘에서 로그인한다. 조직 배포는 MSI와 MDM 정책을 함께 검토한다.
iPhone·iPad·Android
iOS·iPadOS는 iOS 15 이상, Android는 Android 8 이상이 현재 지원 기준이다. 앱 설치 후 운영체제의 VPN 구성 추가를 허용하고 같은 tailnet으로 로그인한다. 모바일 상단에 VPN 표시가 나타나더라도 Exit Node를 선택하지 않았다면 일반 인터넷 트래픽 전체가 Tailscale을 통과하는 것은 아니다.
Linux도 자동 업데이트할 수 있다
과거 정보와 달리 현재 Linux도 Tailscale 자체 자동 업데이트를 지원한다. 다만 “설치했으니 무조건 자동”이라고 가정하면 안 된다.
현재 설정을 확인한다.
tailscale get auto-update
자동 업데이트를 활성화한다.
sudo tailscale set --auto-update
다시 끄려면 다음과 같이 실행한다.
sudo tailscale set --auto-update=false
자동 업데이트는 처음 설치할 때 사용한 방식을 활용한다. Linux 패키지 관리자로 설치했다면 해당 패키지 관리자가 업데이트에 사용된다.
운영 시 다음 조건을 함께 알아둬야 한다.
- 새로 만든 tailnet은 새 장치 자동 업데이트가 기본 활성화된다.
- 2024년 2월 이전에 만든 tailnet은 관리자 콘솔과 기존 장치 각각에서 활성화해야 할 수 있다.
- 관리자 콘솔의 설정 변경은 기존 장치에 소급 적용되지 않는다.
- Arch Linux 기반 배포판은 현재 Tailscale 자체 자동 업데이트를 지원하지 않는다.
- 새 버전 공개 즉시 모든 장치가 업데이트되지 않는다. 보통 안정성 확인 후 약 일주일에 걸쳐 순차 적용될 수 있다.
- 원하는 시각으로 자동 업데이트 일정을 지정하는 기능은 현재 지원하지 않는다.
- iOS, Android, macOS App Store 버전은 각 앱 스토어의 자동 업데이트 설정도 확인해야 한다.
서버 원격 접속을 안전하게 구성하는 방법
1. 먼저 일반 SSH를 Tailscale 위에서 사용한다
가장 단순한 방법은 기존 OpenSSH를 유지하고 접속 대상만 공인 IP에서 Tailscale IP 또는 MagicDNS 이름으로 바꾸는 것이다.
ssh ubuntu@server-name
기존 SSH 키, sshd_config, 감사 로그와 사용자 정의 포트를 그대로 유지할 수 있다. 특히 여러 사용자나 강제 명령, 세밀한 authorized_keys 정책을 쓰는 서버에는 이 방식이 이해하기 쉽다.
공개 SSH 포트를 닫을 때는 순서가 중요하다.
- Tailscale 연결 상태와 서버 이름을 확인한다.
- 방화벽에서
tailscale0인터페이스의 SSH만 허용한다. - 기존 세션을 유지한 채 새 터미널에서 Tailscale 경로로 로그인한다.
- 재부팅 후에도
tailscaled와 SSH가 정상인지 확인한다. - 마지막으로 클라우드 보안 목록과 호스트 방화벽의 공개 SSH 허용을 제거한다.
테스트 전에 공개 SSH를 먼저 닫으면 원격 서버에서 잠길 수 있다. 클라우드 콘솔 같은 복구 경로도 미리 확인한다.
2. 필요하면 Tailscale SSH를 사용한다
Tailscale SSH는 WireGuard 네트워크 연결뿐 아니라 SSH 인증과 권한도 tailnet 정책으로 관리한다.
sudo tailscale set --ssh
대상 장치에서 기능을 켜는 것만으로 끝나지 않는다. 네트워크 접근 규칙과 SSH 규칙이 모두 허용되어야 하며, Tailscale SSH는 현재 포트 22를 전제로 한다. 사용자 정의 SSH 포트를 유지하거나 authorized_keys의 명령 제한을 적극 사용하는 환경은 일반 SSH over Tailscale이 더 적합할 수 있다.
3. 관리자 화면은 인터넷이 아니라 tailnet에 둔다
Portainer, Nginx Proxy Manager, 데이터베이스 관리 도구, 모니터링 대시보드의 포트를 0.0.0.0으로 공개해 두고 로그인 화면만 믿는 것은 좋지 않다.
가능하면 다음 중 하나로 줄인다.
- 애플리케이션을 로컬 또는 Tailscale 주소에만 바인딩
- 호스트 방화벽에서
tailscale0을 통한 접근만 허용 - Tailscale Serve를 사용해 tailnet 내부 HTTPS로 제공
- Grants·ACL로 관리자 사용자와 관리 장치만 허용
Tailscale은 애플리케이션 취약점을 패치해 주지 않는다. 사설망 안의 서비스라도 업데이트, 강한 로그인, 2단계 인증과 백업은 계속 필요하다.
Grants·ACL로 최소 권한 적용하기
새 tailnet의 기본 정책은 장치 간 통신을 폭넓게 허용한다. 설치 직후 두 장치가 바로 연결되는 이유다. 개인 장치 몇 대를 넘어서 서버, 가족, 팀원이 섞이면 접근 정책을 별도로 작성해야 한다.
Tailscale은 기존 ACL을 계속 지원하지만, 새 정책에는 더 확장된 Grants 구문을 권장한다. 아래 예시는 구성원이 tag:server 장치의 SSH 포트에만 접근하도록 제한하는 개념 예시다.
{
"tagOwners": {
"tag:server": ["autogroup:admin"]
},
"grants": [
{
"src": ["autogroup:member"],
"dst": ["tag:server"],
"ip": ["tcp:22"]
}
]
}
실제 적용 전에는 현재 사용자, 장치 소유권, 필요한 포트와 복구 경로에 맞게 바꿔야 한다.
src는 연결을 시작할 사용자나 장치다.dst는 접근 대상이다.ip는 허용할 프로토콜과 포트다.- 규칙은 방향성이 있으므로 반대 방향도 자동 허용되지 않는다.
- 정책은 각 대상 장치에서 로컬로 집행된다.
정책 파일에 접근 제어 구간이 없으면 기본 전체 허용 정책이 적용될 수 있다. 반대로 정책을 잘못 바꾸면 관리자 자신도 서버에 접근하지 못할 수 있다. 기존 관리 세션을 유지하고 정책 테스트를 작성한 뒤 단계적으로 좁힌다.
태그는 사람의 노트북이나 스마트폰보다 서버, Subnet Router, Exit Node 같은 비인간 워크로드에 적합하다. 장치에 태그를 적용하면 사용자 신원 대신 태그 신원으로 동작한다. 여러 태그를 붙였을 때 권한은 교집합이 아니라 합집합이므로, tag:prod와 tag:db를 함께 붙여 “운영 DB만”을 뜻하게 만들면 예상보다 권한이 넓어질 수 있다. 교집합 의미가 필요하면 tag:prod-db처럼 목적이 분명한 복합 태그를 만든다.
Grants는 tailnet을 통과하는 트래픽을 통제한다. 같은 LAN, 공인 IP, Docker의 게시 포트처럼 Tailscale 바깥 경로로 들어오는 트래픽을 호스트 방화벽처럼 차단하지는 않는다.
장치 신뢰와 키를 관리하는 방법
신원 공급자부터 보호한다
Tailscale 로그인 계정이 침해되면 새 장치 등록과 관리 콘솔 접근으로 이어질 수 있다. Google, GitHub, Microsoft 등 실제 로그인에 사용하는 계정에 2단계 인증을 적용하고 복구 수단을 점검한다.
장치 승인
장치 승인을 활성화하면 새 장치가 로그인에 성공해도 관리자가 승인하기 전에는 tailnet 트래픽을 주고받지 못한다. 개인 tailnet에서도 계정 탈취에 대한 방어층을 하나 더 만들 수 있다.
키 만료
일반 장치의 노드 키는 기본적으로 180일 뒤 만료되며 1~180일 범위에서 설정할 수 있다. 주기적으로 재인증하도록 만료를 유지하는 편이 안전하다. 원격 서버, Subnet Router, Exit Node처럼 사람이 즉시 재인증하기 어려운 장치는 키 만료를 끌 수 있지만, 보안과 가용성의 교환이다. 태그로 인증한 장치는 키 만료가 기본 비활성화될 수 있으므로 관리 콘솔에서 따로 확인한다.
tailscale up --force-reauth는 재인증 과정에서 현재 Tailscale 연결을 끊을 수 있다. 유일한 Tailscale SSH·RDP 세션 안에서 실행하지 말고 클라우드 콘솔이나 별도 관리 경로를 먼저 확보한다. 인증 키가 만료되거나 폐기돼도 이미 등록된 노드가 자동 삭제되는 것은 아니므로, 사용을 끝낸 노드는 관리 콘솔에서 별도로 제거한다.
키 만료를 끈 장치는 다음 조건을 더 엄격히 지킨다.
- 태그와 Grants로 접근 대상을 최소화한다.
- 디스크와 운영체제를 보호하고 자동 보안 업데이트를 적용한다.
- 폐기·분실·재설치 시 즉시 장치를 제거하거나 키를 취소한다.
- Subnet Router와 Exit Node는 가능하면 이중화한다.
Tailnet Lock
Tailnet Lock은 신뢰된 서명 장치가 새 노드의 공개키를 서명해야 tailnet 참여를 허용한다. 침해된 제어 평면이 미서명 노드를 tailnet에 끼워 넣는 공격을 막는 고급 기능이다. 반면 연결 차단이나 악성 정책 배포 같은 가용성 공격, endpoint·서명 장치·신원 공급자 탈취까지 막지는 않는다. 2026년 8월 기준 Personal·Enterprise 플랜, 클라이언트 1.46.1 이상에서 제공되며 서명 장치를 최소 두 대 준비해야 한다.
강력한 대신 운영 책임도 커진다. 여러 서명 장치, 복구용 disablement secret의 안전한 보관, 새 장치 서명 절차가 필요하다. 복구 비밀을 잃고 지원용 비밀도 제공하지 않았다면 tailnet을 복구하지 못할 수 있다. 또한 Tailnet Lock과 장치 승인은 동시에 사용할 수 없다. 작은 개인 환경이라면 장치 승인과 최소 권한 정책부터 적용하고, 복구 절차를 실제로 운영할 수 있을 때 Tailnet Lock을 검토한다.
Docker에서 사용할 때
Tailscale 공식 컨테이너를 사이드카 또는 게이트웨이로 사용할 수 있다. 다음은 Tailscale 컨테이너와 웹 앱이 같은 네트워크 namespace를 공유해, 앱의 80번 포트를 tailnet 안에서만 제공하는 사이드카 예시다.
services:
tailscale:
image: tailscale/tailscale:stable
hostname: private-web
environment:
TS_AUTHKEY: ${TS_AUTHKEY}
TS_STATE_DIR: /var/lib/tailscale
TS_USERSPACE: "false"
TS_EXTRA_ARGS: --advertise-tags=tag:server
volumes:
- tailscale-state:/var/lib/tailscale
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- NET_RAW
restart: unless-stopped
app:
image: nginx:alpine
network_mode: service:tailscale
depends_on:
- tailscale
restart: unless-stopped
volumes:
tailscale-state:
app 서비스에 ports:를 두지 않았다는 점이 중요하다. 이 구성에서 Nginx는 Tailscale 컨테이너와 네트워크를 공유하므로 private-web:80으로 접근할 수 있지만 호스트의 공인 인터페이스에는 포트를 게시하지 않는다. 실제 애플리케이션 이미지와 내부 포트에 맞게 바꾸고 Grants로 접근 대상을 제한한다.
운영 환경에서는 다음을 지킨다.
- 인증 키를 Compose 파일이나 Git 저장소에 직접 적지 않는다.
- 태그 소유자와 권한을 먼저 정의하고 최소 권한의 인증 키를 발급한다.
- 상태 디렉터리를 영속 볼륨에 저장한다.
- Tailscale 전용 앱이라면 호스트의
ports:를 불필요하게 게시하지 않는다. 게시 포트는 tailnet 정책을 우회하는 별도 경로가 된다. - 컨테이너 내부 자동 업데이트보다
stable이미지를 새로 받아 재배포한다. stable태그를 적었다고 실행 중인 이미지가 자동 교체되는 것은 아니다. 계획된pull과 재배포가 필요하다.- Tailscale 컨테이너에 불필요한 호스트 네트워크나 과도한 capability를 추가하지 않는다.
공식 컨테이너는 기본적으로 userspace 네트워킹을 사용할 수 있어 TUN 장치와 추가 capability 없이도 실행할 수 있다. 위 예시처럼 TS_USERSPACE=false, /dev/net/tun, NET_ADMIN·NET_RAW를 주는 kernel 네트워킹은 라우팅이나 성능상 필요한 경우에만 선택한다.
컨테이너 내부에서 tailscale set --auto-update를 켜도 재시작 후 설정이 유지되지 않을 수 있다. 공식 권장 방식은 불변 컨테이너 원칙에 맞춰 새 안정 이미지를 받아 재배포하는 것이다. 특히 TS_STATE_DIR를 영속화하지 않으면 재시작할 때마다 새 노드가 등록돼 관리 콘솔에 오래된 노드가 쌓일 수 있다.
로깅과 프라이버시에서 알아둘 점
각 Tailscale agent는 기본적으로 장애 진단과 운영을 위한 로그를 log.tailscale.com으로 스트리밍한다. 장치 이름, 운영체제, IP, 클라이언트 버전, 연결 시각과 연결 통계 같은 메타데이터는 포함될 수 있지만, WireGuard로 종단간 암호화된 트래픽의 본문을 Tailscale이 읽는다는 뜻은 아니다.
장치별 --no-logs-no-support 또는 컨테이너의 TS_NO_LOGS_NO_SUPPORT=true로 전송을 거부할 수 있다. 대신 진단 정보가 없어져 해당 장치에 대한 공식 지원이 제한될 수 있다.
관리 설정 변경을 기록하는 configuration audit log와 실제 네트워크 흐름을 기록하는 network flow log도 구분해야 한다. 후자는 별도 기능이며 페이로드를 저장하지 않는다. 진단 로그를 완전히 끄는 옵션도 있지만 공식 지원에 필요한 정보가 사라지는 대가가 있으므로 조직의 개인정보·감사 정책과 함께 판단한다.
방화벽과 포트포워딩에 대한 오해
Tailscale은 일반적으로 기존 NAT와 방화벽 뒤에서 추가 포트포워딩 없이 동작한다. 직접 연결이 어렵다면 DERP로 연결을 유지한다.
UDP 포트를 열거나 UPnP·NAT-PMP를 허용하면 직접 연결 성능이 나아질 수 있지만, 보안 경계도 바뀐다. 단지 relay로 보인다는 이유만으로 공유기와 클라우드 방화벽을 넓게 열어서는 안 된다. 먼저 실제 성능 문제가 있는지 측정하고, 필요한 트래픽만 제한적으로 허용한다.
서버 운영의 목적이 관리 포트를 숨기는 것이라면 다음 원칙이 더 중요하다.
- 웹 서비스에 필요한 80·443만 공개한다.
- SSH와 관리자 UI는 Tailscale 경로로 제한한다.
- 데이터베이스와 Docker 관리 포트는 인터넷에 게시하지 않는다.
- 클라우드 보안 목록과 호스트 방화벽을 함께 확인한다.
- Tailscale 정책과 호스트 방화벽을 서로 대체재로 보지 않는다.
문제 해결 순서
1. 서비스와 로그인 상태
systemctl status tailscaled --no-pager
tailscale version
tailscale status
tailscale ip
장치가 offline, stopped, needs login 상태인지 먼저 확인한다. 키가 만료됐다면 재인증이 필요할 수 있다.
2. 대상까지 Tailscale 경로 확인
tailscale ping server-name
일반 ping보다 먼저 tailscale ping을 사용하면 MagicDNS 이름, 피어 발견과 Tailscale 경로를 함께 확인하기 쉽다. 결과가 direct인지 relay인지도 살펴본다.
3. NAT와 DERP 상태
tailscale netcheck
UDP 사용 가능 여부, 가까운 DERP 리전과 지연 시간을 확인한다. relay라고 해서 곧바로 장애는 아니다. 실제 SSH, 파일 전송, 웹 응답 속도가 요구 수준을 충족하는지도 같이 본다.
4. Linux 인터페이스와 로그
ip addr show tailscale0
journalctl -u tailscaled --since="1 hour ago" --no-pager
로그를 외부에 공유할 때는 Tailscale IP, 장치 이름, 사용자 계정, 인증 URL, 키와 내부 대역을 먼저 가린다.
현재 발생 중인 문제는 tailscale debug daemon-logs로 실시간 로그를 확인할 수 있다. 재현 직후 tailscale bugreport를 실행해 생성된 ID를 기록하면 공식 지원에 사건 시점을 전달하기 쉽다. 실시간 로그 명령은 과거 로그를 복구하는 기능이 아니므로 Linux에서는 journalctl도 함께 확인한다.
5. MagicDNS가 안 될 때
IP로는 접속되는데 이름만 안 된다면 다음을 확인한다.
- 관리자 콘솔에서 MagicDNS가 활성화됐는지
- 장치 이름이 중복되거나 바뀌지 않았는지
- 전체
장치명.tailnet-이름.ts.net이름은 동작하는지 - 다른 VPN, 보안 프로그램 또는 로컬 DNS 설정이 충돌하는지
- macOS에서 시스템 DNS 경로를 우회하는 일부 도구만 실패하는 것은 아닌지
6. Subnet Router가 안 될 때
- 라우터 장치의 IP forwarding이 활성화됐는지
- 올바른 CIDR을 광고했는지
- 관리자 콘솔에서 경로를 승인했는지
- Grants·ACL이 해당 서브넷을 허용하는지
- 목적지 장치의 방화벽과 반환 경로가 올바른지
- 서로 겹치는 사설 IP 대역을 사용하고 있지 않은지
7. Exit Node 사용 후 로컬 장치가 안 보일 때
Exit Node 클라이언트의 Allow LAN access를 확인한다. 회사·카페·집이 같은 사설 대역을 쓰면 경로 충돌도 점검한다.
자주 묻는 질문
Tailscale을 켜면 인터넷 속도가 모두 느려지나
기본 분할 터널에서는 일반 인터넷 트래픽이 기존 경로를 사용한다. tailnet 통신만 Tailscale로 이동한다. Exit Node를 선택한 경우에는 인터넷 트래픽이 Exit Node를 거치므로 해당 장치의 회선, CPU, 거리와 중계 여부가 성능에 영향을 준다.
DERP로 연결되면 위험한가
DERP는 WireGuard로 암호화된 패킷을 중계하며 개인키를 갖지 않는다. 보안 수준보다 지연 시간과 처리량 차이를 먼저 고려한다.
공인 IP가 없어도 사용할 수 있나
대부분의 가정용 NAT, 이동통신망, 클라우드 환경에서 사용할 수 있다. 직접 연결이 되지 않으면 릴레이 경로를 사용하므로 CGNAT 환경에서도 유용하다.
포트포워딩을 전부 지워도 되나
Tailscale을 통해서만 사용할 SSH와 관리자 UI는 대체할 수 있다. 그러나 공개 웹사이트의 80·443, 메일 수신처럼 인터넷에서 누구나 접근해야 하는 서비스까지 자동으로 대체하는 것은 아니다. 서비스별 공개 대상부터 분류해야 한다.
Tailscale만 설치하면 서버가 안전해지나
아니다. Tailscale은 네트워크 접근 경로와 신원을 강화한다. 운영체제 패치, 애플리케이션 취약점, 약한 비밀번호, 잘못된 컨테이너 권한, 백업 부재까지 해결해 주지는 않는다.
Headscale을 쓰면 더 좋은가
Headscale은 자체 제어 평면을 운영하려는 선택지지만 별도 프로젝트이며, 직접 가용성·업데이트·백업·기능 차이를 책임져야 한다. 개인키가 장치에 남고 데이터가 종단간 암호화된다는 이유만으로 모든 사용자가 제어 평면까지 직접 운영할 필요는 없다. 데이터 주권 요구와 운영 역량을 함께 비교한다.
운영 전 최종 체크리스트
- [ ] 로그인에 사용하는 신원 공급자에 2단계 인증을 적용했다.
- [ ] 장치 이름을 역할이 드러나게 정리하고 MagicDNS를 확인했다.
- [ ] 새 tailnet의 기본 전체 허용 상태를 그대로 방치하지 않았다.
- [ ] 새 정책은 Grants를 우선 검토하고 필요한 포트만 허용했다.
- [ ] 서버와 공유 인프라에는 사용자 소유권 대신 적절한 태그를 사용했다.
- [ ] 장치 승인 또는 Tailnet Lock 중 운영 가능한 방식을 선택했다.
- [ ] 키 만료를 끈 장치의 폐기·분실 대응 절차가 있다.
- [ ] Linux 장치의 자동 업데이트 상태를 개별 확인했다.
- [ ] Docker는 상태 볼륨과 인증 키 비밀 관리를 적용했다.
- [ ] SSH와 관리자 UI의 Tailscale 경로를 먼저 테스트했다.
- [ ] 테스트 후 불필요한 공개 포트와 클라우드 방화벽 규칙을 정리했다.
- [ ] Subnet Router와 Exit Node의 경로·승인·접근 정책을 함께 확인했다.
- [ ] Funnel로 공개한 서비스와 tailnet 전용 Serve를 구분했다.
- [ ] 장애 시 콘솔 접속이나 다른 관리 경로로 복구할 수 있다.
마무리
Tailscale의 가장 큰 장점은 “VPN 설정을 간단하게 만든다”는 데서 끝나지 않는다. 장치마다 공인 IP와 포트포워딩을 관리하는 구조를, 신원과 정책을 중심으로 한 암호화된 메시 네트워크로 바꾼다는 데 의미가 있다.
특히 여러 클라우드 서버, 집의 NAS, Mac·Windows PC와 스마트폰을 함께 관리한다면 효과가 크다. 공개 웹서비스는 80·443으로 유지하되 SSH, Portainer, 데이터베이스와 관리자 화면은 tailnet 안으로 옮기면 외부 공격 표면을 크게 줄일 수 있다.
다만 편리함이 기본 보안을 대신하지는 않는다. 로그인 계정의 2단계 인증, Grants·ACL의 최소 권한, 장치 승인, 키 수명, 자동 업데이트, 불필요한 공개 포트 제거까지 함께 적용해야 Tailscale의 장점을 제대로 얻을 수 있다.
함께 읽으면 좋은 글
- 서버 보안 점검 1편: 외부 노출 포트와 방화벽 상태 확인
- 서버 보안 점검 3편: SSH 비밀번호 차단과 root 로그인 정책
- 서버 보안 점검 4편: Portainer·Agent·Docker 관리면
참고한 공식 문서
- What is Tailscale?
- Control and data planes
- Connection types
- DERP servers
- MagicDNS
- Install Tailscale on Linux
- Update Tailscale
- Manage permissions using ACLs
- Manage permissions using Grants
- Tags
- Device approval
- Key expiry
- Tailnet Lock
- Subnet routers
- Exit nodes
- Tailscale SSH
- Tailscale Serve
- Tailscale Funnel
- Logging
- Security best practices
- Troubleshooting
- Tailscale pricing