서론

블로그에서 소개 했다시피, 저는 집에다 mini PC를 두고 서버로 이용하며 개발을 하고 있습니다. 그런데 최근 인스타에서 Mac mini + tailscale + tmux 조합이 개발 치트키라는 글을 봤어요(사실 인스타는 아니고 인스타에 뜨는 쓰레드 추천글이었는데, 저는 쓰레드 가입을 안해서 딱 저 첫문장만 보긴 했습니다 ㅎㅎ). Mac mini랑 tmux는 알겠는데 tailscale은 뭔지 궁금했습니다.
찾아보니 tailscale은 사용자가 등록한 기기들끼리 가상 네트워크를 만들어서 별도의 포트개방 없이도 ssh 접속 등을 가능하게 해주는 서비스더군요. 처음 든 생각은 ‘공유기로 포트포워딩 해서 접속하면 되는데, 굳이?’ 였습니다.
하지만 항상 문제는 보안이죠. 사실 포트포워딩으로 서버를 열어두면 로그에 정말 많은 접속시도가 찍혀있습니다. 물론 방화벽도 있고, ssh 접속 포트번호도 변경해놓지만 불안하긴 합니다. 그래서 이참에 나도 포트포워딩은 막고 tailscale을 적용해볼까 했는데, 홈서버에서 제 블로그도 서비스 중이라 바로 차단을 해버릴 순 없었어요.
하지만 이제 저는 서버가 하나가 아니죠 ㅎㅎ.. K-meme 위키를 서비스 중인 vultr 서버로 블로그를 옮기고, ssh 접속만 가능하도록 tailscale을 적용하기로 했습니다. 블로그 서버를 옮기는 일도 시행착오가 있어서 별도의 글로 남기도록 하겠습니다.

tailscale 설치 과정

적용을 미룬것이 무색하게 tailscale 설치는 정말 쉬웠습니다. 홈서버와 맥북, 아이폰, 아이패드를 다 등록하는데 몇분 걸리지도 않았어요.

서비스 가입

https://tailscale.com
tailscale은 계정 로그인을 기반으로 기기를 등록합니다. 그래서 일단 위 사이트에서 사용할 계정을 생성합니다.

아이폰 앱 설치

보통은 서버에다 프로그램 설치를 먼저 할텐데, 저는 접속기기 등록이 어떻게 이루어지는지 궁금해서 아이폰 앱을 먼저 설치했습니다. 앱 실행 후 로그인을 하면 자동으로 VPN 설정이 뜹니다. 수락하면 설정화면에 이전에는 나타나지 않던 VPN 설정버튼이 생깁니다.
아이폰설정화면 설정을 마치면 tailscale이 제공하는 tailnet이라는 가상 네트워크가 활성화되고, 내 계정에 등록된 기기 목록을 볼 수 있습니다. 목록에는 tailnet 내에서 부여된 내 기기의 IP도 볼 수 있습니다. 나중에 접속할 때에는 이 IP를 사용하는거죠.
아이패드도 동일한 방법으로 등록을 하는데, VPN 설정을 켜면 아이패드는 상단 통신 아이콘 옆에 작은 VPN 마크가 생깁니다. 아이패드아이콘

맥북에 패키지 설치

맥북에는 tailscale 홈페이지에서 제공하는 pkg 파일을 내려받아 설치합니다. 마찬가지로 설정은 자동으로 적용되고, tailscale이 실행중이면 화면 상단에 tailscale 아이콘이 표시됩니다.

우분투 서버에 설치

서버 설치는 apt같은 패키지 관리자로 설치하지 않고, curl 명령으로 설치합니니다.

curl -fsSL https://tailscale.com/install.sh | sh

설치가 끝난 후 sudo 권한으로 tailscale을 실행합니다.

sudo tailscale up

실행을 하면 인증을 위한 URL이 표시됩니다. 웹 브라우저에서 이 URL로 접속하면 로그인을 통해 방금 설치한 기기를 등록할 수 있습니다.

tailnet 기기 접속

기기를 다 등록했으니 이제 ssh 접속을 해봅니다. 접속은 등록한 기기 간에만 가능하고, 기존 사용하던 공인 IP가 아닌 tailnet IP를 사용합니다. 서버에서 다른 설정을 바꾸지 않았다면, 접속 포트는 기존에 사용하던 포트를 그대로 사용합니다.

