Webship 블로그로 돌아가기

Webship 엔지니어링

Webship 웹 서버: 기본적으로 안전한 설정

Webship는 기본적으로 주요 HTTP 방어, 자원 한도 및 응답 보호 기능을 활성화하면서 선택적 제어 영역은 비공개로 유지하거나 비활성화합니다. 여기에는 기준선과 운영 점검 목록이 있습니다.

# Webship 웹 서버: 기본적으로 안전한 설정

보안 웹 서버는 운영자가 새벽 2시에 또 하나의 설정을 기억하는 것에 의존해서는 안 됩니다. 웹 서버는 보호 기준선에서 시작해야 하며, 안전하지 않은 설정은 거부하고, 민감한 기능을 노출하기 전에 신중한 선택을 요구해야 합니다.

그것이 Webship 뒤에 있는 모델입니다. 기본 구성은 주요 요청 및 응답 방어를 켜고, 공격자가 사용할 수 있는 자원을 제한하며, 선택적 제어면은 비활성화된 상태로 둡니다. 실제 애플리케이션에서는 이러한 기본값을 조정할 수 있지만, 첫 번째 요청이 도착하기 전에 모든 보호 기능을 발견할 필요는 없습니다.

기본적으로 안전하다고 해서 문맥 없이 안전하다는 의미는 아닙니다. 인증서, 애플리케이션 권한, 네트워크 정책, 비밀 정보, 사고 대응은 여전히 운영자의 책임입니다. Webship의 역할은 안전한 출발점을 분명히 하고 실수로 약화되는 것을 더 어렵게 만드는 것입니다.

시작 시 활성화되는 보호 기능

Webship는 기본 구성에서 여섯 개의 레이어를 활성화합니다:

| 레이어 | 기본 동작 | 무엇을 줄이는가 | | --- | --- | --- | | 도트 파일 보호 | 도트로 시작하는 정적 경로 세그먼트 거부 | 환경 파일, 저장소 메타데이터 및 로컬 구성의 우발적 노출 | | 웹 애플리케이션 방화벽 | 알려진 공격 패턴 차단 | SQL 인젝션, 크로스 사이트 스크립팅, 트래버설, 민감 경로 탐색, 명령어 인젝션, 헤더 스머글링, 지원되지 않는 요청 인코딩 | | DDoS 제어 | 제한된 클라이언트 상태로 정상 모드에서 실행 | 요청 폭주, 무제한 추적 및 피할 수 있는 자원 고갈 | | 봇 챌린지 | 서명된 챌린지 쿠키 사용 | 저비용 자동화 남용 및 반복 스캐닝 | | 응답 보안 헤더 | 제한적인 브라우저 정책 추가 | MIME 혼동, 프레이밍, 리퍼러 누출, 위험한 브라우저 기능, 광범위한 콘텐츠 로딩 | | API Shield | API 계약이 정의되면 블록 모드를 사용하고 알 수 없는 경로를 거부함 | 섀도우 엔드포인트, 의도하지 않은 메서드, 예상치 못한 콘텐츠 유형, 누락된 인증 요구 사항 |

기본 WAF는 또한 검사 대상에 대해 엄격한 한계를 설정합니다: 요청 헤더 32KiB, 경로 2,048바이트, 요청 본문 1MiB입니다. 이는 임의의 성능 스위치가 아니라 보안 제한입니다. 애플리케이션에서 실제로 더 큰 요청이 필요하다면, 해당 애플리케이션에 대한 관련 제한을 높이고 검사 전체를 비활성화하지 말고 결과를 테스트하십시오.

DDoS 보호는 분당 600개의 요청에서 정상 모드로 시작하며, 클라이언트 키당 100개의 버스트 허용량이 있습니다. 클라이언트 상태 테이블은 65,536개의 항목으로 제한됩니다. 이 값들은 기준값일 뿐, 보편적인 트래픽 모델은 아닙니다: 공개 API, 다운로드 서비스 및 내부 관리 패널은 동일한 애플리케이션별 제한을 공유하면 안 됩니다.

브라우저 보호 기능은 기본 사항의 일부입니다

