보안 모범 사례

보안 모범 사례 (Security Best Practices)

LiteLLM에서 보안은 최우선이에요. 프로덕션·엔터프라이즈 배포에는 다음 사례를 사용하세요.

출처: 문서

본문

1. 보안 이메일 모니터링과 신속한 업그레이드

LiteLLM Enterprise 계정과 연결된 이메일 주소의 CVE 알림과 보안 업데이트를 모니터링하세요. 크거나 주요한 보안 업데이트의 경우 LiteLLM은 공개 공개 7일 전에 Enterprise 고객에게 이메일로 알려요. 이 기간을 사용해 업데이트된 버전을 테스트·배포하고, 업그레이드 문제가 있으면 회신하세요.

이 이메일이 보안·플랫폼 양쪽 팀에 모두 도달하는지 확인하세요.

2. 지원되는 안정 릴리스 실행

최신 안정 릴리스에 머물고 정기 패치 프로세스에 LiteLLM 업그레이드를 포함하세요. latest 대신 정확한 버전이나 이미지 다이제스트를 고정하고, 배포 전에 Docker 이미지 서명을 검증하세요.

현재 릴리스 일정은 LiteLLM 릴리스 주기를 참고하세요.

3. 최소 권한 접근 (Least-privilege access)

최소 필수 RBAC 역할을 지정하고 프록시 관리자 수를 적게 유지하세요.

애플리케이션·사용자는 LiteLLM 마스터 키가 아니라 범위가 지정된 가상 키를 사용해야 해요. 각 프로덕션 워크로드에 별도의 서비스 계정 키를 사용해서 다른 서비스에 영향 없이 접근을 폐기할 수 있게 하세요.

Admin UI에 대한 환경 자격증명 로그인 비활성화

기본적으로 Admin UI는 환경 변수로 만든 로그인을 받아들여요. UI_USERNAME(기본 admin) + UI_PASSWORD, 그리고 UI_PASSWORD가 설정되지 않으면 마스터 키 자체예요. 이것은 영구적·공유·평문 관리 자격증명이에요. 사람마다 회전할 수 없고, 환경을 한 번이라도 읽은 사람은 누구나 프록시 관리자로 계속 로그인할 수 있으며, 감사 로그는 개인에게 변경을 귀속시킬 수 없어요. 부트스트랩 메커니즘으로만 취급하세요. 활성화된 동안 대시보드는 관리자에게 경고 배너를 보여줘요.

비활성화 전에 관리자마다 자체 비밀번호의 proxy_admin 사용자를 만들고(또는 SSO 연결) 로그인할 수 있는지 확인하세요. 그다음 config.yaml에 다음을 설정하고 프록시를 재시작해요.

general_settings:
  disable_env_credential_login: true

이제 UI_USERNAME, UI_PASSWORD, 마스터 키가 로그인 페이지에서 거부되고 배너가 사라져요. DB 사용자와 SSO는 영향받지 않아요. 관리자 계정이 있기 전에 활성화했다면 설정을 제거하고 재시작해 환경 로그인을 되돌려요. API는 그동안 마스터 키로 계속 동작해요. 단계별 흐름은 Admin UI 빠른 시작 참조.

실패한 Admin UI 로그인 시도 제한

Admin UI에 대한 실패한 비밀번호 로그인은 기본적으로 레이트 리밋돼요. 60초 내에 한 소스 주소에서 10개보다 많은 틀린 비밀번호는 그 주소를 5분간 차단하고, 그 주소에서 단일 사용자 이름에 대해 5개보다 많으면 그 쌍만 차단해요. 차단은 주소에 키가 매겨지고 계정에는 절대 매겨지지 않으므로, 아무도 다른 곳에서 사용자 이름을 추측해 관리자를 잠글 수 없어요. 사용자 이름별 제한은 사무실 NAT 뒤의 잘못 구성된 스크립트 하나가 같은 주소의 모든 동료를 차단하는 것을 막아줘요. 차단은 절대적이에요. 올바른 비밀번호, UI_USERNAME/UI_PASSWORD, 마스터 키 모두 만료 전까지 429로 거부돼요. 올바른 자격증명에 대한 예외가 있으면 공격자가 그것을 통해 계속 추측할 수 있기 때문이에요. 차단된 관리자는 여전히 마스터 키를 API bearer 토큰으로 사용할 수 있으며 제한이 다루지 않아요.

