本文档介绍如何在CEF框架中接入DoH。
1. 前言
CEF(Chromium Embedded Framework)是一个基于Chromium的开源框架,广泛应用于需要嵌入Web浏览功能的桌面应用程序中。在CEF框架的应用场景中,尤其是在涉及敏感数据交互或高安全性要求的环境中,传统DNS解析方式可能无法满足安全需求。DoH通过HTTPS加密通道传输DNS查询和响应,能够有效防止中间人攻击、DNS劫持以及流量嗅探,从而提升应用的安全性和用户隐私保护能力。通过将DoH集成到CEF框架中,开发者可以在不改变原有应用逻辑的前提下,显著提升嵌入式浏览器的安全性和用户体验。
2. 前提条件
在CEF框架接入 DoH 前,请您确保已经完成配置DoH服务。
CEF 会使用内置的探测域名
google.com
对 DoH 可用性检查,在探测完成前,DoH 被视为“未确定可用”,为保证 DoH 服务正常工作,请确保google.com
域名添加到解析列表中或允许所有域名解析。CEF版本要求:建议使用115或更高版本(对应Chromium 115+)
3 接入步骤
CEF框架接入DoH主要包含三个核心步骤:首先需要配置独立的应用级缓存路径以避免配置冲突;然后通过Preferences API设置DoH模板和模式以启用加密DNS服务;最后实现自动降级机制以保障服务的稳定性。以下将详细介绍每个步骤的具体实现方法。
3.1 配置CEF应用缓存路径
本方案需要主动配置应用级的缓存路径。若未主动设置缓存路径而使用默认路径,其他CEF应用可能会污染本应用缓存,导致DoH配置失效或被覆盖。
在初始化CEF时,可以通过CefSettings
对象来设置缓存路径,同时确保应用有权限访问此缓存路径。以下为示例代码:
void ConfigureCachePath(CefSettings& settings) {
// 设置根缓存路径
std::string cache_path;
#if defined(OS_MAC)
cache_path = std::string("/Users/") + getenv("USER") + "/Library/Application Support/YourAppName/cache";
#elif defined(OS_WIN)
cache_path = std::string(getenv("LOCALAPPDATA")) + "\\YourAppName\\cache";
#else
cache_path = std::string(getenv("HOME")) + "/.cache/YourAppName";
#endif
CefString(&settings.root_cache_path) = cache_path;
CefString(&settings.cache_path) = cache_path;
}
// 在main函数中使用
int main(int argc, char* argv[]) {
CefSettings settings;
// 其他参数配置
// ...
ConfigureCachePath(settings);
// 初始化CEF
CefInitialize(main_args, settings, app.get(), nullptr);
// ...
}
3.2 通过Preferences配置DoH
使用CefPreferenceManager
来配置DoH。以下为示例代码:
void UpdateDnsOverHttpsTemplate(const std::string& new_template) {
// 获取全局的 CefPreferenceManager 实例
CefRefPtr<CefPreferenceManager> pref_manager =
CefPreferenceManager::GetGlobalPreferenceManager();
// 设置DoH模板
CefRefPtr<CefValue> template_value = CefValue::Create();
template_value->SetString(new_template);
// 设置DoH模式为"secure"
CefRefPtr<CefValue> mode_value = CefValue::Create();
mode_value->SetString("secure");
// 应用设置
CefString error;
pref_manager->SetPreference("dns_over_https.mode", mode_value, error);
pref_manager->SetPreference("dns_over_https.templates", template_value, error);
}
// 在应用初始化时调用
void OnContextInitialized(CefRefPtr<ClientAppBrowser> app) override {
// 在此处更换为自己的专属DoH接入点
UpdateDnsOverHttpsTemplate("https://1xxxx3.aliyunhttpdns.com/dns-query");
}
3.3 实现自动降级机制
CEF支持以下DoH模式:
secure
: 强制使用DoH,不允许回退到普通DNS。automatic
: 自动模式,允许在DoH失败时回退到普通DNS。off
: 关闭DoH。
为了提高应用的可用性,可以实现自动降级机制:在DoH解析失败时自动切换到本地DNS。以下是一个实现示例:
void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
// 检测DNS相关错误
if (errorCode == ERR_NAME_NOT_RESOLVED ||
errorCode == ERR_NAME_RESOLUTION_FAILED) {
LOG(ERROR) << "DNS resolution failed for URL: " << failedUrl.ToString()
<< ". Error code: " << errorCode
<< ". Switching to Local DNS...";
// 获取全局preference manager
CefRefPtr<CefPreferenceManager> pref_manager =
CefPreferenceManager::GetGlobalPreferenceManager();
// 切换到automatic模式,允许使用本地DNS
CefRefPtr<CefValue> new_mode = CefValue::Create();
new_mode->SetString("automatic");
CefString error;
if (pref_manager->SetPreference("dns_over_https.mode", new_mode, error)) {
// 重试加载失败的页面
frame->LoadURL(failedUrl);
return;
}
}
// 处理其他错误...
}
4. 总结
通过本文档介绍的步骤,您可以成功在CEF框架中集成DNS over HTTPS (DoH)功能,从而显著提升应用程序的安全性和用户隐私保护能力。配置后可通过网络抓包查看 HTTPS 请求、检查 DNS 日志或进行网络故障测试来验证 DoH 接入成功。推荐使用 automatic
模式并配置多个 DoH 服务器以确保生产环境的稳定性。