Webship의 응답 헤더 정책은 애플리케이션이 자체 헤더를 추가하는 것을 잊었더라도 활성화됩니다. 기본값에는 다음이 포함됩니다:

  • X-Content-Type-Options: nosniff;
  • 프레임 거부 정책;
  • 참조자 정책: no-referrer;
  • 하위 도메인을 포함하여 1년 동안 엄격한 전송 보안;
  • Content-Security-Policy가 동일 출처 콘텐츠로 제한되며, 프레이밍 및 기본 URI 제한이 적용됩니다;
  • 권한 정책에서 위치 정보, 마이크, 카메라 접근을 비활성화합니다.

이 기본값들은 의도적으로 제한적입니다. 서브도메인이 완전히 HTTPS 준비가 되어 있지 않은 도메인에 적용하기 전에 HSTS를 검토하세요. 애플리케이션이 다른 출처에서 스크립트, 스타일, 폰트, 이미지 또는 연결을 로드하기 전에 Content-Security-Policy를 검토하세요. 안전한 기본값은 배포 시 눈에 띄게 실패해야 하며, 운영 환경에서 조용히 약화되어서는 안 됩니다.

선택적 표면은 닫힌 상태로 유지됩니다

Webship은 바이너리에 포함되어 있다고 해서 모든 기능을 노출하지 않습니다. 리버스 프록시, WebTransport, 관측 엔드포인트, 자동 TLS, 응답 출처, 그리고 MCP 제어 엔드포인트는 기본적으로 비활성화되어 있습니다.

MCP 엔드포인트는 활성화되면 루프백 범위로 설정되며 명시적인 보안 구성이 필요합니다. 메트릭 및 통계는 의도적으로 활성화해야 하는 계측이 필요합니다. 자동 인증서 관리는 운영자가 ACME 디렉토리, 연락처, 저장소 및 서비스 약관 수락을 선택해야 합니다. 이는 운영 기능이 예상치 못한 네트워크 표면이 되는 것을 방지합니다.

기본 리스너는 127.0.0.1에 바인딩됩니다. 운영자는 명시적으로 공개 주소를 선택해야 합니다. 그 단일 선택은 방화벽 규칙, 서비스 권한, TLS 신원, 배포 토폴로지에 대한 유용한 검토 지점을 만듭니다.

리버스 프록시는 신뢰 경계를 유지합니다

리버스 프록시가 활성화되면 TLS 패스스루는 기본값으로 유지됩니다. Webship는 애플리케이션 평문이나 활성 세션 키를 소유하지 않고 암호화된 트래픽을 전달합니다. 원본은 여전히 TLS 및 협상된 프로토콜에 대한 책임을 집니다.

TLS 종료는 Webship가 HTTP 요청을 검사하거나, 경로별로 라우팅하거나, WAF 및 API 정책을 적용하거나, 헤더를 재작성하거나, 응답을 캐시해야 할 때만 활성화하십시오. 종료 자체가 본질적으로 덜 안전한 것은 아니며, 신뢰 경계를 이동시키는 것입니다. 중요한 결정은 어느 기계가 평문을 볼 수 있는지와 그 이유입니다.

패스스루(pass-through)에도 기능적 한계가 있습니다. TCP 라우팅은 HTTP 요청이 암호화되어 있기 때문에 ClientHello SNI를 기반으로 합니다. HTTP/3 패스스루는 라우트가 하나의 UDP 오리진을 공유하도록 요구합니다. 엣지에서 콘텐츠 인식 보안이 필요하다면, 그곳에서 TLS를 종료하고 엣지에서 오리진까지의 구간을 별도로 보호하십시오.

검토할 수 있는 생산 기준

다음 발췌문은 생략에 의존하지 않고 중요한 기본값을 명시적으로 보여줍니다:

listen = "0.0.0.0:443"
deny_dotfiles = true

[tls]
unknown_sni = "reject"

[ddos]
enabled = true
mode = "normal"
requests_per_minute = 600
burst = 100
block_seconds = 60
max_tracked_clients = 65536

[security]
enabled = true
rate_limit_max_entries = 65536

[security.waf]
enabled = true
mode = "block"
sqli = true
xss = true
traversal = true
sensitive_paths = true
header_abuse = true
max_header_bytes = 32768
max_path_bytes = 2048
max_body_bytes = 1048576

