Update CHANGELOG.md for version 1.1.1; enhance SSL handling and logging
- Added a new section for version 1.1.1 detailing SSL fixes, including forced IPv4 resolution and additional SSL hardening measures. - Improved verbose logging for HTTPS requests, capturing detailed TLS handshake information for diagnostics. - Updated the help dialog to provide users with specific instructions for resolving SSL connection issues related to antivirus software. - Refactored SSL options in the plugin to ensure consistent handling across different components.
This commit is contained in:
+43
-11
@@ -441,26 +441,58 @@ extern "C" void ssl_error_dialog_show(const char *detail, const char *locale)
|
||||
QString title = is_de ? "Verbindungsfehler"
|
||||
: "Connection Error";
|
||||
|
||||
QString text = is_de
|
||||
QString err = detail && detail[0] ? QString(detail) : QString("SSL connect error");
|
||||
bool is_sec_e = err.contains("SEC_E_INVALID_TOKEN");
|
||||
|
||||
QString hint_de = is_sec_e
|
||||
? QString::fromUtf8(
|
||||
"Easy IRL Stream konnte keine sichere Verbindung "
|
||||
"zu stools.cc herstellen.\n\n"
|
||||
"Dein Antivirus-Programm f\xc3\xa4""ngt HTTPS-Verbindungen ab "
|
||||
"und st\xc3\xb6""rt den TLS-Handshake.\n\n"
|
||||
"So behebst du das Problem:\n"
|
||||
"1. \xc3\x96""ffne dein Antivirus-Programm (z.B. Panda Dome, "
|
||||
"Kaspersky, Avast, ESET, Bitdefender)\n"
|
||||
"2. Gehe zu Einstellungen \xe2\x86\x92 Schutz / Webschutz\n"
|
||||
"3. Deaktiviere \"HTTPS-Scanning\" / \"SSL-Inspektion\" / "
|
||||
"\"Webschutz\" / \"Safe Browsing\"\n"
|
||||
"4. Oder f\xc3\xbc""ge stools.cc als Ausnahme hinzu\n"
|
||||
"5. Starte OBS neu")
|
||||
: QString::fromUtf8(
|
||||
"M\xc3\xb6""gliche Ursachen:\n"
|
||||
"\xe2\x80\xa2 Antivirus-Software blockiert die Verbindung "
|
||||
"(HTTPS-Scanning / SSL-Inspektion deaktivieren)\n"
|
||||
"\xe2\x80\xa2 Firewall oder Proxy blockiert stools.cc\n"
|
||||
"\xe2\x80\xa2 VPN-Verbindung aktiv\n\n"
|
||||
"Fehler: %1")
|
||||
.arg(detail && detail[0] ? detail : "SSL connect error")
|
||||
: QString("Easy IRL Stream could not establish a secure "
|
||||
"connection to stools.cc.\n\n"
|
||||
"\xe2\x80\xa2 VPN-Verbindung aktiv");
|
||||
|
||||
QString hint_en = is_sec_e
|
||||
? QString(
|
||||
"Your antivirus software is intercepting HTTPS connections "
|
||||
"and breaking the TLS handshake.\n\n"
|
||||
"How to fix this:\n"
|
||||
"1. Open your antivirus program (e.g. Panda Dome, "
|
||||
"Kaspersky, Avast, ESET, Bitdefender)\n"
|
||||
"2. Go to Settings \xe2\x86\x92 Protection / Web Protection\n"
|
||||
"3. Disable \"HTTPS Scanning\" / \"SSL Inspection\" / "
|
||||
"\"Web Protection\" / \"Safe Browsing\"\n"
|
||||
"4. Or add stools.cc as an exception\n"
|
||||
"5. Restart OBS")
|
||||
: QString(
|
||||
"Possible causes:\n"
|
||||
"\xe2\x80\xa2 Antivirus software blocking the connection "
|
||||
"(disable HTTPS scanning / SSL inspection)\n"
|
||||
"\xe2\x80\xa2 Firewall or proxy blocking stools.cc\n"
|
||||
"\xe2\x80\xa2 VPN connection active\n\n"
|
||||
"Error: %1")
|
||||
.arg(detail && detail[0] ? detail : "SSL connect error");
|
||||
"\xe2\x80\xa2 VPN connection active");
|
||||
|
||||
QString text = is_de
|
||||
? QString::fromUtf8(
|
||||
"Easy IRL Stream konnte keine sichere Verbindung "
|
||||
"zu stools.cc herstellen.\n\n%1\n\n"
|
||||
"Fehler: %2")
|
||||
.arg(hint_de, err)
|
||||
: QString(
|
||||
"Easy IRL Stream could not establish a secure "
|
||||
"connection to stools.cc.\n\n%1\n\n"
|
||||
"Error: %2")
|
||||
.arg(hint_en, err);
|
||||
|
||||
QMessageBox::warning(parent, title, text, QMessageBox::Ok);
|
||||
}
|
||||
|
||||
+58
-1
@@ -299,6 +299,44 @@ struct update_ctx {
|
||||
#include "help-dialog.hpp"
|
||||
#include "stats-dialog.hpp"
|
||||
|
||||
static int curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
||||
size_t size, void *userptr)
|
||||
{
|
||||
(void)handle;
|
||||
(void)userptr;
|
||||
|
||||
const char *prefix;
|
||||
switch (type) {
|
||||
case CURLINFO_TEXT:
|
||||
prefix = "* ";
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
return 0;
|
||||
case CURLINFO_HEADER_IN:
|
||||
prefix = "< ";
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
prefix = "> ";
|
||||
break;
|
||||
case CURLINFO_DATA_IN:
|
||||
case CURLINFO_DATA_OUT:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
size_t len = size < sizeof(buf) - 1 ? size : sizeof(buf) - 1;
|
||||
memcpy(buf, data, len);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
|
||||
blog(LOG_INFO, "[%s] curl: %s%s", PLUGIN_NAME, prefix, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool check_update_blocking(void)
|
||||
{
|
||||
char url[256];
|
||||
@@ -323,7 +361,17 @@ static bool check_update_blocking(void)
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
#ifdef _WIN32
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION,
|
||||
CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
|
||||
(long)CURL_HTTP_VERSION_1_1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
@@ -386,6 +434,15 @@ bool obs_module_load(void)
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
|
||||
curl_version_info_data *vi = curl_version_info(CURLVERSION_NOW);
|
||||
if (vi) {
|
||||
blog(LOG_INFO,
|
||||
"[%s] curl %s, SSL: %s, features: 0x%x",
|
||||
PLUGIN_NAME, vi->version,
|
||||
vi->ssl_version ? vi->ssl_version : "none",
|
||||
(unsigned)vi->features);
|
||||
}
|
||||
|
||||
if (check_update_blocking()) {
|
||||
g_update_required = true;
|
||||
blog(LOG_WARNING,
|
||||
|
||||
+59
-6
@@ -45,6 +45,63 @@ static void maybe_show_ssl_error(CURLcode res, const char *errbuf)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- cURL debug callback ---- */
|
||||
|
||||
static int curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
||||
size_t size, void *userptr)
|
||||
{
|
||||
(void)handle;
|
||||
(void)userptr;
|
||||
|
||||
const char *prefix;
|
||||
switch (type) {
|
||||
case CURLINFO_TEXT:
|
||||
prefix = "* ";
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
return 0;
|
||||
case CURLINFO_HEADER_IN:
|
||||
prefix = "< ";
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
prefix = "> ";
|
||||
break;
|
||||
case CURLINFO_DATA_IN:
|
||||
case CURLINFO_DATA_OUT:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
size_t len = size < sizeof(buf) - 1 ? size : sizeof(buf) - 1;
|
||||
memcpy(buf, data, len);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
|
||||
blog(LOG_INFO, "[%s] curl: %s%s", PLUGIN_NAME, prefix, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void curl_set_ssl_opts(CURL *curl)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
#ifdef _WIN32
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION,
|
||||
CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
|
||||
(long)CURL_HTTP_VERSION_1_1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb);
|
||||
}
|
||||
|
||||
/* ---- cURL helpers ---- */
|
||||
|
||||
struct mem_buf {
|
||||
@@ -92,9 +149,7 @@ static char *api_get(const char *path, const char *token)
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
curl_set_ssl_opts(curl);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
@@ -147,9 +202,7 @@ static bool api_post(const char *path, const char *token, const char *json_body)
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
curl_set_ssl_opts(curl);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
+48
-1
@@ -25,6 +25,43 @@ static size_t discard_response(void *ptr, size_t size, size_t nmemb,
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
static int webhook_curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
||||
size_t size, void *userptr)
|
||||
{
|
||||
(void)handle;
|
||||
(void)userptr;
|
||||
|
||||
const char *prefix;
|
||||
switch (type) {
|
||||
case CURLINFO_TEXT:
|
||||
prefix = "* ";
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
case CURLINFO_DATA_IN:
|
||||
case CURLINFO_DATA_OUT:
|
||||
return 0;
|
||||
case CURLINFO_HEADER_IN:
|
||||
prefix = "< ";
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
prefix = "> ";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
size_t len = size < sizeof(buf) - 1 ? size : sizeof(buf) - 1;
|
||||
memcpy(buf, data, len);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
|
||||
blog(LOG_INFO, "[Easy IRL Stream] curl: %s%s", prefix, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void webhook_do_send(const char *url, const char *json_body)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
@@ -48,7 +85,17 @@ static void webhook_do_send(const char *url, const char *json_body)
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "easy-irl-stream-webhook/1.0");
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
#ifdef _WIN32
|
||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION,
|
||||
CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
|
||||
(long)CURL_HTTP_VERSION_1_1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, webhook_curl_debug_cb);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
Reference in New Issue
Block a user