Turnout이 Mac에서 하는 일
Turnout은 root 권한으로 실행되는 서비스를 설치합니다. 그래서 이 서비스가 하는 일과 그것을 확인하는 방법을 정확히 설명합니다. 서비스가 무엇인지, 무엇을 변경하는지, 무엇을 보관하는지, 어디에 연결하는지를 각각 사용자의 Mac에서 직접 확인하는 방법과 함께 소개합니다.
두 부분: 앱과 백그라운드 서비스
앱인 Turnout.app은 특별한 권한 없이 사용자 계정으로 실행됩니다. 앱은 터널을 표시하고, 구성을 편집하고, 백그라운드 서비스에 터널의 연결과 연결 해제를 요청합니다. 네트워크 트래픽에는 전혀 관여하지 않습니다.
백그라운드 서비스는 root 권한으로 실행되는 LaunchDaemon인 cc.ctsite.turnout.daemon입니다. 그 프로그램인 turnout-daemon은 앱 안의 /Applications/에 있습니다. Turnout은 macOS의 로그인 항목(SMAppService)을 통해 서비스를 등록하므로, macOS가 ‘시스템 설정’ › ‘일반’ › ‘로그인 항목 및 확장 프로그램’에서 서비스를 허용할지 묻고, 그곳에서 서비스를 끌 수도 있습니다.
서비스는 각 터널의 utun 인터페이스를 만들고, 서비스에 내장된 GotaTun으로 사용자 공간에서 WireGuard를 실행합니다. GotaTun은 Mullvad가 MPL-2.0 라이선스로 공개한 구현입니다. 서비스를 거치는 것은 터널의 패킷뿐이며, 나머지 트래픽은 평소처럼 macOS가 라우팅합니다. 터널은 서비스 안에서 동작하므로 앱을 닫아도 계속 연결되어 있습니다.
변경하는 항목과 사용하는 도구
주소, MTU, 경로, DNS는 wg-quick이 macOS에서 사용하는 프로그램으로 변경합니다. 각 프로그램은 셸을 거치지 않고 인수와 함께 직접 실행됩니다.
/sbin/ifconfig- 터널 인터페이스의 주소와 MTU 설정, 인터페이스 활성화.
/sbin/route- 터널로 들어가는 경로, 서버 주소를 물리 네트워크에 유지하는 경로, 터널을 우회하는 경로.
/usr/sbin/networksetup- 네트워크 서비스의 DNS 서버와 검색 도메인.
따라서 평소에 쓰는 명령으로 서비스가 한 일을 정확히 볼 수 있습니다.
netstat -rn
networksetup -listallnetworkservices
networksetup -getdnsservers Wi-Fi # 또는 목록에 있는 다른 서비스
터널의 연결이 해제되면 서비스는 자신이 추가한 경로를 제거하고 자신이 바꾼 DNS 설정을 원래대로 되돌립니다.
구성
터널은 root가 소유한 폴더인 /Library/Application Support/cc.ctsite.turnout/tunnels에 터널마다 파일 하나씩, 개인 키를 포함해 모드 0600으로 저장됩니다. 이 폴더에 쓰는 것은 서비스뿐이며, 앱은 서비스에 저장을 요청합니다.
sudo ls -l "/Library/Application Support/cc.ctsite.turnout/tunnels"
훅
PreUp, PostUp, PreDown, PostDown은 /bin/bash -c를 통해 root 권한으로 실행되며, %i는 터널의 utun 인터페이스로, %I는 터널 이름으로 바뀝니다. 이는 sudo와 같은 수준의 권한이므로 다음과 같이 다룹니다.
- 훅은 항상 디스크에 있는 구성 파일에서만 가져오며, 앱이 서비스에 보내는 내용에서는 절대 가져오지 않습니다.
- 훅이 새로 추가되었거나 변경된 구성을 저장하려면 관리자 승인이 필요합니다. 서비스는 macOS Authorization Services로 그 승인을 직접 확인하며, 앱의 말을 그대로 믿지 않습니다.
- 훅을 건드리지 않는 편집에는 새로운 승인이 필요하지 않습니다.
sudo로 실행하는 스크립트를 대할 때처럼, 승인하기 전에 구성의 훅을 읽어 보십시오.
서비스가 응답하는 대상
앱은 Unix 소켓 /var/run/을 통해 서비스와 통신합니다. 서비스는 연결하는 모든 프로그램의 코드 서명을 확인하고, 같은 개발자 팀이 Turnout의 번들 식별자 cc.ctsite.turnout으로 서명한 프로그램에만 응답합니다. 다른 프로그램은 거부됩니다.
충돌 후
서비스가 멈추면 macOS가 터널 인터페이스를 제거하고, 그 인터페이스에 있던 경로도 함께 사라집니다. 그러나 물리 게이트웨이를 거치는 경로와 DNS 설정은 사라지지 않으며, 이렇게 설정된 DNS는 재시동 후에도 유지됩니다. 그래서 서비스는 모든 변경을 하기 전에 저널에 기록하고, 다음에 시작할 때 이전 실행이 남긴 것을 모두 되돌립니다. 이 작업이 끝날 때까지는 어떤 터널도 연결하지 않으며, Turnout은 아직 남아 있는 항목을 ‘지금 복원’ 버튼과 함께 보여 줍니다.
Turnout › ‘네트워크 설정 복구…’를 선택하면 언제든지 같은 작업을 합니다. 서비스가 실행 중이 아니면 관리자 암호를 요청한 다음 직접 저널을 재생합니다.
네트워크 연결
업데이트를 위해 앱 자체는 두 곳에 연결합니다. 새 버전이 있는지 확인하기 위해 GitHub에, 설치 수를 집계하기 위해 Google Analytics에 연결합니다. 라이선스를 위해서는 라이선스를 구입한 후 Polar에, 그리고 사용자의 iCloud 계정에 연결합니다. 언제, 무엇을 보내는지는 아래의 라이선스에 나와 있습니다.
/Applications에 있는 사본만 메뉴나 윈도우를 열 때 최대 1시간에 한 번 스스로 확인합니다. Turnout › ‘업데이트 확인…’을 선택하면 언제든지 확인합니다.- 확인할 때는 GitHub에 있는 이 프로젝트의 최신 릴리스에서 작은 파일 하나를 요청합니다. 이 요청에는 계정 정보도, 사용자나 사용자의 터널에 관한 정보도 담기지 않습니다. GitHub는 요청과 사용자의 IP 주소를 볼 수 있습니다.
- 확인할 때마다 앱은 Google Analytics(
www.google-analytics.com, Measurement Protocol 사용)에 이벤트 하나를 보냅니다. 이 이벤트에는 Turnout이 처음 사용될 때 만들어 환경설정에 보관하는 무작위 설치 ID(하드웨어에서 만든 값이 아님), Turnout 버전과 빌드, macOS 버전, 프로세서 아키텍처, 시스템 언어, 그리고 Google Analytics가 집계에 필요로 하는 두 필드인 Turnout 시작 시각에서 가져온 세션 번호와 고정된 참여 시간이 담깁니다. 터널, 서버, 키, 네트워크에 관한 정보는 없으며, 계정이나 사용자 ID도 없습니다. Google은 Google 개인정보처리방침에 따라 요청과 사용자의 IP 주소를 볼 수 있습니다. - ‘일반’(Turnout › ‘설정…’)에서 ‘자동으로 업데이트 확인’을 끄면 자동 확인과 보고서가 모두 중단됩니다. ‘업데이트 확인…’은 선택하면 여전히 확인하지만 보고서는 보내지 않습니다.
- 업데이트를 설치하면 설치 프로그램은 같은 릴리스에서 받으며, Turnout은 macOS 설치 프로그램에 넘기기 전에 설치 프로그램의 체크섬과 Developer ID 서명을 확인합니다.
터널은 구성에 지정된 서버에 연결되며, 훅은 사용자가 작성한 대로 동작합니다. 그 밖에는 앱도 서비스도 어디에도 연결하지 않습니다. 자체 충돌 보고도, 광고도, 계정도 없습니다.
라이선스
Turnout은 각 Mac에서 7일 체험 기간 동안 모든 기능을 사용할 수 있으며, 원하면 1회에 한해 7일을 더 사용할 수 있습니다. 그 후에는 터널을 연결하려면 라이선스가 필요합니다. 라이선스가 필요한 것은 연결뿐입니다. 연결된 터널은 계속 연결된 상태로 유지되며, 연결 해제, 편집, 가져오기, 내보내기, ‘네트워크 설정 복구…’, 제거는 언제든지 할 수 있습니다. 라이선스 때문에 연결이 해제되는 일은 결코 없습니다.
라이선스는 앱에서만 처리됩니다. 백그라운드 서비스는 라이선스에 관해 아무것도 모르며, Polar나 iCloud에 절대 연결하지 않습니다.
- 체험 기간에는 라이선스를 확인하지 않습니다. 체험 기간의 날짜는 이 Mac의 키체인에 있는
cc.ctsite.turnout.license항목에 보관됩니다. 이 항목은 Turnout을 제거해도 남으므로, 다시 설치해도 체험 기간이 새로 시작되지 않습니다. - 구입한 후에는 앱이 다음과 같은 경우에 Polar의 라이선스 서비스
api.polar.sh를 호출합니다. 이 Mac을 활성화할 때(키, Mac에 지정하는 이름, 모델 식별자, macOS 및 Turnout 버전, 하드웨어 식별자의 단방향 해시), 약 1주일에 한 번 메뉴나 윈도우를 열 때와 ‘지금 확인’을 선택할 때마다(키, 이 Mac의 활성화 ID, 해시), 그리고 Mac을 제거할 때(키와 해당 Mac의 활성화 ID)입니다. 계정은 없으며, 터널에 관한 정보도 보내지 않습니다. - Polar에 연결할 수 없어도 달라지는 것은 없습니다. 라이선스가 있는 Mac은 오프라인 상태가 아무리 오래 지속되어도 계속 연결할 수 있으며, ‘라이선스’ 패널에는 라이선스를 마지막으로 확인한 시점만 표시됩니다.
- 키와 그 키를 사용하는 Mac 목록은 사용자 iCloud 계정의 Turnout 전용 영역(CloudKit)에 레코드로 보관되므로, 같은 계정에 로그인한 다른 Mac이 라이선스를 찾아 클릭 한 번으로 사용할 수 있습니다. 앱은 시작할 때와 메뉴나 윈도우를 열 때 이 레코드를 읽으며, 활성화, 확인 또는 제거 후에만 레코드를 씁니다. 레코드는 Apple의 표준 iCloud 보호 방식으로 저장되며 종단 간 암호화되지 않습니다. iCloud에 로그인되어 있지 않은 Mac은 아무것도 동기화하지 않으므로, 그런 Mac에서는 키를 직접 입력하십시오.
전송되는 모든 정보와 그 수신자는 개인정보 처리방침에 나와 있으며, 약관은 라이선스 약관에서 볼 수 있습니다.
위치 및 Wi-Fi 규칙
Wi-Fi 규칙(#@ OnWiFi)에는 Mac이 연결된 네트워크의 이름이 필요합니다. macOS는 이 이름을 위치 정보로 취급하므로, 위치 접근 권한이 있는 앱만 이 이름을 읽을 수 있습니다. Turnout은 실행할 때가 아니라 Wi-Fi 규칙을 설정할 때 접근 권한을 요청하며, 이 권한은 네트워크 이름을 읽는 데만 사용하고 사용자가 있는 위치를 알아내는 데는 절대 사용하지 않습니다. 사용자가 나열한 이름은 Mac에 있는 구성 파일에 남습니다. 접근 권한이 없으면 Wi-Fi 규칙은 아무 동작도 하지 않습니다.
로그
/Library/Logs/cc.ctsite.turnout.daemon.log - 백그라운드 서비스가 한 작업과 오류.
/Library/Logs/cc.ctsite.turnout.update.log - 업데이트를 설치할 때 기록됩니다.
‘도움말’ › ‘Finder에서 로그 보기’를 선택하면 두 파일을 볼 수 있습니다. 앱 자체의 메시지는 시스템 로그에 있습니다.
/usr/bin/log show --predicate 'subsystem == "cc.ctsite.turnout"' --last 1h
zsh에서는 그냥 log라고 입력하면 다른 내장 명령이 실행되므로 전체 경로를 입력해야 합니다.
직접 확인하기
launchctl print system/cc.ctsite.turnout.daemon # launchd가 보는 서비스
ls -l /Applications/Turnout.app/Contents/MacOS/ # Turnout과 turnout-daemon
cat /Applications/Turnout.app/Contents/Resources/uninstall.sh
defaults read cc.ctsite.turnout analyticsClientID # 무작위 설치 ID
netstat -rn
networksetup -getdnsservers Wi-Fi
제거 프로그램은 앱 안에 있는 셸 스크립트입니다. 실행하기 전에 읽어 보십시오.
제거
제거하는 방법은 세 가지이며, 모두 같은 스크립트를 실행합니다.
- Turnout 윈도우를 연 상태에서 Turnout › ‘Turnout 제거…’를 선택하십시오. 확인 창에서 ‘저장된 터널과 해당 개인 키도 삭제’를 선택하면 그것들도 삭제됩니다. 라이선스가 있는 Mac에서는 확인 창에서 다르게 선택하지 않는 한 먼저 이 Mac을 라이선스에서 제거하고 iCloud 계정에서 이 Mac의 레코드를 삭제합니다.
- 설치 프로그램을 열고 설치할 항목 목록에서 Remove Turnout을 선택하십시오. 저장된 터널도 삭제하려면 Delete saved tunnels도 선택하십시오(설치 프로그램은 현재 영어로만 제공됩니다).
- 터미널에서 다음을 실행하십시오(저장된 터널도 삭제하려면
--purge를 추가합니다).sudo sh /Applications/Turnout.app/Contents/Resources/uninstall.sh
어느 방법이든 모든 터널의 연결을 해제하고(이때 경로와 DNS가 복원됩니다), ‘로그인 항목’에서 백그라운드 서비스를 제거하고, 충돌한 서비스가 남긴 것을 되돌리고, 앱, 로그, 설치 프로그램의 설치 기록, 그리고 모든 사용자의 Turnout 환경설정, 저장된 윈도우 상태, 캐시를 삭제합니다. /Library/Application Support/cc.ctsite.turnout에 있는 저장된 터널과 개인 키는 삭제를 선택하지 않는 한 남아 있습니다.
키체인의 라이선스 항목은 남으므로 다시 설치해도 체험 기간이 새로 시작되지 않으며, 키는 다른 Mac을 위해 iCloud 계정에 남습니다. 설치 프로그램과 터미널 스크립트는 사용자의 키체인이나 iCloud 계정 없이 root 권한으로 실행되므로 이 Mac을 라이선스에서 제거할 수 없습니다. 먼저 ‘라이선스’ 패널에서 제거하거나, 나중에 다른 Mac 또는 Polar의 고객 포털에서 제거하십시오.