[security.response_headers]
enabled = true
nosniff = true
frame_deny = true
referrer_no_referrer = true
hsts = "max-age=31536000; includeSubDomains"
content_security_policy = "default-src 'self'; frame-ancestors 'none'; base-uri 'self'"
permissions_policy = "geolocation=(), microphone=(), camera=()"

다중 도메인 리스너에서 unknown_sni = "reject"는 인식되지 않는 호스트명이 리스너의 기본 인증서를 받는 것을 방지합니다. Webship의 자동 TLS 리스너는 인증서가 존재할 때까지 이미 알 수 없는 이름을 거부합니다.

유효성 검사는 보안 통제입니다

Webship은(는) 리스너를 바인딩하기 전에 구성을 검증합니다. 알 수 없는 필드, 잘못된 제한, 불완전한 식별, 충돌하는 리스너 및 지원되지 않는 프로토콜 조합은 특정 오류와 함께 시작 실패를 발생시킵니다. 동일한 검증이 라이브 구성 설치 전에 실행됩니다. 재로드가 실패하면 현재 구성이 유지됩니다.

인증된 MCP 구성 경로는 또 다른 보호 장치를 추가합니다: 활성 WAF, DDoS 계층, API Shield, 봇 챌린지, 엣지 인증 정책 또는 응답 헤더 계층을 비활성화하는 라이브 변경을 거부합니다. 버전 검사는 한 관리자가 최신 구성 스냅샷을 덮어쓰지 못하도록 방지합니다. 프로세스에 바인딩된 설정은 부분적인 라이브 변경이 성공한 척 하지 않고 여전히 재시작이 필요합니다.

이것은 유용한 구분입니다. 안전한 기본값은 새로운 배포를 보호합니다. 트랜잭션 검증과 보호된 업데이트는 운영 중인 배포를 보호합니다.

어떤 운영자가 여전히 결정해야 하는지

인터넷에 Webship를 공개하기 전에:

  1. 신뢰할 수 있는 TLS 아이덴티티를 구성하고 개인 키를 보호하십시오.
  2. 리스너 토폴로지에 대한 알 수 없는 SNI 처리를 설정합니다.
  3. HSTS와 콘텐츠 보안 정책이 모든 애플리케이션과 서브도메인에 일치하는지 확인하십시오.
  4. API Shield 엔드포인트, 허용된 메서드, 콘텐츠 유형 및 인증 요구 사항을 정의합니다.
  5. 전역 기준에만 의존하지 말고 경로별 요율 제한을 추가하세요.
  6. 보호된 호스트나 경로에 대해 엣지 인증을 활성화하고 단기 토큰을 사용하세요.
  7. MCP와 관측 리스너를 비공개로 유지하고, 인증하며, 공개 트래픽과 분리하세요.
  8. 가능한 경우, 전용 비권한 계정, 읽기 전용 애플리케이션 루트와 필요한 운영 체제 기능만 사용하여 Webship를 실행하십시오.
  9. 배포 전에 구성을 검증한 다음, 카나리 환경에서 차단된 트래픽과 허용된 트래픽을 테스트합니다.
  10. 보안 감사 이벤트를 모니터링하고 정상 모드에서 공격받는 모드 또는 잠금 모드로 전환하는 연습을 하십시오.

더 안전한 기본값은 주장이 아니라 시작이다

어떤 웹 서버도 어떤 사용자가 청구서를 보게 하는지, 어떤 출처가 API를 호출할지, 비즈니스 엔드포인트가 얼마나 빨리 요청을 받아야 하는지 결정할 수 없습니다. 이러한 제어는 애플리케이션 지식을 필요로 합니다.

Webship는 하위 계층을 제공합니다: 제한된 파서, 엄격한 구성, 방어적인 응답 헤더, 요청 검사, 남용 통제, 그리고 폐쇄된 선택적 인터페이스. 그 결과가 '보안 해결'은 아닙니다. 그것은 서버를 설치하는 것과 책임감 있게 운영하는 것 사이의 간극을 줄여줍니다.

프로덕션 배포 전에 전체 Webship 문서를 검토하십시오. 구성 스키마와 실행 중인 바이너리가 운영 중인 정확한 버전에 대한 권위 있는 출처로 남아 있습니다.