주소별 제한은 LiteLLM이 클라이언트가 어떤 주소인지 알 때만 실행되므로, 프로덕션 배포는 general_settings.trusted_proxy_ranges를 리버스 프록시·ingress의 CIDR 범위로 설정해 클라이언트를 X-Forwarded-For에서 읽고 바깥의 위조 헤더가 다른 주소를 고를 수 없게 하거나, 클라이언트가 직접 연결할 때 []로 설정해야 해요. 미설정으로 두면 프록시가 시작 시 경고하고 사용자 이름별 제한만 강제하는데, 이는 한 주소에서의 사용자 이름 스프레이를 무제한으로 남겨요. 알려진 공유 이그레스 주소에는 전역 제한을 올리는 대신 max_failed_login_attempts_per_source_overrides를 사용하세요.

general_settings:
  trusted_proxy_ranges: ["10.0.0.0/8"]  # your ingress; [] when clients connect directly
  max_failed_login_attempts_per_source_overrides:
    "203.0.113.7": 50                   # shared office egress
    "198.51.100.4": 0                   # a scanner you run yourself, exempt

차단은 Redis를 통해 워커·파드 간에 공유되며, Redis가 없으면 각 워커가 별도로 세고 프록시가 시작 시 경고해요. 사용자 이름은 해시로 저장돼요. 설정과 기본값은 Admin UI 가이드에 있어요.

4. 엔터프라이즈 신원 공급자 연결

SSO

Admin UI에 SSO를 활성화해 인증·MFA·로그인 정책이 신원 공급자에서 중앙 집중되게 해요.

JWT

API 트래픽에 JWT 인증을 활성화해 워크로드가 공유·장수명 API 키 대신 OIDC 제공자의 서명 신원을 사용할 수 있게 해요. JWT 클레임은 요청을 LiteLLM 사용자, 팀, 모델, 지출 제어에 매핑할 수도 있어요.

SCIM

SCIM을 활성화해 사용자·팀을 자동으로 프로비저닝·디프로비저닝해요. 사용자가 신원 공급자에서 제거되면 LiteLLM이 연결된 키와 접근 토큰을 제거해 쓸모없는 접근을 줄여요.

5. 네트워크 접근 제한

가능하면 LiteLLM 게이트웨이를 사설 네트워크에서 실행하고 클라이언트가 필요한 라우트만 노출하세요. 배포 전에 공용 라우트 설정을 검토하세요.

클라이언트-게이트웨이 및 게이트웨이-프로바이더 트래픽에 TLS를 사용하세요. 인증서 검증을 유지하세요. 조직이 사설 CA를 사용하면 커스텀 CA 번들을 구성하세요.

6. 비밀 보호와 감사 로그 검토

프로바이더 자격증명, 마스터 키, 솔트 키를 플랫폼의 시크릿 스토어 또는 지원되는 시크릿 매니저에 저장하세요. config.yaml이나 소스 제어에 비밀을 커밋하지 마세요. 마스터 키 로테이션 가이드를 따르고, 자격증명이 저장된 뒤에는 LITELLM_SALT_KEY를 회전하지 마세요.

감사 로그를 활성화하고 키 생성, 키 삭제, 역할 변경, 팀 업데이트 같은 관리 변경을 검토하세요.

7. 오류 응답·헤더를 통해 내부 노출 피하기

예상치 못한 5xx 오류는 클라이언트에 일반적 Internal server error 메시지를 반환하며, 원본 예외(스택 트레이스 포함)는 항상 서버 로그에 기록돼요. x-litellm-call-id 응답 헤더를 사용해 클라이언트 노출 메시지가 어떤 상세도 담을 필요 없이 실패한 요청을 서버 측 로그 항목과 연관지어요.

LiteLLM 자체의 uvicorn 기반 시작(litellm --config ... 또는 기본 Docker 이미지)은 Server 응답 헤더를 보내지 않아요. gunicorn, hypercorn, granian 워커 뒤에서, 또는 리버스 프록시·로드 밸런서(nginx, ingress 컨트롤러, CDN) 뒤에서 실행하면 그 계층이 자체 이름·버전을 공개하는 Server 헤더를 추가할 수 있어요. 그 헤더를 생략하거나 일반화하도록 구성하세요. 예를 들어 nginx의 server_tokens off, 또는 ingress 컨트롤러·CDN의 해당 설정.

8. 민감 워크로드용 가드레일 추가 (선택)

워크로드가 민감하거나 규제된 데이터를 다루면 가드레일을 추가해 프롬프트와 응답을 검사하세요. 콘텐츠 필터링, PII 감지, 거부 주제 정책에는 Bedrock Guardrails를, 특정 단어·패턴의 가벼운 regex 기반 차단에는 LiteLLM 콘텐츠 필터를 권장해요. 가드레일은 키·팀·모델별로 적용할 수 있어 필요할 때 더 엄격한 제어를 강제할 수 있어요.

