인터넷에서 개인정보 보호 지향 애플리케이션이나 서비스를 실행하는 경우, 사용자의 개인정보를 확실하게 보호할 수 있는 옵션이 제한되어 있습니다. 로그와 데이터 수집을 최소화할 수는 있지만, 그러한 경우에도 네트워크 수준에서 모든 HTTP 요청이 어딘가에서 발생해야 합니다. 사용자의 IP 주소, TLS 지문 등 HTTP 요청에 따라 생성된 정보는 특히 애플리케이션 데이터와 결합될 때 중요할 수 있습니다.
사용자의 개인정보 보호를 의미 있게 개선하려면 클라이언트 장치에서 애플리케이션 로직을 실행하는 서버로 HTTP 요청이 전송되는 방식을 변경해야 합니다. 바로 이러한 필요성 때문에 클라이언트와 애플리케이션 서버 간에 암호화된 HTTP 요청과 응답을 중계하는 서비스인 Privacy Gateway가 개발되었습니다. Privacy Gateway를 사용하면 Cloudflare에서는 요청의 출처는 알지만, 요청에 포함된 내용은 알 수 없으며, 애플리케이션에서는 포함된 내용은 볼 수 있지만, 요청의 출처는 알 수 없습니다. Cloudflare에서도 애플리케이션 서버에서도 모두 전체 상황을 파악할 수 없으므로 최종 사용자의 개인정보 보호가 개선됩니다.
Cloudflare에서는 최근 대표적인 여성 건강 앱인 Flo Health Inc.의 Anonymous Mode 출시를 위해 Privacy Gateway를 배포했습니다. Privacy Gateway를 이용하면 Anonymous Mode 사용자가 요청하는 모든 데이터가 앱 사용자와 Flo 간에 암호화되므로 Flo에서는 해당 사용자의 IP 주소를 볼 수 없고, Cloudflare에서도 해당 요청 데이터의 내용을 볼 수 없습니다.
Privacy Gateway를 채택하면 개인정보 보호에 중요한 다른 여러 애플리케이션을 사용할 수 있습니다.
브라우저 개발자는 설치된 확장 프로그램, 사용자가 변경했을 수 있는 기본값 등 개인정보를 존중하는 방식으로 사용자 텔레메트리를 수집하고 아울러 해당 데이터에서 개인 식별자(IP 주소)일 가능성이 있는 항목을 제거할 수 있습니다.
사용자는 사이트에서 자신의 IP 주소 및/또는 위치가 추적되리라는 우려를 하지 않고 의료 사이트를 방문하여 코로나19에 노출되었음을 신고할 수 있습니다.
DNS 확인자는 요청을 한 사람과 방문 중인 웹 사이트를 연결하지 않고도 DNS 쿼리를 제공할 수 있으며, 우리는 모호한 DNS 패턴으로 이를 구현했습니다.Privacy Gateway는 새롭게 떠오르는 IETF인 Oblivious HTTP(OHTTP) 표준을 기반으로 하며 표준 하이브리드 공개 키 암호화를 기반으로 구축되었습니다.
어떻게 작동하나요?
기본적인 프록시 서비스를 넘어선 Oblivious HTTP 표준의 주요 혁신은 이러한 메시지가 _애플리케이션의 서버_로 암호화되어 Privacy Gateway에서는 각 메시지의 출처와 목적지 외에는 애플리케이션 데이터에 대해 아무것도 알 수 없다는 점입니다.
Privacy Gateway를 사용하면 특히 강력한 개인정보 보호 요구 사항이 있는 애플리케이션 개발자와 플랫폼이 네트워크 전체에 걸쳐 메시지의 출처와 목적지를 난독화하는 접근 방식인 "Mixnet"과 매우 유사한 것을 구축할 수 있습니다. 이를 위해 Privacy Gateway는 다음과 같은 세 가지 주요 구성 요소로 이루어져 있습니다.
클라이언트: 사용자 장치, 또는 요청을 Privacy Gateway로 전달하도록 구성된 모든 클라이언트.
Privacy Gateway: Cloudflare 에서 운영하는 서비스로, 클라이언트와 게이트웨이 간의 요청을 내부 내용을 관찰할 수 없도록 중계하도록 설계되었습니다.
애플리케이션 서버: 클라이언트의 요청을 해독하고 응답을 다시 암호화하는 것을 담당하는 원본 또는 애플리케이션 웹 서버.
요청 데이터를 봉투의 내용물(편지)로, IP 주소와 요청 메타데이터를 봉투 표면의 주소로 상상한다면, Privacy Gateway를 사용하여 Cloudflare에서는 봉투의 주소를 확인하고 내부 내용을 볼 수 없어도 안전하게 목적지까지 전달할 수 있습니다.
Privacy Gateway를 사용하는 Oblivious HTTP 트랜잭션
데이터 흐름을 조금 더 자세히 설명하면 다음과 같습니다.
클라이언트는 애플리케이션 서버의 공개 키를 사용하여 HTTP 요청을 캡슐화하여 HTTPS 연결을 통해 Privacy Gateway로 전송합니다.
Privacy Gateway에서는 애플리케이션 서버와의 별도의 HTTPS 연결을 통해 요청을 서버로 전달합니다.
애플리케이션 서버에서는 요청을 캡슐화 해제하여 응답을 생성할 수 있는 대상 서버로 전달합니다.
애플리케이션 서버는 캡슐화된 응답을 Privacy Gateway에 반환하고, Privacy Gateway는 그 결과를 클라이언트에게 전달합니다.프로토콜에 명시된 대로 클라이언트에서 서버로의 요청은 공개 키 암호화를 위한 최신 기술 표준인 HPKE를 사용하여 암호화됩니다(자세한 정보는 여기에서 알아보세요). 우리는 OHTTP의 HPKE 사용이 안전한지 확인하기 위해 프로토콜에 대한 공식 분석을 수행하여 추가 조치를 취했으며, 향후 몇 주 내에 더 심층적인 분석 결과를 발표할 예정입니다.
Privacy Gateway가 최종 사용자 개인정보 보호를 개선하는 방법
이 상호작용으로 두 가지 유형의 개인정보 보호가 제공되며, 당사에서는 이를 비공식적으로 요청 개인정보 보호 및 _클라이언트 개인정보 보호_라고 부릅니다.
요청 개인정보 보호란 애플리케이션 서버가 IP 주소, 지리적 위치, TLS, HTTPS 지문 등 HTTP 요청에 의해 공개될 수 있는 정보를 학습하지 않는 것을 의미합니다. Privacy Gateway에서는 자체와 애플리케이션 서버 간에 별도의 HTTPS 연결을 사용하므로 애플리케이션 서버에 공개되는 모든 요청별 정보는 클라이언트의 정보가 아닌 Privacy Gateway의 정보를 나타냅니다. 그렇지만, 개발자는 요청 내용에 개인 식별 정보가 포함되지 않도록 주의해야 합니다. 예를 들어, 캡슐화 해제된 요청에 사용자의 이메일, 전화번호, 신용카드 정보 등의 정보가 포함되어 있는 경우 Privacy Gateway는 개인정보 보호를 의미 있게 개선하지 못합니다.
클라이언트 개인정보 보호는 더 강력한 개념입니다. Cloudflare와 애플리케이션 서버는 개별 사용자의 데이터를 공유를 계획하지 않으므로 서버의 관점에서는 각 개별 트랜잭션이 Privacy Gateway 막후에 있는 알 수 없는 클라이언트에서 발생한 것으로 간주됩니다. 다시 말하면, 올바르게 구성된 Privacy Gateway 배포는 애플리케이션에서 어떤 두 요청을 동일한 클라이언트에 연결할 수 없다는 것을 의미합니다. 특히 Privacy Gateway를 사용하면 개인정보 보호가 더욱 강화됩니다. Privacy Gateway를 사용하는 최종 사용자가 한 명뿐인 경우에는 요청 개인정보 보호만 제공됩니다(클라이언트 IP 주소가 Gateway로부터 숨겨져 있으므로). 각 요청이 동일한 단일 클라이언트에 해당한다는 것을 서버에서 알 수 있으므로 Privacy Gateway에서는 클라이언트 개인정보를 제공하지 않습니다. 클라이언트 개인정보 보호를 위해서는 시스템 사용자가 많아야 하므로 애플리케이션 서버에서 이를 판단할 수 없습니다.
요청 개인정보 보호와 클라이언트 개인정보 보호를 더 잘 이해하려면 클라이언트와 서버 간의 다음 HTTP 요청을 고려하세요.
클라이언트 익명성 세트가 크기 1인 일반 HTTP 구성
클라이언트에서 서버(또는 OHTTP 용어로는 "Gateway")에 직접 연결하면 서버에서는 IP 주소, 사용된 TLS 암호, 해당 IP 주소를 기반으로 한 위치 데이터 등 클라이언트에 관한 정보를 볼 수 있습니다.
여기에는 최종 사용자에게 고유할 수 있는 중요한 정보가 많이 있습니다. 다시 말하자면, 이 연결에서는 요청 개인정보 보호나 클라이언트 개인정보 보호가 제공되지 않습니다.
- ipAddress: 192.0.2.33 # the client’s real IP address
- ASN: 7922
- AS Organization: Comcast Cable
- tlsCipher: AEAD-CHACHA20-POLY1305-SHA256 # potentially unique
- tlsVersion: TLSv1.3
- Country: US
- Region: California
- City: Campbell
Privacy Gateway를 사용할 경우 클라이언트가 애플리케이션 서버 자체에 직접 연결되지 않습니다. 대신 Privacy Gateway에 연결되고, 이 게이트웨이는 다시 서버에 연결됩니다. 다시 말하자면, 서버는 클라이언트의 개별 연결이 아닌 Privacy Gateway의 연결만 관찰하므로 다른 보기가 생성됩니다.
클라이언트 익명성 세트가 크기 k로 설정된 Privacy Gateway 구성
- ipAddress: 104.16.5.5 # a Cloudflare IP
- ASN: 13335
- AS Organization: Cloudflare
- tlsCipher: ECDHE-ECDSA-AES128-GCM-SHA256 # shared across several clients
- tlsVersion: TLSv1.3
- Country: US
- Region: California
- City: Los Angeles
이는 요청 개인정보 보호입니다. 클라이언트의 위치 및 신원에 대한 모든 정보는 애플리케이션 서버에서 숨겨집니다. 또한 애플리케이션 데이터에 대한 모든 세부 정보는 Privacy Gateway에서 숨겨집니다. DNS와 같은 중요한 애플리케이션 및 프로토콜의 경우 이 메타데이터를 애플리케이션 데이터와 분리하여 보관하는 것이 최종 사용자의 개인정보 보호를 개선하는 데 있어 중요한 단계입니다.
또한 애플리케이션에서는 개별 요청에서 중요한 고객별 정보가 노출되지 않도록 주의해야 합니다. Privacy Gateway는 평문 애플리케이션 데이터를 관찰할 수 없으므로 애플리케이션이 요청 본문에서 이메일 주소, 성명 등 식별 정보를 포함하여 전송하지 않는다고 보장할 수 없습니다. 요청에 사용자 식별 정보를 공개하는 애플리케이션은 클라이언트 개인정보는 침해할 수 있지만, 요청 개인정보는 침해하지 않습니다. 따라서 당사의 전체 애플리케이션 수준 Privacy Proxy 제품과 달리 Privacy Gateway는 임의의 애플리케이션 및 트래픽에 대한 일반적인 프록시 기반 프로토콜로 사용하기 위한 것이 아닙니다. Privacy Gateway는 앞서 설명한 바와 같이 DNS(Oblivious DNS-over-HTTPS), 텔레메트리 데이터, 일반 API 호출 등 중요한 애플리케이션을 위한 특수 목적의 프로토콜로 사용됩니다.
애플리케이션에 Privacy Gateway 통합
Privacy Gateway와 통합하려면 애플리케이션에서 OHTTP 프로토콜의 클라이언트 및 서버 측을 구현해야 합니다. 여기에는 어떤 것들이 수반되는지 살펴보겠습니다.
서버 통합
프로토콜의 서버 측 부분은 다음과 같은 두 가지 기본 작업을 담당합니다.
요청 캡슐화를 위한 공개 키 게시.
캡슐화된 클라이언트 요청을 해독하고, 결과 요청을 처리하며, 해당 응답을 암호화.
키 구성이라고 하는 공개 캡슐화 키는 키 식별자(서버에서 로테이션을 위해 한 번에 여러 키를 지원할 수 있도록), 암호화 및 해독을 위한 암호화 알고리즘 식별자, 공개 키로 구성됩니다.
클라이언트에서는 요청을 생성하기 위해 이 공개 키를 필요로 하며, 이를 생성하는 방법에는 여러 가지가 있습니다. 서버는 공개 키를 수정한 다음 이를 애플리케이션에 적용할 수 있지만 키를 로테이션 하려면 소프트웨어 업데이트가 필요합니다. 아니면, 클라이언트에서 다른 방법으로 공개 키를 검색할 수도 있습니다. 많은 검색 메커니즘이 존재하며 위협 모델에 따라 다릅니다(자세한 내용은 이 문서를 참조하세요). 우선, 간단한 접근 방식은 클라이언트에서 API를 통해 서버에서 직접 공개 키를 가져오도록 하는 것입니다. 아래에는 우리의 오픈 소스 OHTTP 서버에서 제공하는 API의 일부가 나와 있습니다.
HPKE Symmetric Algorithms {
HPKE KDF ID (16),
HPKE AEAD ID (16),
}
OHTTP Key Config {
Key Identifier (8),
HPKE KEM ID (16),
HPKE Public Key (Npk * 8),
HPKE Symmetric Algorithms Length (16),
HPKE Symmetric Algorithms (32..262140),
}
공개 키 생성 및 배포가 해결되면, 다음으로 서버에서는 클라이언트의 캡슐화된 요청을 처리해야 합니다. 서버에서는 각 요청에 대해 요청을 해독하고 평문 텍스트를 해결할 수 있는 해당 HTTP 요청으로 변환한 다음 결과 응답을 다시 암호화하여 클라이언트로 전송해야 합니다.
func (s *GatewayResource) configHandler(w http.ResponseWriter, r *http.Request) {
config, err := s.Gateway.Config(s.keyID)
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Write(config.Marshal())
}
오픈 소스 OHTTP 라이브러리에서는 일반적으로 요청 해독 및 응답 암호화 기능이 제공되는 반면, 바이너리 HTTP에서 HTTP 요청으로의 일반 텍스트 변환은 별도로 처리됩니다. 예를 들어, 당사의 오픈 소스 서버에서는 이 번역을 다른 라이브러리에 위임하는데, 이 라이브러리는 Go HTTP 요청이 메모리에서 표현되는 방식에 따라 다릅니다. 특히 일반 텍스트 요청을 Go HTTP 요청으로 변환하는 기능은 다음과 같은 서명을 가진 기능으로 수행됩니다.
반대로 Go HTTP 응답을 일반 텍스트 바이너리 HTTP 응답 메시지로 변환하는 것은 다음 서명을 가진 기능을 사용하여 수행됩니다.
func UnmarshalBinaryRequest(data []byte) (*http.Request, error) {
...
}
OHTTP 서버 지원을 구현하는 데 사용할 수 있는 몇 가지 오픈 소스 라이브러리가 있지만, 우리는 이 모든 것을 오픈 소스 서버 구현(여기에서 확인 가능)에 패키지로 묶어 놓았습니다. 여기에는 쉽게 시작할 수 있도록 빌드, 테스트, 배포에 대한 지침이 포함되어 있습니다.
type BinaryResponse http.Response
func (r *BinaryResponse) Marshal() ([]byte, error) {
...
}
클라이언트 통합
당연히, OHTTP의 클라이언트 측 동작은 서버의 동작을 반영합니다. 특히 클라이언트에서는 반드시 다음과 같아야 합니다.
서버 공개 키를 검색하거나 획득합니다.
HTTP 요청을 인코딩 및 암호화하여 Privacy Gateway로 전송하고 HTTP 응답을 해독 및 디코딩합니다.
서버 공개 키 검색은 서버가 선택한 배포 모델에 따라 다릅니다. 예를 들어 공개 키가 API를 통해 제공되는 경우 클라이언트는 단순히 공개 키를 직접 가져올 수 있습니다.
인코딩, 암호화, 해독, 디코딩은 사용 가능한 경우 OHTTP 라이브러리에서 처리하는 것이 가장 좋습니다. 이러한 기능을 사용할 수 있으므로 클라이언트 지원을 구축하는 것은 매우 간단합니다. 위에 링크된 라이브러리 기능을 사용하는 간단한 예제 Go 클라이언트는 다음과 같습니다.
$ curl https://server.example/ohttp-configs > config.bin
기존 애플리케이션이 있는 경우 이와 같은 독립형 클라이언트는 그다지 유용하지 않을 수 있습니다. 기존 애플리케이션과의 통합을 지원하기 위해 당사에서는 iOS 및 macOS 앱과 호환되는 샘플 OHTTP 클라이언트 라이브러리를 마련했습니다. 또한, 클라이언트 또는 서버 측에서 쉽게 통합하는 데 도움이 되는 언어 또는 플랫폼 지원이 필요한 경우 당사에 알려주시기 바랍니다!
configEnc := ... // encoded public key
config, err := ohttp.UnmarshalPublicConfig(configEnc)
if err != nil {
return err
}
request, err := http.NewRequest(http.MethodGet, "https://test.example/index.html", nil)
if err != nil {
return err
}
binaryRequest := ohttp.BinaryRequest(*request)
encodedRequest, err := binaryRequest.Marshal()
if err != nil {
return err
}
ohttpClient := ohttp.NewDefaultClient(config)
encapsulatedReq, reqContext, err := ohttpClient.EncapsulateRequest(encodedRequest)
relayRequest, err := http.NewRequest(http.MethodPost, "https://relay.example", bytes.NewReader(encapsulatedReq.Marshal()))
if err != nil {
return err
}
relayRequest.Header.Set("Content-Type", "message/ohttp-req")
client := http.Client{}
relayResponse, err := client.Do(relayRequest)
if err != nil {
return err
}
bodyBytes, err := ioutil.ReadAll(relayResponse.Body)
if err != nil {
return err
}
encapsulatedResp, err := ohttp.UnmarshalEncapsulatedResponse(bodyBytes)
if err != nil {
return err
}
receivedResp, err := reqContext.DecapsulateResponse(encapsulatedResp)
if err != nil {
return err
}
response, err := ohttp.UnmarshalBinaryResponse(receivedResp)
if err != nil {
return err
}
fmt.Println(response)
관심이 있으신가요?
Privacy Gateway는 현재 일부 개인정보 보호 지향 기업 및 파트너가 이용할 수 있는 초기 액세스 버전입니다. 관심이 있으시면 문의해 주세요.