특정 전술에 대해 안전하게 개발하고 치트를 방지하는 방법에 대해 들어가기 전에, Roblox 보안의 기본 원칙을 이해하는 것이 필수적입니다. 안전한 경험은 적대적인 행동을 예상하는 사고 방식 위에 구축됩니다. 한 줄의 코드를 작성하기 전에 이러한 기본 원칙을 내재화해야 합니다. 이 원칙들은 여러분의 모든 아키텍처 및 디자인 결정에 영향을 미쳐야 합니다.
클라이언트를 결코 믿지 마세요
이것이 기본 원칙입니다. 단호한 악용자는 자신의 로컬 상태와 네트워크 트래픽을 완전히 제어합니다. 악용자가 이러한 수준의 제어를 가지고 있기 때문에 클라이언트 측 강제를 기반으로 한 모든 보안 조치는 결국 우회될 것입니다. 이것은 Roblox의 한계가 아닙니다. 클라이언트-서버 아키텍처의 기본적인 현실입니다. 클라이언트에서 전송된 모든 데이터는 조작되었거나, 제작되었거나, 악의적인 의도로 전송되었다고 가정해야 합니다. 이는 다음과 같은 권한을 포함합니다:
- 클라이언트에서 실행되지 않더라도 복제된 LocalScript 또는 ModuleScript를 디컴파일할 수 있습니다.
- 자신의 캐릭터 및 고정되지 않은 부품을 네트워크 소유할 수 있습니다.
- Touched 이벤트 또는 ProximityPrompt 활성화와 같은 클라이언트 주도 이벤트를 임의의 범위나 빈도로 트리거할 수 있습니다.
- 자신의 플레이어 위치, 물리 또는 세상과의 상호작용을 수정할 수 있습니다.
- 첫 번째 Player 인수를 제외한 임의의 인수로 RemoteEvents 및 RemoteFunctions를 임의의 빈도로 발사하거나 호출할 수 있습니다.
- 예상 이벤트를 트리거하지 않고 자신의 로컬 DataModel에서 무언가를 변경할 수 있습니다.
- 로컬에서 실행 중인 코드의 동작을 균일하게 변경할 수 있습니다.
이 때문에 모든 중요한 로직은 서버 측에서 검증되거나 서버에서만 실행되어야 합니다. 이러한 제어의 결과에 대한 자세한 내용은 네트워크 소유권, 움직임 검증 및 물리적 악용 및 접근 제어와 기밀성에서 확인할 수 있습니다.
서버 권한
서버는 모든 시뮬레이션 상태, 규칙, 플레이어 진행 상황 및 중요한 결정에 대한 궁극적인 진실의 원천이 되어야 합니다. 클라이언트의 역할은 세상을 렌더링하고 사용자 입력을 서버로 전송하는 것입니다.
서버의 역할은 다음과 같습니다:
- 클라이언트로부터 입력을 수신합니다.
- 요청된 행동이 가능하고 허용 가능한지 검증합니다.
- 행동을 실행하고 권위 있는 상태를 업데이트합니다.
- 관련 모든 클라이언트에 결과를 복제합니다.
예를 들어, 플레이어가 "블록시 콜라를 사고 싶어요"라고 말하면 서버는 해당 아이템의 실제 가격, 플레이어의 돈, 플레이어 캐릭터의 상점으로부터의 물리적 거리를 알아야 거래를 검증하고 승인할 수 있습니다. 가능한 한 검증할 상태는 서버에서만 유지되고 클라이언트에서는 유지되지 않아야 합니다. 예를 들어, 블록시 콜라 거래가 승인되면 서버는 플레이어의 돈에서 블록시 콜라의 가격을 차감해야 하지만, 서버가 항상 플레이어의 캐릭터를 제어할 수는 없습니다.
설계에 의한 보안
처음부터 경험의 설계에 보안 고려사항을 통합하고, 나중에 단순히 추가하는 것이 아니라는 점을 인지하세요.
- 모든 새로운 기능에 대해 위협 모델을 만듭니다. 각 새로운 기능에 대해 다음을 질문하세요:
- 공격자가 자신의 클라이언트를 완전히 제어할 수 있다고 가정할 때, 이 기능을 어떻게 악용할 수 있을까요?
- 클라이언트가 이 기능에 사용되는 모든 매개변수에 대해 어떤 값을 보낼 수 있다면, 최악의 결과는 무엇일까요?
- 이 기능이 초당 1,000회 이상 사용되면 어떻게 될까요? 최대 사용 속도는 얼마이어야 할까요?
- 악용자가 이 기능을 사용하여 다른 플레이어의 경험을 흐트러뜨릴 수 있을까요?
- 최악의 경우, 이 기능이 사용할 수 있는 리소스는 얼마인가요?
- 이 기능을 위해 노출해야 하는 최소 내부 정보나 상태는 무엇인가요?
- 책임을 조기에 분할하세요. ServerScriptService에서 로직과 데이터를 유지하십시오. 절대 ReplicatedStorage 또는 Workspace와 같은 복제된 컨테이너에 배치하지 마세요.