mirror of
https://github.com/Runnin4ik/dpi-detector.git
synced 2026-10-19 09:23:17 +00:00
fix: the Russian sign-in hops read OK, and a hostless Location reads REDIR
`mail.ru` and `vkvideo.ru` answer `302` to `login.vk.ru`'s autologin and `dzen.ru` `302` to `sso.passport.yandex.ru`'s push. Each target is its own operator's account host, so the hop is the site's behaviour rather than a foreign redirect, and without the pair `site_of` reads the two hosts as different sites and paints a red REDIR. The same pass fixes the other end of the same decision: a `Location` that names no host at all (`https:///`, the shape a rewriting middlebox leaves behind) is REDIR too, and its detail carries the raw value rather than a host, because there is no host to compare against the site and the value itself is the evidence.
This commit is contained in:
parent
65879ff2bd
commit
6be2f614d5
1 changed files with 59 additions and 1 deletions
|
|
@ -648,6 +648,16 @@ fn strip_www(host: &str) -> &str {
|
|||
/// answers `301` to `video.google.com` over plain HTTP and to `www.google.com`
|
||||
/// over TLS. All four targets are Google's own hosts, so the hop is the site's
|
||||
/// behaviour rather than a foreign redirect — the exact pair, still directional.
|
||||
///
|
||||
/// The Russian sign-in hops are the same shape, measured the same way: the mail
|
||||
/// service `mail.ru` and the video portal `vkvideo.ru` both answer `302` to
|
||||
/// `login.vk.ru`'s autologin, and the article portal `dzen.ru` answers `302` to
|
||||
/// `sso.passport.yandex.ru`'s push. Each is its own operator's account host, so
|
||||
/// the hop is the site's behaviour rather than a foreign redirect — the exact
|
||||
/// pair, still directional. The classifier returns `Detail::Redirect` for it like
|
||||
/// any other hop; a row whose four columns all passed then collapses that line
|
||||
/// into its timings, which is the difference between these pairs and the red
|
||||
/// `REDIR` they replaced.
|
||||
const REDIRECT_EXCEPTIONS: &[(&str, &str)] = &[
|
||||
("messenger.com", "facebook.com"),
|
||||
("instagram.com", "facebook.com"),
|
||||
|
|
@ -655,6 +665,9 @@ const REDIRECT_EXCEPTIONS: &[(&str, &str)] = &[
|
|||
("studio.youtube.com", "accounts.google.com"),
|
||||
("googlevideo.com", "google.com"),
|
||||
("googlevideo.com", "video.google.com"),
|
||||
("mail.ru", "login.vk.ru"),
|
||||
("vkvideo.ru", "login.vk.ru"),
|
||||
("dzen.ru", "sso.passport.yandex.ru"),
|
||||
];
|
||||
|
||||
/// True when `from` → `to` is a declared exception in [`REDIRECT_EXCEPTIONS`].
|
||||
|
|
@ -732,6 +745,11 @@ fn site_of(host: &str) -> Option<&str> {
|
|||
/// same-host hop to https reads `301 → https`, elsewhere `→ https`), a foreign
|
||||
/// host → REDIR with the host it named.
|
||||
///
|
||||
/// A `Location` that names no host at all (`https:///`, measured on a line that
|
||||
/// rewrites plain-HTTP answers) is REDIR too, and its detail carries the raw
|
||||
/// value rather than a host: there is no host to compare against the site, and
|
||||
/// the value itself is the evidence.
|
||||
///
|
||||
/// "Same family" is any of three things, with a leading `www.` ignored on both
|
||||
/// sides:
|
||||
/// * the same name (`holod.media` → `www.holod.media`);
|
||||
|
|
@ -762,7 +780,16 @@ pub(crate) fn classify_redirect(
|
|||
|| norm_loc.ends_with(&format!(".{}", norm_dom))
|
||||
|| norm_dom.ends_with(&format!(".{}", norm_loc))
|
||||
|| (site_loc.is_some() && site_loc == site_of(&norm_dom));
|
||||
let short_host: String = loc_host.chars().take(30).collect();
|
||||
// A Location that names no host at all — `https:///` is the measured shape,
|
||||
// the kind of header a rewriting middlebox leaves behind — is not a host to
|
||||
// name: the raw value is the whole evidence, and the row prints it instead.
|
||||
// Every other case keeps naming just the host, which is what a reader
|
||||
// compares against the site they asked for.
|
||||
let short_host: String = if loc_host.is_empty() {
|
||||
location.chars().take(30).collect()
|
||||
} else {
|
||||
loc_host.chars().take(30).collect()
|
||||
};
|
||||
|
||||
// A declared exception ([`REDIRECT_EXCEPTIONS`]) is the site's own redirect:
|
||||
// OK, and the detail still names the host the browser is sent to — the pair
|
||||
|
|
@ -1232,4 +1259,35 @@ mod tests {
|
|||
DpiStatus::RedirSuspect
|
||||
);
|
||||
}
|
||||
|
||||
/// The Russian sign-in hops read `OK` with the target named, the same shape
|
||||
/// as the Google pairs: measured live, `mail.ru` and `vkvideo.ru` answer
|
||||
/// `302` to `login.vk.ru`'s autologin and `dzen.ru` `302` to
|
||||
/// `sso.passport.yandex.ru`'s push. Without the pair each is a red `REDIR` —
|
||||
/// `site_of` reads the two hosts as different sites — which blames the
|
||||
/// network for the site's own account host answering.
|
||||
#[test]
|
||||
fn the_declared_signin_redirects_read_ok() {
|
||||
let cases: &[(&str, &str)] = &[
|
||||
("mail.ru", "https://login.vk.ru/?act=autologin&app_id=7539952&redirect_uri=https%3A%2F%2Faccount.mail.ru%2Flogin"),
|
||||
("vkvideo.ru", "https://login.vk.ru/?act=autologin&redirect_uri=https://vkvideo.ru"),
|
||||
("dzen.ru", "https://sso.passport.yandex.ru/push?uuid=75461044&retpath=https%3A%2F%2Fdzen.ru%2F"),
|
||||
];
|
||||
for (domain, location) in cases {
|
||||
let base = format!("https://{domain}");
|
||||
let (s, d) = classify_redirect(domain, &base, 302, location, false);
|
||||
assert_eq!(s, DpiStatus::Ok, "{domain} + {location} -> {}", d.code());
|
||||
assert!(matches!(d, Detail::Redirect { .. }), "{domain} names the target it was sent to");
|
||||
}
|
||||
// The pair is exact and directional: the hop back, and a host that only
|
||||
// wears the name, keep the default red verdict.
|
||||
assert_eq!(
|
||||
classify_redirect("login.vk.ru", "https://login.vk.ru", 302, "https://vkvideo.ru/", false).0,
|
||||
DpiStatus::RedirSuspect
|
||||
);
|
||||
assert_eq!(
|
||||
classify_redirect("notvkvideo.ru", "https://notvkvideo.ru", 302, "https://login.vk.ru/", false).0,
|
||||
DpiStatus::RedirSuspect
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue