Overview

API เกตเวย์ HTTP ของ Google Safe Browsing

หมายเหตุ: เอกสารนี้ยังอยู่ระหว่างการพัฒนา คาดว่าจะมีการปรับปรุงในอนาคตอันใกล้

Safe Browsing Oblivious HTTP Gateway API เป็น API การรักษาความเป็นส่วนตัวที่สร้างต่อยอดโปรโตคอล IETF RFC ชื่อ Oblivious HTTP, RFC 9458

ภาพรวม

Safe Browsing Oblivious HTTP Gateway API เป็นบริการของ Google ที่ช่วยให้แอปพลิเคชันไคลเอ็นต์ตรวจสอบ URL กับรายการทรัพยากรบนเว็บที่ไม่ปลอดภัยของ Google ที่อัปเดตอย่างต่อเนื่องโดยมีการคุ้มครองความเป็นส่วนตัวเพิ่มเติม

ซึ่งทำได้ผ่านโปรโตคอลขนาดเล็กที่เรียกว่า Oblivious HTTP หรือเรียกสั้นๆ ว่า OHTTP ซึ่งเป็นโปรโตคอลแบบไม่เก็บสถานะที่ไคลเอ็นต์ Google Safe Browsing สามารถใช้เพื่อเข้าถึง Google Safe Browsing V5 API เพื่อการปกป้องที่ทรงประสิทธิภาพและเพิ่มการครอบคลุมโดยไม่รบกวนผู้ใช้ ความเป็นส่วนตัว

หมายเหตุ: บริการนี้ไม่สามารถเข้าถึง Google Safe Browsing API เวอร์ชัน 4 ได้

โปรโตคอล HTTP ของ Google Safe Browsing Oblivious

โปรโตคอล RFC

Oblivious HTTP เป็นโปรโตคอลที่ใช้งานง่ายตามที่ระบุไว้ใน RFC 9458 ซึ่งใช้สำหรับการเข้ารหัสและส่งข้อความ HTTP จากไคลเอ็นต์ไปยังเซิร์ฟเวอร์เป้าหมาย ซึ่งจะใช้บริการส่งต่อที่เชื่อถือได้ในลักษณะที่ลดการใช้ข้อมูลเมตาของเซิร์ฟเวอร์เป้าหมาย เช่น ที่อยู่ IP และข้อมูลการเชื่อมต่อสำหรับการระบุไคลเอ็นต์ ทำให้มีความเป็นส่วนตัวและความปลอดภัยนอกเหนือจากโปรโตคอล HTTP/S ธรรมดา โปรโตคอลนี้ใช้ HTTP แบบไบนารีตามที่ระบุไว้ใน RFC 9292 เพื่อเข้ารหัส/ถอดรหัสคำขอ/การตอบกลับ HTTP

ในระดับสูง Relay จะอยู่ระหว่างทรัพยากรของไคลเอ็นต์และเกตเวย์ซึ่งทำหน้าที่เป็นพร็อกซีการรับส่งข้อมูลของไคลเอ็นต์โดยการนำตัวระบุไคลเอ็นต์ทั้งหมดออก ซึ่งรวมถึงแอตทริบิวต์ที่ละเอียดอ่อนด้านความเป็นส่วนตัว เช่น ที่อยู่ IP เพื่อลบข้อมูลระบุคำขอ HTTP ขาเข้าไปยังบริการเกตเวย์ได้อย่างมีประสิทธิภาพ ประโยชน์เพิ่มเติมของ OHTTP คือคำขอทั้งหมดเข้ารหัสจากต้นทางถึงปลายทาง ซึ่งหมายความว่า รีเลย์จะมองไม่เห็นคำค้นหา Google Safe Browsing (นั่นคือแฮชที่ถูกตัดของนิพจน์ URL) โปรดดูที่blogpostสำหรับตัวอย่างการใช้งานใน Chrome

สถาปัตยกรรมโดยรวมของบริการ
รูปที่: ขั้นตอน OHTTP

ลูกค้าสามารถเลือกผู้ให้บริการ Relay ใดก็ได้ (เช่น Fastly) เพื่อผสานรวมกับบริการ รีเลย์ต้องใช้การตรวจสอบสิทธิ์ Oauth 2.0 ที่มีขอบเขตการให้สิทธิ์ต่อไปนี้เพื่อเข้าถึงบริการ


// OAuth Authorization scope: https://www.googleapis.com/auth/3p-relay-safe-browsing
ปลายทาง API
คีย์สาธารณะ OHTTP

ปลายทางนี้จะแสดงการกำหนดค่าคีย์สาธารณะ OHTTP ตามที่ระบุไว้ใน RFC 9458 ซึ่งไคลเอ็นต์จะใช้เพื่อเข้ารหัสคำขอ OHTTP


GET https://safebrowsingohttpgateway.googleapis.com/v1/ohttp/hpkekeyconfig?key=<API key>

คีย์ API ด้านบนไม่จำเป็นจริงๆ เซิร์ฟเวอร์ไม่เปลี่ยนแปลงคีย์สาธารณะ OHTTP ตามคีย์ API ที่ให้มา ไคลเอ็นต์จะตรวจสอบข้อเท็จจริงนี้ได้โดยใช้คีย์ API อื่นที่ถูกต้องเพื่อเข้าถึงปลายทางนี้ หรือไม่ได้ใช้คีย์ API เลย และตรวจสอบว่าการตอบกลับมีคีย์สาธารณะ OHTTP เดียวกันจริง อย่างไรก็ตาม ขอแนะนำให้ใช้คีย์ API เพื่อให้แก้ไขข้อบกพร่องได้ง่ายขึ้น ซึ่งจะช่วยให้ลูกค้าดูสถิติต่างๆ เช่น จำนวนคำขอบน Google Cloud Console ได้ หากไคลเอ็นต์ต้องการระบุคีย์ API โปรดดูเอกสารประกอบนี้เกี่ยวกับวิธีตั้งค่าคีย์ API

ตามที่ระบุไว้ในส่วนคำแนะนำเกี่ยวกับความเป็นส่วนตัว เราขอแนะนำให้ผู้ให้บริการไคลเอ็นต์ตั้งค่าโครงสร้างพื้นฐานของการกระจายคีย์แบบรวมศูนย์เพื่อดึงข้อมูลคีย์จากปลายทางนี้และแจกจ่ายไปยังแอปพลิเคชันไคลเอ็นต์ของตนในภายหลัง เพื่อให้บรรลุเป้าหมายด้านความสอดคล้องที่สำคัญ

มีการหมุนเวียนคีย์ในเซิร์ฟเวอร์เป็นประจำตามคำแนะนำในการจัดการคีย์ ไคลเอ็นต์ควรรีเฟรชคีย์ กล่าวคือ ให้ดึงข้อมูลและอัปเดตสำเนาคีย์ในเครื่องเป็นประจำเพื่อหลีกเลี่ยงการถอดรหัสไม่สำเร็จ

ไคลเอ็นต์ควรรีเฟรช (ดึงข้อมูลและอัปเดต) คีย์สาธารณะวันละครั้ง หากใช้กลไกการจัดจำหน่ายแบบรวมศูนย์ กลไกนี้ควรดึงข้อมูลและแจกจ่ายคีย์วันละครั้ง

คำขอที่เข้ารหัส OHTTP

ปลายทางนี้จะแสดงคำขอ OHTTP ที่รวมอยู่ในเนื้อหา HTTP ของคำขอ POST โดยทำการถอดรหัสคำขอ และจากนั้นเข้ารหัสการตอบสนอง OHTTP เพื่อส่งต่อกลับไปยัง Relay ในการตอบกลับ HTTP ไคลเอ็นต์ต้องรวมส่วนหัวของคำขอ Content-Type เป็น message/ohttp-req ในคำขอ HTTP POST


