# 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 서비스로 확장