🎮

[1/5] MacBook에서 Windows 분석 VM 보기 — Sunshine·Moonlight 원격 분석 환경

Description
MacBook의 Moonlight와 Windows 분석 VM의 Sunshine을 Linux 게이트웨이로 연결하면서 원격 화면과 네트워크 권한을 분리한 구성
URL
기간
Sep 30, 2025 → Oct 14, 2025
분야
보안
상태
초안
시리즈
Security Foundations
요약
Sunshine·Moonlight의 실제 배치, 가상 디스플레이, 스트리밍 포트와 stateful 응답 경로를 분석한다.
원작성일
Aug 26, 2026
태그
Windows Internals
Reverse Engineering
Pentesting
🎮
클라이언트: MacBook Moonlight
서버: Windows VM 10.10.0.20 Sunshine
게이트웨이: Linux tailscale0 → nftables FORWARD → 전용 NIC

구성 요약

Moonlight, Linux gateway, Sunshine의 실행 위치는 다음과 같다.
MacBook: Moonlight Client Linux: Tailscale subnet router + nftables gateway Windows VM 10.10.0.20: Sunshine Server + 분석 도구
Linux에는 Sunshine과 Moonlight를 설치하지 않았다. Linux는 Tailnet 패킷을 전용 NIC로 전달하고 nftables에서 허용 여부를 결정한다.

원격 접속 요구사항

악성코드는 Windows VM에서 실행한다. 화면 수신과 입력은 MacBook에서 처리한다. 물리 모니터가 없는 VM에는 Sunshine이 캡처할 가상 디스플레이가 필요하다.
에서 Wake-on-LAN까지 포함한 Windows 원격 운용을 고민했고, 에서 1소켓 6코어, 메모리 24GB의 Windows VM을 구성했다. 이후 에서 Virtual Display Driver와 MonitorSwapAutomation을 적용했다.
신규 Sunshine 세션은 MacBook에서 시작한다. 패킷은 Linux의 FORWARD hook을 거쳐 Windows VM에 도착한다.

패킷 경로

구성 요소
실행 위치
역할
Moonlight
MacBook
Windows 화면 수신과 입력 전달
Tailscale
MacBook·Linux
MacBook에서 Linux 게이트웨이까지 관리 터널 제공
nftables
Linux
Tailnet과 분석망 사이의 신규 흐름 심사
Sunshine
Windows VM 10.10.0.20
화면 캡처·인코딩·스트리밍 서비스
Virtual Display Driver
Windows VM
물리 모니터가 없어도 캡처할 화면 생성

Windows VM 가상 디스플레이 설정

Windows VM은 CPU 1소켓 6코어, 메모리 24GB로 구성했고 ballooning을 활성화했다. 물리 모니터가 없으므로 Sunshine이 캡처할 디스플레이가 존재하지 않았다.
Virtual Display Driver로 두 번째 가상 화면을 만들고 Sunshine이 그 화면을 사용하도록 했다. MonitorSwapAutomation은 물리·가상 디스플레이 전환 과정의 불편을 줄이기 위한 보조 도구였다.
Sunshine은 Virtual Display Driver가 만든 화면을 캡처하고, MacBook의 Moonlight가 영상과 입력 세션을 처리한다.

Sunshine/Moonlight 허용 포트

nftables에는 다음 포트 범위를 정의했다.
define S_TCP = { 47984-47990, 48010 } define S_UDP = { 47998-48010 }
S_TCPS_UDP는 서버에 실제 적용한 허용 범위다. 범위 안의 모든 포트가 항상 필수라는 뜻은 아니다. Sunshine 문서에는 HTTPS, HTTP, Web UI, RTSP, video, control, audio처럼 포트별 역할이 구분되어 있다. Sunshine Network configuration
이 범위는 서버에 적용했던 화이트리스트이며 Sunshine의 필수 포트 목록과 동일하지 않다. 애플리케이션 버전과 스트리밍 채널을 고려해 공식 문서의 개별 포트보다 넓게 설정했다.

신규 연결과 응답 트래픽

Moonlight가 MacBook에서 Windows VM의 Sunshine으로 연결을 시작하면 신규 패킷은 다음 규칙을 통과한다.
iif $IF_TS oif $IF_INTERNAL ip daddr $VM_IP tcp dport $S_TCP counter accept iif $IF_TS oif $IF_INTERNAL ip daddr $VM_IP udp dport $S_UDP counter accept
Windows가 보내는 정상 응답은 별도의 역방향 신규 허용 규칙이 없어도 connection tracking으로 처리된다.
ct state { established, related } counter accept
패킷 흐름을 세션 기준으로 보면 다음과 같다.
1. MacBook Moonlight가 10.10.0.20 Sunshine으로 연결 시작 2. tailscale0 → Linux FORWARD → 전용 NIC 3. nftables가 목적지·포트 기준으로 신규 연결 허용 4. Windows의 응답은 established 상태로 복귀
최종 ruleset에는 Windows VM이 Tailnet의 동일 목적 포트로 신규 연결을 시작하는 역방향 예외도 있다. 이 예외는 Sunshine 응답용 established 규칙과 별개의 신규 연결 규칙이다.

흐름별 허용·차단 정책

Sunshine 세션과 Windows VM의 일반 라우팅은 다음과 같이 분리했다.
흐름
결과
의미
MacBook → Windows Sunshine
ALLOW
원격 관리 경로
Windows → 같은 세션의 응답
ALLOW
stateful response
Windows → Linux 호스트 신규 연결
DROP
분석 VM이 게이트웨이 서비스를 탐색하지 못하게 함
Windows → WAN 일반 라우팅
DROP
Linux를 인터넷 출구로 사용하지 못하게 함
Windows → Tailnet 임의 포트
DROP
관리망으로의 횡적 이동 제한
MacBook → Windows Sunshine 세션과 해당 응답은 허용된다. Windows VM → Linux·WAN·Tailnet 비허용 포트의 신규 연결은 차단된다.

패킷 및 counter 검증

Linux에서 연결 여부만 확인하는 대신 인터페이스와 nftables counter를 함께 본다.
sudo nft list chain inet filter FWD-TS sudo nft list chain inet filter FWD-STATE sudo tcpdump -ni tailscale0 host 10.10.0.20 sudo tcpdump -ni enx00e04c637a20 host 10.10.0.20
확인할 포인트는 세 가지다.
  1. MacBook에서 연결을 시작할 때 tailscale0에 패킷이 보이는가
  1. 같은 세션이 enx00e04c637a20으로 전달되는가
  1. 응답 패킷이 FWD-STATE의 established counter를 증가시키는가
세 조건이 충족되면 Sunshine 세션이 Linux에서 정상적으로 forwarding되고 FWD-STATE가 응답 패킷을 처리한 것이다.

정리

Moonlight는 MacBook, Sunshine과 Virtual Display Driver는 Windows VM에서 실행한다. Linux는 tailscale0와 전용 NIC 사이에서 IP forwarding과 nftables filtering을 수행한다.
FWD-TS는 목적지 10.10.0.20과 스트리밍 포트의 신규 연결을 허용한다. FWD-STATE는 해당 세션의 established,related 응답을 처리한다. Windows VM의 Linux·WAN·Tailnet 비허용 포트 접근은 별도 DROP 규칙에 도달한다.

Sources

작업 기록

공식·프로젝트 문서


시리즈 이동

전체 시리즈