POST https://safebrowsingohttpgateway.googleapis.com/v1/ohttp:handleOhttpEncapsulatedRequest?key=<API key>

หมายเหตุ: ตามคำแนะนำของ RFC โปรดเข้ารหัสคำขอภายใน (ดูเอกสารประกอบ V5 เกี่ยวกับวิธีสร้างคำขอ Google Safe Browsing) โดยใช้โปรโตคอล HTTP แบบไบนารี RFC 9292

ไลบรารีไคลเอ็นต์

Google Quiche มีการใช้งานฝั่งไคลเอ็นต์สำหรับทั้งโปรโตคอล OHTTP และ BHTTP เราแนะนำให้ลูกค้าใช้ไลบรารีเหล่านี้ โปรดดูรหัสเทียมด้านล่างเกี่ยวกับวิธีสร้างคำขอ OHTTP เพื่อเข้าถึง API

ตัวอย่างการใช้งานฝั่งไคลเอ็นต์

ไคลเอ็นต์จะดึงข้อมูลคีย์สาธารณะ HTTP จากปลายทางคีย์สาธารณะ ต่อจากนั้น ให้เริ่มต้นการกำหนดค่าคีย์ OHTTP สำหรับคีช แล้วเริ่มต้นไคลเอ็นต์ OHTTP สำหรับ quiche


auto ohttp_key_cfgs = quiche::ObliviousHttpKeyConfigs::ParseConcatenatedKeys(std::string public_key); auto key_config = ohttp_key_cfgs->PreferredConfig(); auto public_key = ohttp_key_cfgs->GetPublicKeyForId(key_config.GetKeyId()) auto ohttp_client = quiche::ObliviousHttpClient::Create(public_key, key_config);

ไคลเอ็นต์จะใช้การเข้ารหัส HTTP แบบไบนารีเพื่อสร้างคำขอ BHTTP เป็นขั้นตอนแรกก่อนการเข้ารหัส


quiche::BinaryHttpRequest::ControlData bhttp_ctrl_data{ .method = "POST", .scheme = "https", .authority = "safebrowsing.googleapis.com", .path = "/v5/hashes:search?key=<API key>&hashPrefixes=<HASH prefix 1>&hashPrefixes=<HASH prefix 2>", }; quiche::BinaryHttpRequest bhttp_request(bhttp_ctrl_data);

หลังจากนั้น ไคลเอ็นต์จะเข้ารหัสคำขอ HTTP แบบไบนารีที่สร้างขึ้นในขั้นตอนข้างต้น


auto bhttp_serialized = bhttp_request.Serialize(); auto ohttp_request = ohttp_client.CreateObliviousHttpRequest(*bhttp_serialized); // Client must include this in POST body, and add `Content-Type` header as "message/ohttp-req". auto payload_include_in_post_body = ohttp_request.EncapsulateAndSerialize();

เมื่อได้รับการตอบสนองจาก Relay ไคลเอ็นต์จะถอดรหัสการตอบสนอง การตอบกลับจะมีส่วนหัวการตอบกลับ Content-Type เป็น ohttp-res


auto ctx = std::move(ohttp_request).ReleaseContext(); auto ohttp_response = ohttp_client.DecryptObliviousHttpResponse("data included in body of http_response", ctx);

หลังจากถอดรหัสการตอบกลับ OHTTP เรียบร้อยแล้ว ให้ถอดรหัสเอาต์พุตโดยใช้ HTTP แบบไบนารีในลักษณะดังกล่าว


auto bhttp_response = BinaryHttpResponse::Create(ohttp_response.GetPlaintextData()); if (bhttp_response.status_code() == 200) { auto http_response = bhttp_response.body(); auto response_headers = bhttp_response.GetHeaderFields(); }