매일 업데이트
2022-11-24 02:04 6 min

Cloudflare 작업자를 사용하여 보안 헤더를 구현하는 방법은 무엇입니까?

이 글은 Cloudflare에서 제공하는 웹사이트에 보안 HTTP 헤더를 설정하는 과정을 상세히 안내합니다. Cloudflare Workers를 활용하여 XSS, 클릭재킹, MIMI 스니핑, 교차 사이트 스크립팅과 같은 다양한 보안 취약점으로부터 웹사이트를 안전하게 보호할 수 있습니다. OWASP(Open Web Application Security Project)는 이러한 보안 헤더 적용을 권장하고 있습니다. 오와스프.

이전에는 Apache, Nginx, IIS 같은 웹 서버에서 헤더를 설정하는 방법을 다루었지만, 이제는 Cloudflare를 사용하는 경우 Cloudflare Workers를 통해 HTTP 응답 헤더를 손쉽게 제어할 수 있습니다. Cloudflare Workers는 JavaScript, C, C++, Rust 등으로 작성된 코드를 서버리스 환경에서 실행할 수 있는 강력한 플랫폼입니다. Cloudflare의 전 세계 200개 이상의 데이터 센터에 배포되어 전역적으로 빠른 속도를 제공합니다.

Cloudflare Workers를 통한 보안 헤더 구현은 매우 간편하고 유연합니다. 특정 하위 도메인이나 URI에만 헤더를 적용하거나, 정규식을 이용하여 더욱 세밀하게 설정할 수 있습니다. 일치하는 패턴을 정의하여 적용 범위를 정할 수 있습니다.

본 예시에서는 Scott Helme의 코드를 기반으로 진행하겠습니다.

시작하기

  • 먼저 Cloudflare에 로그인하고 Workers 대시보드로 이동합니다 (직접 링크).

  • GitHub에서 worker.js 코드를 복사하여 Cloudflare Worker의 스크립트 편집기에 붙여넣습니다.
const securityHeaders = {
    "Content-Security-Policy": "upgrade-insecure-requests",
    "Strict-Transport-Security": "max-age=1000",
    "X-Xss-Protection": "1; mode=block",
    "X-Frame-Options": "DENY",
    "X-Content-Type-Options": "nosniff",
    "Referrer-Policy": "strict-origin-when-cross-origin"
},
sanitiseHeaders = {
    Server: ""
},
removeHeaders = [
    "Public-Key-Pins",
    "X-Powered-By",
    "X-AspNet-Version"
];

async function addHeaders(req) {
    const response = await fetch(req),
        newHeaders = new Headers(response.headers),
        setHeaders = Object.assign({}, securityHeaders, sanitiseHeaders);

    if (newHeaders.has("Content-Type") && !newHeaders.get("Content-Type").includes("text/html")) {
        return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: newHeaders
        });
    }

    Object.keys(setHeaders).forEach(name => newHeaders.set(name, setHeaders[name]));

    removeHeaders.forEach(name => newHeaders.delete(name));

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

addEventListener("fetch", event => event.respondWith(addHeaders(event.request)));

아직 저장하지 마세요. 다음 헤더들은 필요에 따라 조정할 수 있습니다.

  • Content-Security-Policy: 애플리케이션의 정책을 설정해야 하는 경우 여기서 설정할 수 있습니다.

예를 들어, 여러 URL에서 iFrame을 통해 콘텐츠를 가져와야 하는 경우 다음과 같이 frame-ancestors를 사용할 수 있습니다.

"Content-Security-Policy" : "frame-ancestors 'self' gf.dev koreantech.org.com",

위와 같이 설정하면 gf.dev, koreantech.org.com, 그리고 자신의 사이트에서 콘텐츠를 로드할 수 있습니다.

  • X-Frame-Options: iFrame을 사용하여 동일한 사이트 내의 일부 페이지에 콘텐츠를 표시하려면 SAMEORIGIN으로 변경할 수 있습니다.
"X-Frame-Options": "SAMEORIGIN",
  • Server: 여기서 서버 헤더를 삭제하거나 원하는 값으로 변경할 수 있습니다.
"Server" : "koreantech.org Server",
  • RemoveHeaders: 정보 유출 위험을 줄이기 위해 특정 헤더를 제거할 수 있습니다.
let removeHeaders = [
	"Public-Key-Pins",
	"X-Powered-By",
	"X-AspNet-Version",
]
  • 새 헤더 추가: 사용자 정의 헤더가 필요한 경우, securityHeaders 섹션에 추가할 수 있습니다.
let securityHeaders = {
	"Content-Security-Policy" : "frame-ancestors 'self' gf.dev koreantech.org.com",
	"Strict-Transport-Security" : "max-age=1000",
	"X-Xss-Protection" : "1; mode=block",
	"X-Frame-Options" : "SAMEORIGIN",
	"X-Content-Type-Options" : "nosniff",
	"Referrer-Policy" : "strict-origin-when-cross-origin",
    "Custom-Header"  : "Success",
}

필요한 모든 헤더를 구성한 후, Worker 이름을 지정하고 '저장 및 배포' 버튼을 클릭합니다.

이제 Worker가 준비되었습니다. 다음 단계는 헤더를 적용할 웹사이트에 Worker를 연결하는 것입니다.

  • Cloudflare 대시보드에서 해당 웹사이트를 선택합니다.
  • 'Workers' 탭으로 이동하여 '경로 추가'를 클릭합니다.
  • 적용할 URL 패턴을 입력합니다 (정규식 사용 가능).
  • 생성한 Worker를 선택하고 저장합니다.

모든 설정이 완료되었습니다. 이제 웹사이트에 보안 헤더가 적용된 것을 확인할 수 있습니다.

다음은 Chrome 개발자 도구에서 확인한 헤더 정보입니다. HTTP 헤더 테스팅 도구를 활용하여 검증할 수도 있습니다.

Server 헤더가 변경되지 않는 이유는 Cloudflare에서 이를 무시하는 것으로 보입니다.

전체 구현 과정은 약 15분 정도 소요되며, Apache나 Nginx처럼 웹 서버를 재시작하거나 다운타임을 발생시킬 필요가 없습니다. 프로덕션 환경에 적용하기 전에 테스트 환경이나 특정 페이지에 먼저 적용하여 결과를 확인하는 것이 좋습니다.

정말 멋지죠!

코드 제공에 감사드립니다. Scott.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.