Heresy 這邊很早之前,就有開始使用 WebSocket++ 來開發自己的 WebSocket Server;而後來其實也有改用 Boost.Beast 來做同樣的工作。而這兩套函式庫的底層,其實都是 Boost::asio(官網),所以其實在某些地方還滿接近的。
而之前用起來都還算很正常,不管是老老的 IE 還是 Chrome 都可以使用,在有申請 SSL 憑證的情況下,就算建立加密的 WSS 也是可以正確使用的。
但是,前陣子當想使用 node.js(官網)來進行 WebSocket 的連線的時候,卻發現會出現「unable to verify the first certificate」的錯誤。
而根據 ssl-root-cas(官網)針對這個訊息給的說明,則是
the intermediate certificate wasn’t bundled along with the server certificate, you’ll need to fix that
也就是中繼憑證沒有正確設定造成的。
後來查了一下,Heresy 當初在設定 SSL 憑證的時候,都是參考官方的範例、透過 boost::asio::ssl::context 來讀取憑證;而在範例(echo_server_tls、server.cpp)中,基本上都是透過 use_certificate_chain_file() 這個函式來讀取憑證檔、並透過 use_private_key_file() 以及 set_password_callback() 來設定金鑰。
而申請憑證時,其實還有另外一個 bundle 的憑證(應該就是所謂的 intermediate certificate)要怎麼用?老實說,當時也沒研究出來,因為幾個主要的瀏覽器也都已經能用了,所以就放著不管了。
但是現在看來,node.js 這邊碰到的問題,似乎就和這個額外的憑證有關,所以似乎就不能不處理了。
而看了一下,boost::asio::ssl::context 又沒有名字接近的函式、而網路上也沒能找到類似的文件、範例(或許是關鍵字用錯了…)。
最後,在試了一陣子之後,才發現原來是要使用 load_verify_file() 這個函式,來讀取 bundle 的憑證;在這樣設定後,就可以用了。
Heresy 這邊針對 ssl::context 最後的設定方法是寫成:
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv12)); ctx->set_options( boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); ctx->set_password_callback( [rInfo](std::size_t max_length, boost::asio::ssl::context::password_purpose purpose) { return rInfo.m_sPassword; }); ctx->use_certificate_chain_file(rInfo.m_sCertFile); ctx->use_private_key_file(rInfo.m_sPrivateKeyFile, boost::asio::ssl::context::pem); ctx->set_verify_mode(boost::asio::ssl::context::verify_none); ctx->load_verify_file(rInfo.m_sVerifyFile);
這樣的形式,看起來是暫時沒問題了。
老實說,Heresy 對這方面的東西一整個不熟,現在也只是調到不會有問題而已;這邊也只是稍微紀錄一下,讓自己如果有需要有地方可以查而已。
如果有錯誤的話,也麻煩指證一下。
[…] Heresy 之前在用 Boost ASIO 建立 WebSocket Server 的時候類似,是沒有正確設定那個 bundle.crt […]
讚讚