ZaStoGram_desktop/Telegram/SourceFiles/mtproto/proxy/status.cpp
loop-uh 5dffb4758d Name the camouflage answer instead of blaming the digest
When a relay does not recognise a ClientHello it proxies the connection
on to the domain it fronts for, so the ServerHello we then verify was
written by a real TLS server. Its first application data record carries a
certificate chain, which is kilobytes; a relay's is about sixty bytes,
for a batch of roughly two hundred in total. The size tells the two apart
with no ambiguity, and the reports in hand sat at 1448, 2856 and 4099
bytes against 202 for the connection that worked.

Both were reported as "bad Server Hello digest", which points at the
relay and hides that the hello never reached it. They are separate
reasons now, and the log carries server_hello_foreign_tls for the one
that means the relay looked straight past us.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 00:15:27 +03:00

184 lines
7.8 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "mtproto/proxy/status.h"
namespace MTP {
bool IsMtproxyTerminalFailure(ProxyMtproxyTerminalReason reason) {
return reason != ProxyMtproxyTerminalReason::None;
}
ProxyConnectionStatusKind ProxyConnectionStatusKindFor(
const ProxyConnectionStatus &status) {
switch (status.mtproxyReason) {
case ProxyMtproxyTerminalReason::None:
break;
case ProxyMtproxyTerminalReason::DnsFailed:
return ProxyConnectionStatusKind::MtproxyDnsFailed;
case ProxyMtproxyTerminalReason::TcpConnectTimeout:
return ProxyConnectionStatusKind::MtproxyTcpConnectTimeout;
case ProxyMtproxyTerminalReason::TcpConnectedNoClientHelloWrite:
return ProxyConnectionStatusKind::MtproxyTcpConnectedNoClientHelloWrite;
case ProxyMtproxyTerminalReason::ClientHelloSentNoServerHello:
return ProxyConnectionStatusKind::MtproxyNoServerHello;
case ProxyMtproxyTerminalReason::TlsAlertAfterClientHello:
return ProxyConnectionStatusKind::MtproxyTlsAlert;
case ProxyMtproxyTerminalReason::ServerHelloHmacMismatch:
return ProxyConnectionStatusKind::MtproxyServerHelloHmacMismatch;
case ProxyMtproxyTerminalReason::ServerHelloForeignTls:
return ProxyConnectionStatusKind::MtproxyServerHelloForeignTls;
case ProxyMtproxyTerminalReason::ServerHelloOkNoAppData:
return ProxyConnectionStatusKind::MtproxyServerHelloOkNoAppData;
case ProxyMtproxyTerminalReason::ServerHelloOkNoMtprotoData:
case ProxyMtproxyTerminalReason::ConnectedNoMtprotoData:
return ProxyConnectionStatusKind::MtproxyConnectedNoMtprotoData;
case ProxyMtproxyTerminalReason::AppDataRemoteClosed:
return ProxyConnectionStatusKind::MtproxyAppDataRemoteClosed;
case ProxyMtproxyTerminalReason::MtpReceiveTimeoutAfterData:
return ProxyConnectionStatusKind::MtproxyMtpReceiveTimeoutAfterData;
case ProxyMtproxyTerminalReason::ProxyProtocolBadResponse:
return ProxyConnectionStatusKind::MtproxyProxyProtocolBadResponse;
}
switch (status.error) {
case ProxyConnectionError::None:
break;
case ProxyConnectionError::HostNotFound:
return ProxyConnectionStatusKind::HostNotFound;
case ProxyConnectionError::ConnectionRefused:
return ProxyConnectionStatusKind::ConnectionRefused;
case ProxyConnectionError::Timeout:
return ProxyConnectionStatusKind::Timeout;
case ProxyConnectionError::Authentication:
return ProxyConnectionStatusKind::Authentication;
case ProxyConnectionError::ProxyProtocol:
return ProxyConnectionStatusKind::ProxyProtocol;
case ProxyConnectionError::RemoteClosed:
return ProxyConnectionStatusKind::RemoteClosed;
case ProxyConnectionError::Network:
return ProxyConnectionStatusKind::Network;
case ProxyConnectionError::BadResponse:
return ProxyConnectionStatusKind::BadResponse;
case ProxyConnectionError::Unknown:
return ProxyConnectionStatusKind::Failed;
}
switch (status.phase) {
case ProxyConnectionPhase::None:
return ProxyConnectionStatusKind::None;
case ProxyConnectionPhase::Resolving:
return ProxyConnectionStatusKind::Resolving;
case ProxyConnectionPhase::Connecting:
return ProxyConnectionStatusKind::Connecting;
case ProxyConnectionPhase::Handshake:
return ProxyConnectionStatusKind::Handshake;
case ProxyConnectionPhase::CheckingTelegram:
return ProxyConnectionStatusKind::CheckingTelegram;
case ProxyConnectionPhase::Connected:
return ProxyConnectionStatusKind::Connected;
case ProxyConnectionPhase::Failed:
return ProxyConnectionStatusKind::Failed;
}
return ProxyConnectionStatusKind::None;
}
ProxyConnectionStatusSeverity ProxyConnectionStatusSeverityFor(
ProxyConnectionStatusKind kind) {
switch (kind) {
case ProxyConnectionStatusKind::None:
return ProxyConnectionStatusSeverity::None;
case ProxyConnectionStatusKind::Resolving:
case ProxyConnectionStatusKind::Connecting:
case ProxyConnectionStatusKind::Handshake:
case ProxyConnectionStatusKind::CheckingTelegram:
return ProxyConnectionStatusSeverity::Progress;
case ProxyConnectionStatusKind::Connected:
return ProxyConnectionStatusSeverity::Success;
case ProxyConnectionStatusKind::MtproxyServerHelloOkNoAppData:
case ProxyConnectionStatusKind::MtproxyConnectedNoMtprotoData:
case ProxyConnectionStatusKind::MtproxyMtpReceiveTimeoutAfterData:
return ProxyConnectionStatusSeverity::Warning;
case ProxyConnectionStatusKind::HostNotFound:
case ProxyConnectionStatusKind::ConnectionRefused:
case ProxyConnectionStatusKind::Timeout:
case ProxyConnectionStatusKind::Authentication:
case ProxyConnectionStatusKind::ProxyProtocol:
case ProxyConnectionStatusKind::RemoteClosed:
case ProxyConnectionStatusKind::Network:
case ProxyConnectionStatusKind::BadResponse:
case ProxyConnectionStatusKind::Failed:
case ProxyConnectionStatusKind::MtproxyDnsFailed:
case ProxyConnectionStatusKind::MtproxyTcpConnectTimeout:
case ProxyConnectionStatusKind::MtproxyTcpConnectedNoClientHelloWrite:
case ProxyConnectionStatusKind::MtproxyNoServerHello:
case ProxyConnectionStatusKind::MtproxyTlsAlert:
case ProxyConnectionStatusKind::MtproxyServerHelloHmacMismatch:
case ProxyConnectionStatusKind::MtproxyServerHelloForeignTls:
case ProxyConnectionStatusKind::MtproxyAppDataRemoteClosed:
case ProxyConnectionStatusKind::MtproxyProxyProtocolBadResponse:
return ProxyConnectionStatusSeverity::Error;
}
return ProxyConnectionStatusSeverity::None;
}
ProxyConnectionStatusSeverity ProxyConnectionStatusSeverityFor(
const ProxyConnectionStatus &status) {
return ProxyConnectionStatusSeverityFor(
ProxyConnectionStatusKindFor(status));
}
ProxyConnectionStatusTone ProxyConnectionStatusToneFor(
ProxyConnectionStatusKind kind) {
switch (kind) {
case ProxyConnectionStatusKind::None:
return ProxyConnectionStatusTone::None;
case ProxyConnectionStatusKind::Resolving:
case ProxyConnectionStatusKind::Connecting:
case ProxyConnectionStatusKind::Handshake:
case ProxyConnectionStatusKind::CheckingTelegram:
return ProxyConnectionStatusTone::Progress;
case ProxyConnectionStatusKind::Connected:
return ProxyConnectionStatusTone::Success;
case ProxyConnectionStatusKind::MtproxyServerHelloOkNoAppData:
case ProxyConnectionStatusKind::MtproxyConnectedNoMtprotoData:
case ProxyConnectionStatusKind::MtproxyMtpReceiveTimeoutAfterData:
return ProxyConnectionStatusTone::Warning;
case ProxyConnectionStatusKind::HostNotFound:
case ProxyConnectionStatusKind::MtproxyDnsFailed:
return ProxyConnectionStatusTone::ErrorDns;
case ProxyConnectionStatusKind::Timeout:
case ProxyConnectionStatusKind::MtproxyTcpConnectTimeout:
return ProxyConnectionStatusTone::ErrorTimeout;
case ProxyConnectionStatusKind::ConnectionRefused:
case ProxyConnectionStatusKind::RemoteClosed:
case ProxyConnectionStatusKind::Network:
case ProxyConnectionStatusKind::MtproxyTcpConnectedNoClientHelloWrite:
return ProxyConnectionStatusTone::ErrorNetwork;
case ProxyConnectionStatusKind::ProxyProtocol:
case ProxyConnectionStatusKind::BadResponse:
case ProxyConnectionStatusKind::MtproxyProxyProtocolBadResponse:
return ProxyConnectionStatusTone::ErrorProtocol;
case ProxyConnectionStatusKind::Authentication:
return ProxyConnectionStatusTone::ErrorAuth;
case ProxyConnectionStatusKind::MtproxyNoServerHello:
case ProxyConnectionStatusKind::MtproxyTlsAlert:
case ProxyConnectionStatusKind::MtproxyServerHelloHmacMismatch:
case ProxyConnectionStatusKind::MtproxyServerHelloForeignTls:
return ProxyConnectionStatusTone::ErrorHandshake;
case ProxyConnectionStatusKind::MtproxyAppDataRemoteClosed:
return ProxyConnectionStatusTone::ErrorData;
case ProxyConnectionStatusKind::Failed:
return ProxyConnectionStatusTone::Error;
}
return ProxyConnectionStatusTone::None;
}
ProxyConnectionStatusTone ProxyConnectionStatusToneFor(
const ProxyConnectionStatus &status) {
return ProxyConnectionStatusToneFor(ProxyConnectionStatusKindFor(status));
}
} // namespace MTP