ssh <ID>@<tailnet IP> -p <port>

인증키 만료 설정

등록된 기기들은 180일 후면 인증키가 만료돼서 새로 인증을 해야합니다. 모바일 기기들은 새로 인증하는게 어렵지 않지만, 서버의 경우 인증이 만료되면 외부에서의 접속이 막혀버리겠죠. 이를 방지하기 위해 tailscale 웹페이지 콘솔창에서 서버에 Disable key expiry를 설정할 수 있습니다. 그러면 인증 만료 없이 계속 기기등록을 유지할 수 있습니다. key-expiry-설정

포트포워딩 정책 삭제

tailnet으로 기기 접속이 잘 되는 것을 확인 했으니, 이제 공유기에 설정돼있던 포트포워딩 정책을 삭제합니다. 이제 홈서버는 저만 접속하는 순수한 개발용 서버가 됐습니다.

접속 지연시간 비교

tailscale을 이용한 접속은 인증과정을 거치기 때문에 아무래도 지연시간이 더 걸리지 않을까 하는 생각이 드는데요, 클로드는 별 차이 없을거라고 하네요.

대부분의 경우 체감 차이는 거의 없어요. 다만 어떤 경로로 연결되느냐에 따라 달라질 수 있습니다.

직접 연결(P2P)이 되는 경우
> tailscale은 기본적으로 NAT 통과(홀 펀칭)를 시도해서 두 기기가 직접 통신해요. 이때는 포트포워딩과 경로가 사실상 같아서 속도와 지연이 거의 비슷합니다. 오버헤드는 WireGuard 암호화 정도인데, 요즘 CPU에서는 무시할 수준이에요. 다만 포트포워딩 + SFTP는 SSH 암호화만 거치고, tailscale은 그 위에 WireGuard 암호화가 한 겹 더 들어가는 구조라 CPU가 약한 서버(라즈베리파이 등)에서 기가비트급 전송을 할 때는 약간 병목이 생길 수 있어요.

릴레이(DERP)를 거치는 경우
> 홀 펀칭이 실패하면 tailscale의 중계 서버를 거치게 되고, 이때는 확실히 느려집니다. 지연이 늘고 대역폭도 제한적이에요.

실제로 latency는 어떻게 나오는지 확인해보고 싶어서 tcping을 이용하여 각 네트워크별로 측정해봤습니다. local-latency 먼저 집 공유기를 통한 로컬 네트워크 접속 latency입니다. 평균 5.37 ms이네요.

port-forwarding-latency 다음은 기존에 사용하던 공유기 포트포워딩을 통한 외부 네트워크에서의 접속입니다. 평균 6.50 ms로 로컬 네트워크보다는 조금 느린것을 확인할 수 있습니다.

tailnet-latency 마지막으로 궁금했던 tailnet 접속입니다. 평균 7.98 ms로 포트포워딩보다는 latency가 조금 더 길어보입니다.
어쩌다보니 로컬<포트포워딩<tailnet 순으로 latency가 길게 나왔지만, 개별 ping latency를 보면 알 수 있듯이 그다지 신뢰할 수 있는 결과는 아닙니다. tailnet도 2 ms 대의 latency가 나올 때가 있는가 하면, 로컬 접속에서도 10 ms 이상 나오기도 합니다. 실제로 여러번 tcping 명령을 수행했을 때, 네트워크별 평균 latency가 뒤집히는 경우도 많았습니다. 위 실험으로 알 수 있었던 것은, 클로드의 답변처럼 tailnet을 이용해도 체감할 정도의 latency 차이는 발생하지 않는다 정도였습니다.

마치며

SNS는 백해무익하다지만, 이렇게 어쩌다 좋은 정보를 얻어 실행해 보는 경우도 있습니다. 이제 더이상 홈서버의 access 로그에는 모르는 사람의 IP가 찍히지 않고, 부가적으로 제 블로그도 꺼지지 않는 안정적인 서버에서 서비스 하게 되었네요. 설정도 쉽고 만족스러운 변경이었습니다. 끝!