8. TLS 종료 리버스 프록시 뒤에서 보안 쿠키 구성

프록시의 세션·SSO·SAML 쿠키는 공개 기준(public-facing origin)이 HTTPS일 때마다 Secure로 표시돼요. TLS가 LiteLLM 앞의 리버스 프록시·로드 밸런서에서 종료되면 LiteLLM은 그 프록시로부터의 평문-HTTP 홉만 보므로, 공개 origin이 실제로 HTTPS임을 알려주는 하나의 신뢰 신호가 필요해요.

general_settings:
  use_x_forwarded_for: true
  mcp_trusted_proxy_ranges:
    - "10.0.0.0/8" # your reverse proxy / ingress controller's network

이 중 하나도 구성하지 않으면 TLS 종료 뒤의 배포는 Secure 없는 쿠키를 받아요. LiteLLM이 HTTPS로 도달되고 있다는 신뢰할 방식을 알 수 없기 때문이에요. mcp_ 접두사에도 불구하고 두 설정 모두 MCP 전용이 아니에요. 둘 다 LiteLLM이 X-Forwarded-* 헤더에 사용하는 일반 요청 신뢰 경계예요.

9. 프로덕션에서 API 문서 비활성화

기본적으로 프록시는 /에 Swagger UI, /redoc에 ReDoc, /openapi.json에 원시 OpenAPI 스키마를 인증 없이 서빙해요. 보안 스캐너는 모든 라우트와 요청 스키마를 나열하므로 정찰 표면으로 플래그해요. 프로덕션에서 세 개를 모두 비활성화해요.

NO_DOCS="True"
NO_REDOC="True"
NO_OPENAPI="True"

각 변수는 별도 표면을 제어하므로 NO_DOCS만 설정해도 /redoc/openapi.json이 여전히 읽힐 수 있어요. 세 개 모두 설정하고 프록시를 재시작하세요. 그러면 /redoc/openapi.json은 404를 반환하고 /는 평문 "LiteLLM: RUNNING" 상태 문자열만 반환해요. 추론·관리 라우트는 영향받지 않아요. 표면별 변수와 문서를 다른 경로로 옮기는 방법은 모든 API 문서 제한 문서 참조.

10. 파일 업로드 제한

POST /v1/files는 다른 모든 프록시 라우트처럼 가상 키가 필요하며, 프록시는 업로드된 바이트를 구성된 프로바이더에만 전달해요. 파일을 직접 실행·언팩·서빙하지 않아요. 그래도 업로드를 신뢰할 수 없는 입력으로 취급하고 게이트웨이가 프로바이더에 도달하기 전에 받아들이는 것을 제한하세요.

general_settings 아래에 allowed_file_extensions를 워크로드가 실제로 필요한 확장자로 설정해요. 매칭은 업로드된 파일 이름에 대해 대소문자를 무시하므로 .jsonlbatch.JSONL도 받아요. 다른 확장자와 확장자가 없는 파일 이름은 전달 전에 400으로 거부돼요. 빈 목록([])은 모든 업로드를 거부하고, 설정을 빼면 업로드가 무제한으로 남아요. 업로드 상한에는 max_file_size_mb를, 배치 입력 파일에는 max_batch_file_size_mb를, 모든 라우트의 전체 요청 본문에는 max_request_size_mb를 짝지으세요.

general_settings:
  master_key: sk-1234
  allowed_file_extensions: [".jsonl", ".pdf", ".txt"]
  max_file_size_mb: 50
  max_batch_file_size_mb: 200
  max_request_size_mb: 250

거부된 업로드는 OpenAI 형태의 오류를 반환해요.

{
  "error": {
    "message": "File extension '.exe' is not in this proxy's allowed_file_extensions setting. The file was not forwarded to the provider.",
    "type": "invalid_request_error",
    "param": "file",
    "code": "400"
  }
}

blocked_file_extensions는 예전 블록리스트이며 허용 목록을 위해 폐기(deprecated)됐어요. 여전히 동작하고, 둘 다 설정되면 허용 목록이 먼저 확인되고 그걸 통과한 것에 블록리스트도 여전히 강제돼요. 허용 목록을 선호해요. 블록리스트는 막고 싶은 모든 확장자를 지정해야 하지만, 허용 목록은 사용하는 것만 지정하면 되기 때문이에요.

더 알아보기 (Learn more)