본문으로 건너뛰기

보안 ​

이 페이지는 서버를 운영하는 관리자를 위한 것입니다. 새 설치를 강화하는 단계로 시작하고, 그다음 각 보호를 자세히 설명합니다.

프로젝트는 위협 모델과 외부 보안 검토가 아직 진행 중이라고 밝히고 있습니다. 서버를 공개 인터넷에 게시하지 마세요. 클라이언트의 네트워크만 서버에 도달하게 하세요.

새 서버 강화 ​

  1. HTTPS가 작동할 때까지 기본 수신 주소 127.0.0.1을 유지하세요. 네트워크와 HTTPS를 참조하세요.
  2. HTTPS를 켜고 클라이언트 네트워크에 HTTPS 포트만 여세요. 데이터베이스 포트는 절대 열지 마세요.
  3. 관리자를 위한 개인 계정을 만드세요. 비상시를 위해 복구 키를 보관하세요. 복구 키를 참조하세요.
  4. 각 도구나 CI 시스템에 최소 권한을 가진 키가 있는 자체 서비스 계정을 부여하세요. 키와 토큰을 참조하세요.
  5. 자체 등록은 꺼 두세요. 기본적으로 꺼져 있습니다.
  6. Arkvory 앞에 리버스 프록시가 있으면 ARKVORY_TRUSTED_PROXIES를 설정하세요. 로그인 제한을 참조하세요.
  7. 암호화된 vault(기본값)를 쓰고 복구 키트는 서버 밖에 보관하세요. 또한 서비스 계정과 백업 관리자만 읽을 수 있는 암호화된 볼륨에 두세요. 백업을 참고하세요.
  8. 시크릿 파일의 사본을 서버 외부에 보관하세요. 시크릿 백업을 참조하세요.
  9. 메트릭과 경보를 연결하세요. 모니터링을 참조하세요.

네트워크와 HTTPS ​

서버는 기본적으로 127.0.0.1:8080에서 수신 대기합니다. 네이티브 설치는 HTTPS를 구성한 후 다른 주소에서 수신 대기할 수 있습니다:

bash
sudo arkvory configure --root /opt/proanima-arkvory --tls-cert /etc/arkvory/fullchain.pem --tls-key /etc/arkvory/privkey.pem --listen-host 0.0.0.0

이 명령은 파일을 확인하고, 서비스를 다시 시작하며, 서비스가 시작되지 않으면 이전 설정을 복원합니다. 전체 절차와 리버스 프록시가 필요한 Docker Compose는 HTTPS와 리버스 프록시를 참조하세요.

  • 인증서와 키는 읽을 수 있고, 서로 일치하며, 만료되지 않아야 합니다. 그렇지 않으면 API가 시작되지 않으며 일반 HTTP로 대체되지 않습니다.
  • 최소 TLS 버전은 1.2입니다. 1.3을 요구하려면 ARKVORY_TLS_MIN_VERSION=TLSv1.3을 설정하세요. 클라이언트 인증서는 지원되지 않습니다.
  • 서버가 직접 HTTPS를 제공할 때 Strict-Transport-Security: max-age=31536000으로 응답합니다. 프록시가 TLS를 종료할 때는 프록시가 이 헤더를 소유합니다.
  • 갱신된 인증서 파일은 재시작 없이 300초마다(ARKVORY_TLS_RELOAD_SECONDS) 다시 읽습니다. 새 연결은 새 인증서를 받습니다. 읽을 수 없는 파일은 작동 중인 인증서를 그대로 두고 tls.reload_failed를 기록합니다. tls.expiring은 마지막 14일 동안 매일 기록됩니다.
  • TLS와 신뢰할 수 있는 프록시 없이 비루프백 주소를 사용하면 시작 시 http.plaintext_exposed 경고를 기록합니다. 클라이언트를 허용하기 전에 수정하세요.
  • Arkvory는 받은 인증서의 검사를 절대 끄지 않습니다. 미러에서도, 허브에서도, 명령줄 클라이언트에서도 마찬가지입니다. 미러에는 --mirror-ca-file로 자체 인증 기관을 추가하세요.

