botd 트러블 슈팅에서 req.header의 Sec-Fetch-Mode가 cors일 때만 봇 여부를 판별하도록 했었다.
평소 요청을 보내고 받은 응답만 뜯어볼 생각을 했지 요청 헤더에 대해서는 뜯어본 적도, 생각해본 적도 없었는데 위 문제를 해결하면서 링크를 통해 한 번 짚고 넘어가야 할 필요성을 느꼈다.
A fetch metadata request header is an HTTP request header that provides additional information about the context from which the request originated. This allows the server to make decisions about whether a request should be allowed based on where the request came from and how the resource will be used.
fetch metadata request header란 요청이 시작된 context에 대한 추가적인 정보를 제공하는 HTTP request header이다.
fetch metadata request header를 통해 서버는 요청이 어디에서 왔는지, 자원을 어떻게 사용할 것인지를 알 수 있고 이에 따라 요청의 허용 여부를 결정할 수 있다.
With this information a server can implement a resource isolation policy, allowing external sites to request only those resources that are intended for sharing, and that are used appropriately.
This approach can help mitigate common cross-site web vulnerabilities such as CSRF, Cross-site Script Inclusion('XSSI'), timing attacks, and cross-origin information leaks.
이 정보를 사용하여 서버는 resource isolation policy를 구현할 수 있어 외부 사이트에서 공유용으로 적절하게 사용되는 resource만 요청할 수 있다.
이러한 접근 방식은 CSRF, Cross-site Script Inclusion('XSSI'), timing attacks, cross-origin information leaks과 같은 일반적인 사이트 간의 웹 취약성을 완화하는데 도움이 될 수 있다.
These headers are prefixed with Sec-, and hence have forbidden header names. As such, they cannot be modified from JavaScript.
fetch metadata request header들은 Sec-
라는 이름으로 시작되며 JavaScript에서 수정할 수 없다.
=> Sec-Fetch-Site
, Sec-Fetch-Mode
, Sec-Fetch-User
, Sec-Fetch-Dest
The Sec-Fetch-Site fetch metadata request header indicates the relationship between a request initiator's origin and the origin of the requested resource.
Sec-Fetch-Site
는 출처(origin)와 요청된 resource 사이의 관계를 나타낸다.
In other words, this header tells a server whether a request for a resource is coming from the same origin, the same site, a different site, or is a "user initiated" request. The server can then use this information to decide if the request should be allowed.
다시 말하자면, Sec-Fetch-Site
헤더는 resource에 대한 요청이 동일한 출처, 동일한 사이트, 다른 사이트에서 오는지 아니면 사용자가 시작한 요청인지의 여부를 서버에 알려준다.
서버는 이 정보를 활용해 요청을 허용할 것인지 결정한다.
Same-origin requests would usually be allowed by default, but what happens for requests from other origins may further depend on what resource is being requested, or information in other Fetch metadata request headers. By default, requests that are not accepted should be rejected with a 403 response code.
일반적으로 동일 출처 요청은 기본적으로 허용되지만 다른 출처으로부터의 요청은 요청 중인 resource나 다른 Fetch metadata request headers의 정보에 따라 허용 여부가 달라질 수 있다.
기본적으로 허용되지 않은 요청은 403 응답 코드와 함께 거부된다.
Sec-Fetch-Site: cross-site
Sec-Fetch-Site: same-origin
Sec-Fetch-Site: same-site
Sec-Fetch-Site: none
cross-site
요청 개시자와 resource를 호스팅하는 서버가 다른 사이트일 경우.
(ex. "potentially-evil.com"에서 보낸 요청이 "example.com"의 resource에 접근할 경우)
same-origin
요청 개시자와 resource를 호스팅하는 서버가 동일한 출처(origin)를 가질 경우.
same-site
요청 개시자와 resource를 호스팅하는 서버가 동일한 scheme, 도메인/서브도메인을 가지지만 port가 다른 경우.
none
요청이 사용자로부터 시작되었을 경우.
(ex. 주소창에 URL 입력, 브라우저 창에 파일 끌어다 놓기 등.)
The Sec-Fetch-Mode fetch metadata request header indicates the mode of the request.
Broadly speaking, this allows a server to distinguish between: requests originating from a user navigating between HTML pages, and requests to load images and other resources. For example, this header would contain navigate for top level navigation requests, while no-cors is used for loading an image.
Sec-Fetch-Mode
는 요청 모드를 나타낸다.
일반적으로 Sec-Fetch-Mode
는 서버가 HTML 페이지를 이동하는 사용자의 요청과 이미지 및 기타 자원의 요청을 구별할 수 있도록 한다.
예를 들어, 최상단의 navigation 요청 시에는 Sec-Fetch-Mode
가 navigate
이지만 이미지 로드시에는 no-cors
이다.
Sec-Fetch-Mode: cors
Sec-Fetch-Mode: navigate
Sec-Fetch-Mode: no-cors
Sec-Fetch-Mode: same-origin
Sec-Fetch-Mode: websocket
cors
CORS protocol 요청이다.
navigate
HTML document 사이를 이동할 때 사용된다.
no-cors
no-cors 요청이다.
same-origin
요청 중인 resource와 동일한 출처이다.
websocket
websocket 연결을 설정하기 위한 요청이다.
The Sec-Fetch-Dest fetch metadata request header indicates the request's destination. That is the initiator of the original fetch request, which is where (and how) the fetched data will be used.
Sec-Fetch-Dest
는 요청의 대상을 나타낸다.
이는 fetch 요청 개시자로, 가져온 data가 사용되는 곳이다.
This allows servers determine whether to service a request based on whether it is appropriate for how it is expected to be used. For example, a request with an audio destination should request audio data, not some other type of resource (for example, a document that includes sensitive user information).
서버는 요청이 사용되는 방식이 적절한지에 따라 요청의 허용 여부를 결정할 수 있다.
예를 들어, audio를 사용하는 곳에서 온 요청은 다른 타입의 정보가 아닌 audio data를 요청해야 한다.
Sec-Fetch-Dest: audio
Sec-Fetch-Dest: audioworklet
Sec-Fetch-Dest: document
Sec-Fetch-Dest: embed
Sec-Fetch-Dest: empty
Sec-Fetch-Dest: font
Sec-Fetch-Dest: frame
Sec-Fetch-Dest: iframe
Sec-Fetch-Dest: image
...
The Sec-Fetch-User fetch metadata request header is only sent for requests initiated by user activation, and its value will always be
?1
.
A server can use this header to identify whether a navigation request from a document, iframe, etc., was originated by the user.
Sec-Fetch-User
는 사용자가 시작한 요청일 때만 보내지며 항상 ?1
이라는 값을 가진다.
서버는 Sec-Fetch-User
를 사용하여 document, iframe 등의 탐색 요청이 사용자로부터 시작된 것인지 식별할 수 있다.
Sec-Fetch-User: ?1
sec-fetch-dest: document,
sec-fetch-mode: navigate,
sec-fetch-site: none,
sec-fetch-user: ?1
botd 트러블 슈팅 당시 제일 먼저 발생하는 요청에 대해 req.header의 Fetch metadata request header는 위와 같았다.
이걸 해석해보자면, 이 요청은 사용자로부터 시작된 요청이고 요청이 시작된 곳은 document이며 목적은 HTML document 사이를 이동하고자(페이지 전환)한다는 뜻이다.