Files
minecraft_launcher/docs/portforwarding-free-connection-plan.md
claude-bot 24a0569fb4
Some checks failed
Build / release (macos-latest) (push) Has been cancelled
Build / release (ubuntu-latest) (push) Has been cancelled
Build / release (windows-latest) (push) Has been cancelled
Windows Smoke Test / windows-smoke (push) Has been cancelled
Add launcher catalog workflow and smoke tests
2026-05-04 14:06:05 +09:00

265 lines
7.1 KiB
Markdown

# Portforwarding-Free Connection Plan
이 문서는 “포트포워딩 없이 런처만으로 접속” 기능을 나중에 구현하기 위한 설계 초안이다. 현재는 구현하지 않았고, `server-pack` 프로필의 `tunnelCommand` 자리에 외부 도구를 연결할 수 있는 수준까지만 준비되어 있다.
## 목표
- 호스트 사용자가 공유기 포트포워딩을 직접 설정하지 않아도 됨
- 접속 사용자는 런처에서 세션 주소 또는 세션 코드를 받아 바로 접속 가능
- 가능하면 버튼 몇 번으로 `서버 실행 -> 세션 공개 -> 다른 사용자 접속` 흐름이 끝나야 함
- 관리자가 런처와 백엔드를 함께 운영할 수 있어야 함
## 원하는 사용자 흐름
### 호스트
1. 라이브러리에서 `server-pack` 프로필 선택
2. `서버 실행` 클릭
3. 런처가 서버 프로세스를 시작
4. 런처가 백엔드에 세션 생성 요청
5. 백엔드가 공개 접속 주소 또는 세션 코드를 발급
6. 호스트는 그 주소/코드를 다른 사용자에게 전달
### 접속자
1. 같은 프로필을 라이브러리에 추가
2. 호스트가 보낸 주소 또는 세션 코드를 입력
3. 런처가 실제 접속 주소를 해석
4. 마인크래프트를 자동 실행하고 해당 서버로 바로 접속
## 필요한 구성요소
### 1. Session API
역할:
- 세션 생성
- 세션 갱신
- 세션 종료
- 세션 조회
- 세션 코드와 실제 릴레이 주소 매핑
예상 엔드포인트:
- `POST /api/sessions`
- `PATCH /api/sessions/:id`
- `DELETE /api/sessions/:id`
- `GET /api/sessions/:code`
세션 데이터 예시:
```json
{
"id": "sess_123",
"profileId": "my-server-pack",
"hostUserId": "uuid-or-account-id",
"relayAddress": "relay.example.com:34192",
"accessCode": "ABCD-EFGH",
"status": "active",
"createdAt": "2026-05-04T10:00:00Z",
"lastHeartbeatAt": "2026-05-04T10:01:00Z"
}
```
### 2. Relay or Tunnel Layer
실제로 포트포워딩 없는 접속을 가능하게 하는 핵심이다.
선택지:
- 자체 Relay 서버 운영
- 기존 터널링 솔루션 연동
- TURN 비슷한 중계 방식
- 전용 게임 프록시 운영
이 프로젝트에서는 우선 아래 두 단계 접근이 현실적이다.
1. 외부 터널링 도구 연동
2. 자체 세션/중계 서버로 점진적 전환
### 3. Launcher Host Agent
호스트 측 런처가 해야 하는 일:
- 로컬 서버 실행 상태 확인
- 백엔드에 세션 생성
- 터널 또는 릴레이 프로세스 시작
- 공개 주소 수신
- 주기적 heartbeat 전송
- 서버 종료 시 세션 종료
### 4. Launcher Join Resolver
접속자 측 런처가 해야 하는 일:
- 세션 코드 입력 UI 제공
- 코드로 세션 조회
- 실제 접속 주소 해석
- 선택 프로필과 세션 프로필 일치 여부 확인
- 게임 실행 시 자동 접속 파라미터 전달
## 권장 1차 구현 방향
가장 빠른 방향은 “전용 Relay”를 바로 만드는 것이 아니라, “Session API + 터널 도구 연동”부터 시작하는 것이다.
### 이유
- 현재 런처에 `server-pack`, `tunnelCommand`, 공개 주소 표시 흐름이 이미 들어가 있음
- 가장 적은 변경으로 실사용 가능 여부를 먼저 검증할 수 있음
- 이후 자체 릴레이로 갈아탈 때 UI와 라이브러리 모델을 그대로 유지할 수 있음
### 1차 구성
- 런처:
- 서버 실행
- 터널 명령 실행
- 터널 출력에서 공개 주소 파싱
- Session API에 주소 등록
- 백엔드:
- 세션 코드 발급
- 코드 -> 주소 매핑
- heartbeat 만료 처리
- 접속자 런처:
- 세션 코드 입력
- 코드 조회
- 자동 접속
## 이후 2차 구현 방향
터널 명령에 외부 도구를 직접 의존하지 않고, 전용 서비스로 이동한다.
### 추가되는 것
- 릴레이 노드
- 호스트 인증 토큰
- 세션별 임시 접속 권한
- 트래픽/세션 제한
- 관리자 대시보드
### 기대 효과
- 터널 도구 설치 부담 감소
- 사용자 경험 단순화
- 접속 로그와 세션 통계 수집 가능
- 악용 방지 정책 적용 가능
## 런처 쪽에 나중에 추가할 UI
### 라이브러리
- `세션 만들기`
- `세션 코드 복사`
- `세션 종료`
- `세션 상태 보기`
### 설치/실행
- `세션 코드로 접속`
- 최근 접속 세션 기록
- 세션 만료 안내
### 설정
- 세션 API 주소
- 릴레이 지역 선택
- 호스트 세션 자동 재등록 여부
## 프로필 스키마 확장 예정
나중에 `catalog.json` 또는 분리된 관리자 설정에 아래 필드가 추가될 수 있다.
```json
{
"sessionBackendUrl": "https://session.example.com",
"sessionJoinMode": "code",
"sessionCodeLength": 8,
"relayMode": "external-tunnel",
"relayRegion": "ap-northeast-2"
}
```
## 보안 고려사항
필수 항목:
- 세션 생성은 인증된 사용자만 가능해야 함
- 호스트 heartbeat가 끊기면 세션 자동 만료
- 세션 코드는 충분히 예측 불가능해야 함
- 동일 계정의 세션 수 제한 필요
- 악의적 트래픽에 대한 rate limit 필요
- 프로필 ID 불일치 세션 차단 또는 경고 필요
추가 고려:
- 세션 코드에 만료 시간 포함
- 백엔드 서명 토큰 사용
- 서버 로그 업로드 여부
- 접속자 IP/세션 기록 보관 정책
## 장애 대응
### 호스트 측
- 서버는 켜졌는데 릴레이 주소 발급 실패
- 터널은 살아있는데 heartbeat 실패
- 서버 프로세스 종료 후 세션 정리 누락
대응:
- 런처가 재시도 정책 보유
- 종료 이벤트에서 세션 삭제 호출
- stale session 정리 배치 작업 필요
### 접속자 측
- 세션 코드는 맞는데 만료됨
- 주소는 받았는데 릴레이가 이미 죽음
- 잘못된 프로필로 접속 시도
대응:
- 사용자에게 구체적인 실패 메시지 제공
- 세션 재조회 버튼
- 프로필 불일치 시 설치 페이지 이동 유도
## 구현 순서 제안
### 1단계
- Session API 설계
- 세션 코드 발급/조회/만료 로직 구현
- 런처에 세션 코드 입력 UI 추가
### 2단계
- 현재 `tunnelCommand` 기반 흐름과 Session API 연결
- 호스트 세션 등록/heartbeat/종료 처리
- 접속자 자동 접속 완료
### 3단계
- 자체 Relay 서비스 검토
- 전용 호스트 인증 및 운영 정책 도입
- 외부 터널 도구 의존도 축소
## 현재 코드와 연결되는 지점
- `app/assets/js/serverruntime.js`
- 서버 실행 후 공개 주소 확보 지점
- `app/assets/js/scripts/library.js`
- 호스트 공개 주소 표시 및 수동 주소 입력 UI
- `app/assets/js/processbuilder.js`
- 자동 접속 인자 전달 지점
- `app/assets/js/catalogmanager.js`
- 프로필 메타데이터 확장 지점
## 결론
“포트포워딩 없이 접속”은 런처 버튼 하나로 끝나는 기능처럼 보여도, 실제로는 런처만의 문제가 아니라 세션 백엔드와 릴레이 계층이 함께 있어야 성립한다.
따라서 다음 구현 목표는 아래가 적절하다.
1. `Session API` 설계
2. `server-pack + tunnelCommand` 흐름을 세션 코드 모델과 연결
3. 이후 전용 Relay 서비스로 확장