리버스 프록시 뒤에서 API는 루프백에 머뭅니다. 프록시는 전체 파일을 버퍼링하지 않고 본문을 스트리밍해야 합니다. 다운로드 링크가 시크릿을 쿼리 문자열에 담고 있으므로 프록시에서 쿼리 문자열을 기록하지 마세요.

서버의 시크릿 ​

설치 프로그램은 설치 루트에 다음 파일을 만듭니다. 설치 프로그램이 설정한 권한을 유지하세요.

파일내용접근 권한
config/bootstrap-token.txt복구 키. 관리자 권한이 있습니다Linux: root 전용(모드 0600). Windows: SYSTEM 및 Administrators
config/keys.json복구 키와 상태 키의 SHA-256 해시이며 키 자체는 아닙니다Linux: root가 쓰고 서비스 그룹이 읽음(0640). Windows: 루트에서 상속
config/health-token.txt상태 키 deployment-health. 리포지토리 권한이 없습니다Linux: root 전용. Compose: 컨테이너에서 읽을 수 있음
config/runtime.json비밀번호가 포함된 데이터베이스 URL을 포함한 모든 서버 설정Linux: root가 쓰고 서비스 그룹이 읽음(0640). Windows: 루트에서 상속
config/postgres.envCompose 설치의 데이터베이스 비밀번호root 전용, 또는 SYSTEM 및 Administrators
github-token.txt업데이트용 선택적 GitHub 토큰root 전용, 또는 SYSTEM 및 Administrators
config/mirrors/*.token미러의 원본 서버용 읽기 키서비스 계정
TLS 키인증서의 개인 키위치는 직접 선택합니다. 서비스 계정만 허용하세요

Windows에서 루트는 SYSTEM과 Administrators에 모든 권한을 부여합니다. 서비스 계정 LocalService는 루트를 읽고 data\, logs\, 업데이트 수신함에만 씁니다. 데이터베이스는 다른 계정으로 실행되므로 API가 데이터베이스 파일을 읽을 수 없습니다.

모든 시크릿에 대한 규칙:

  • 파일이나 환경 변수로 전달하고, 명령 인수로는 절대 전달하지 마세요. 인수는 프로세스 목록에 표시됩니다.
  • 복구 키를 클라이언트, CI 시스템, 스크립트에 복사하지 마세요. 일상 작업에는 계정과 서비스 키를 만드세요.
  • 서버는 키, 비밀번호, 토큰, Authorization 헤더, 쿼리 문자열을 로그에 절대 기록하지 않습니다. 모니터링을 참조하세요.
  • 설치 프로그램의 명령 출력은 데이터베이스 URL, 키, 긴 시크릿을 마스킹합니다.

복구 키를 교체하려면 bootstrap-token.txt 파일과 config/keys.json의 해당 해시를 함께 변경하고, deployment-health 항목을 유지한 다음, API와 워커를 다시 시작하세요. 구성을 참조하세요.

비밀번호와 로그인 제한 ​

비밀번호는 12~128자이며 솔트 처리된 해시(scrypt)로만 저장됩니다. 로그인은 12시간 동안 유지됩니다. 한 계정은 최대 32개의 활성 세션을 가질 수 있으며, 새 로그인은 가장 오래된 세션을 종료합니다. 비밀번호 변경이나 재설정은 모든 세션을 종료하고 계정의 모든 개인용 토큰을 폐기합니다.

Arkvory에는 하드 잠금이 없습니다. 하드 잠금이 있으면 이름을 아는 누구나 소유자를 잠글 수 있게 됩니다. 대신 여러 계층에서 공격을 지연시킵니다:

계층제한
주소별, 로그인한 번에 10회 시도, 이후 15초마다 1회 추가. 올바른 비밀번호는 시도를 돌려줍니다. IPv6는 /64 네트워크 단위로 계산
주소별, 자체 등록3회 시도, 이후 20분마다 1회; 프로세스당 20회, 이후 3분마다 1회
계정별잘못된 비밀번호마다 부채가 1단위 늘어납니다. 부채는 6초마다 1씩 줄어듭니다. 20단위를 넘으면 잘못된 비밀번호마다 1초에서 2분까지 두 배로 늘어나는 대기가 추가됩니다. 대기 중에는 올바른 비밀번호도 429를 받습니다
동시 로그인 요청최대 16개이며, 요청 본문은 10초 이내에 도착해야 합니다
비밀번호 확인익명 확인과 관리자 확인은 별도 대기열을 사용하므로 로그인 폭주가 관리자를 막지 않습니다

응답은 사유 login_attempts와 Retry-After 헤더가 있는 429 rate_limited입니다. 주소 카운터는 프로세스에 있으며 재시작 시 초기화됩니다. 계정 부채는 데이터베이스에 있습니다. 관리자의 비밀번호 재설정이 이를 지웁니다.

리버스 프록시 뒤에서는 ARKVORY_TRUSTED_PROXIES를 프록시의 주소로 설정하세요(최대 32개, IP 또는 CIDR). 이 주소들만 X-Forwarded-For로 클라이언트 주소를 지정할 수 있습니다. 이 설정이 없으면 모든 클라이언트가 프록시의 주소를 공유하므로, 로그인 몇 번 실패로 모두가 잠시 잠기게 됩니다.

키, 토큰 및 만료 ​

자격 증명유효 기간교체 및 보관
로그인 세션12시간다시 로그인
개인용 액세스 토큰기본 90일, 최대 365일. 범위 read 또는 read-write. 관리자 권한은 없음개인용 액세스 토큰에서 새 토큰을 만들고 이전 토큰을 폐기
서비스 키기본 90일, 최대 365일. 발급되었지만 활성화되지 않은 키는 15분 후 만료교체가 새 키를 발급합니다. 이전 키는 최대 24시간 더 작동합니다. 폐기는 키를 즉시 중지합니다
다운로드 링크콘솔에서 1시간새 링크 생성
복구 키와 상태 키만료되지 않음수동으로 교체합니다. 서버의 시크릿을 참조하세요

개인용 토큰 생성과 비밀번호 변경은 로그인한 세션에서만 하세요. 토큰은 토큰을 만들 수 없습니다. 개인용 토큰은 소유자가 누구든 관리자 권한이 없습니다.

도구를 위한 최소 권한:

  • 서비스 액세스에서 각 소비자마다 서비스 계정을 하나씩 만들고, 리포지토리 권한로 필요한 정확한 리포지토리와 정확한 작업을 지정하세요. 읽기 프리셋와 게시 프리셋는 일반적인 집합을 채웁니다.
  • 계정과 권한 부여 생성에는 복구 키 또는 위임의 별도 권한이 필요합니다. 관리 위임를 사용하면 소유자가 운영자에게 제한된 권한을 넘길 수 있습니다. 위임된 키는 발급자의 키보다 오래 살지 못합니다.
  • 메트릭 스크레이퍼에는 최소 권한을 가진 자체 키를 부여하세요.
  • 권한 부여를 폐기하면 활성화를 기다리는 키가 차단되지만, 이미 활성화된 키는 폐기되지 않습니다. 그 키들은 직접 폐기하거나 비활성화하세요. 시작된 다운로드는 폐기 후에도 계속됩니다.
  • 권한 변경은 다음 요청부터 적용됩니다. 서버는 목록, 메타데이터, 파일 바이트에 대해 모든 요청마다 접근을 다시 확인합니다.

감사 로그 ​

저널기록 내용확인 위치
보안 저널로그인과 실패, 등록, 계정·그룹·권한 부여·비밀번호·개인용 토큰의 변경. 행위자, 자격 증명 종류, 대상, 결과, 클라이언트 주소 포함GET /api/v1/security/audit, 관리자 세션 또는 복구 키용
카탈로그 감사리포지토리의 아티팩트, 경로, 주석, 스테이지 변경GET /api/v1/repositories/{repository}/audit, 감사를 읽을 권한이 있는 경우
서비스 계정 활동서비스 계정의 생성, 변경, 발급되고 폐기된 키콘솔의 활동 로그
프로세스 로그요청마다 http.access 한 줄, principal과 clientIp 포함모니터링을 참조하세요

보안 저널은 추가 전용입니다. 데이터베이스가 행 변경이나 삭제를 거부합니다. 서버는 365일과 최대 1,000,000개 행을 보관하며, 가장 오래된 행을 배치로 제거합니다. 요청 속도 제한이 거부한 요청은 저널에 기록되지 않으므로 폭주가 테이블을 키울 수 없습니다. 더 긴 기록이 필요하면 저널을 자체 이벤트 저장소로 내보내세요.

bash
curl -fsS -H "Authorization: Bearer $ARKVORY_KEY" "https://arkvory.example/api/v1/security/audit?limit=100"

이전 행을 읽으려면 마지막 ID와 함께 after 매개변수를 사용하세요.

콘솔과 브라우저 ​

서버는 콘솔의 응답에 다음 헤더를 설정합니다:

헤더값
Content-Security-Policydefault-src 'none'; img-src 'self' blob:; script-src 'self'; style-src 'self'; connect-src 'self'; worker-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'
Referrer-Policyno-referrer
X-Content-Type-Optionsnosniff
Cache-Controlprivate, no-store
X-Request-Id응답의 요청 ID

모든 API 응답도 X-Content-Type-Options, Cache-Control, X-Request-Id를 포함합니다. CSP는 인라인 스크립트, 외부 스크립트, 프레이밍, 다른 호스트로의 연결을 허용하지 않습니다. blob:의 그림은 피드백 메시지에 추가하는 스크린샷입니다.

서버는 쿠키를 설정하지 않습니다. 콘솔은 키나 세션 토큰을 브라우저 탭의 메모리에만 보관합니다. 브라우저는 테마와 언어 선택, 다운로드 대기열의 비공개 파일만 저장합니다. 다른 주소의 브라우저 페이지는 API를 호출할 수 없습니다. ARKVORY_CORS_ORIGINS는 기본적으로 비어 있습니다. 외부 콘솔을 위해 최대 16개의 정확한 오리진을 나열하며, 루프백에서는 HTTPS 또는 HTTP를 사용합니다. 허용된 오리진도 추가 권한을 받지 않습니다. 모든 요청에 키가 필요하기 때문입니다.

업데이트 서명 ​

모든 릴리스에는 아카이브와 설치 프로그램의 SHA-256이 담긴 매니페스트 arkvory-release.json과 서명 arkvory-release.json.sig가 있습니다. 서명은 minisign 형식의 Ed25519 서명입니다. 업데이터는 코드 내부에 공개 키를 보관합니다.

  • 허브나 GitHub의 릴리스는 서명이 내장 키와 일치하고 SHA-256 값이 매니페스트와 일치할 때만 설치됩니다. 잘못된 서명은 오류이며, 업데이터는 다른 출처를 찾지 않습니다.
  • 개인 서명 키는 유지 관리자에게 남아 있으며 서버에 절대 있지 않습니다. 릴리스는 키 교체를 위해 이전 공개 키와 새 공개 키를 함께 담을 수 있습니다.
  • --artifact로 전달하는 로컬 폴더는 직접 선택한 것입니다. 그 안의 서명 파일은 있을 때 확인됩니다.
  • 그래픽 설치 프로그램과 .deb 및 .rpm 패키지는 아직 게시자 인증서로 서명되지 않았습니다. Windows는 게시자를 알 수 없음으로 표시합니다. GitHub Releases에서만 다운로드하고 SHA-256 값을 release-checksums.json과 비교하세요.
  • 데이터베이스 스키마를 변경하는 릴리스는 서버가 새 백업을 만들고 검증한 후에만 설치됩니다. 업데이트를 참조하세요.

ProAnimaStudio 허브로 전송되는 내용 ​

업데이트는 ProAnimaStudio의 허브(https://hub.proanima.net)에서 승인됩니다. 서버는 다음 경우에 허브에 접속합니다:

데이터전송 시점내용
업데이트 확인6시간마다현재 버전, 운영 체제, 아키텍처가 주소의 일부입니다. 통계가 켜져 있으면 헤더 X-Install-Id에 임의의 설치 ID
updated 이벤트통계가 켜진 상태에서 업데이트 설치 후버전과 설치 ID
피드백사용자가 콘솔에서 양식을 보낼 때만텍스트, 답변용 선택적 이메일 주소, 최대 6개의 스크린샷, 브라우저 페이지의 로그. 관리자는 API 로그의 마지막 1.5 MiB와 시스템 요약을 추가할 수 있습니다. 양식은 보내기 전에 이 모든 것을 표시합니다(첨부 내용 보기)

설치 ID는 config/install-id에 있는 임의의 UUID입니다. 이름, 주소, 콘텐츠를 담지 않습니다. 프로젝트는 허브가 IP 주소, 이름, 파일 콘텐츠를 저장하지 않는다고 밝히고 있습니다. 통계가 없으면 ID가 전송되지 않고, 허브는 모든 설치에 릴리스되었을 때만 버전을 제공합니다. 시스템 요약은 주소와 시크릿 없이 버전, 스키마 번호, 업데이트와 미러의 상태를 담습니다. API 로그에도 시크릿이 없습니다.

끄는 방법:

bash
sudo arkvory configure --root /opt/proanima-arkvory --statistics off
sudo arkvory configure --root /opt/proanima-arkvory --hub-off
  • --statistics off는 설치 ID와 updated 이벤트를 중지합니다. 콘솔에도 같은 스위치가 있습니다: 업데이트의 ProAnimaStudio에 익명 통계 보내기.
  • --hub-off는 허브와의 모든 접속을 중지합니다. 그러면 업데이트는 GitHub에서만 오고, 콘솔 피드백은 서비스가 다음에 다시 시작된 후 꺼집니다. 사용자에게는 대신 콘솔에 표시된 연락 주소가 제공됩니다.
  • --hub-url https://hub.example은 서버를 다른 허브로 지정합니다. HTTPS 또는 루프백의 HTTP만 허용됩니다.

6시간마다 확인은 자동 설치가 꺼져 있어도 실행됩니다. 인터넷 접속이 없는 서버는 릴리스의 로컬 사본에서 설치합니다. 업데이트를 참조하세요.

시크릿 백업 ​

vault에는 카탈로그, 비밀번호 해시, 게시된 모든 파일이 들어 있습니다. Arkvory는 만들 때 이를 암호화하며, 복구 키트는 서버 밖에 보관해야 합니다(백업 참고). vault에는 구성 파일이 들어 있지 않습니다. 이 파일들의 두 번째 사본을 서버 밖의 암호화된 장소에 보관하세요.

  • 백업 vault의 복구 키트: 서버와 그 키 파일을 잃었을 때 백업을 읽을 수 있는 유일한 방법입니다. 두 곳에 두 부를 보관하세요.
  • config/keys.json 및 config/bootstrap-token.txt(복구 키),
  • config/runtime.json,
  • TLS 인증서와 키,
  • 미러의 키가 있는 config/mirrors/,
  • config/hub.json 및 github-token.txt(사용하는 경우).

복원은 자체 설정과 자체 키 파일을 가진 새 인스턴스를 만듭니다. 복원 후에는 세션이 사라지고, 개인용 토큰과 서비스 키가 폐기되며, 물리적 정리와 보존 정책이 꺼집니다. 새 키를 발급하고 정책을 의도적으로 다시 켜세요. 비밀번호는 스냅샷 시각의 상태로 돌아갑니다. 이 파일의 모든 사본을 시크릿으로 취급하세요. 백업을 참조하세요.

취약점 보고 ​

공개 이슈에 취약점을 설명하거나 키를 게시하지 마세요. 프로젝트 소유자는 Ian Panaev입니다(GitHub 계정 ProAnima). 프로젝트는 아직 보안 보고를 위한 전용 비공개 채널을 공개하지 않았습니다. 익스플로잇 세부 정보 없이 짧은 메시지를 프로젝트의 GitHub 계정이나 콘솔에 표시된 스튜디오 주소 info@proanima.net으로 보내고, 비공개로 계속할 방법을 문의하세요. 리포지토리의 SECURITY.md를 참조하세요.

Arkvory · ProAnimaStudio