Is Rutor обход блокировки safe?
Rutor обход блокировки routes browser traffic through a remotely configured proxy and injects clickunder ads on every mouse click.
The extension fetches its proxy configuration—including host, port, and credentials—from an operator-controlled server at dark-proxy.ru on each startup, then applies those settings to redirect user traffic through the specified proxy for configured domains. When no paid promo token is active, it opens an advertisement page at dark-proxy.ru on every mouse click inside the popup. User-entered promo tokens are transmitted to a separate third-party service, token.ruchatgpt.site, for validation on every popup open.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Remote Proxy Config Controls Browser Routing
Enabling the proxy feature requests config from a remote endpoint.
The code accepts a host, port, credentials, and domain list, then installs matching rules.
The toggle GET was observed, but the endpoint was unreachable; no config captured.
You turn on the proxy feature in the popup.
The popup stores the enabled state and sends an enable message to the background worker.
The extension requests proxy rules from a remote host and applies them to matching browsing traffic.
If the response contains a proxy server and domains, the background worker installs a PAC script and proxy authentication handler.
| Field | Value | Why it matters | |
|---|---|---|---|
Proxy server | cfg.host plus cfg.port; no live value captured because the endpoint returned net::ERR_FAILED | Decides which server receives browser traffic for sites covered by the rules. | |
Proxy credentials | cfg.login plus cfg.pass, or user:pass embedded in cfg.servers | Lets the extension answer proxy login prompts for the supplied server. | |
Routed domains | cfg.domains entries matched as exact domains, subdomains, or substrings | Controls which sites are sent through the supplied proxy instead of going directly from your browser. | |
Visited site through proxy | https://rutor.info/favicon.ico | For covered domains, the proxy server can see the requested site and timing of visits. |
The popup trigger, remote config fetch, PAC builder, and proxy authentication path
proxyToggle.addEventListener('change', () => {
chrome.storage.local.get(['promoValidUntil'], (data) => {
const now = Date.now();
const promoValid = data.promoValidUntil && data.promoValidUntil > now;
if (proxyToggle.checked) {
// --- ВИЗУАЛЬНЫЙ ПИНОК (ОТОБРАЖАЕМ FAVICON) ---
const container = document.getElementById('pokeContainer');
if (container) {
container.innerHTML = `Пытаюсь загрузить: <br> <img src="https://rutor.info/favicon.ico?t=${Date.now()}" style="width:16px; height:16px; vertical-align:middle;">`;
}
// --------------------------------------------
chrome.storage.local.set({ proxyEnabled: true }, () => {
chrome.runtime.sendMessage({ action: 'enableProxy', skipTimer: promoValid });
status.textContent = '';
updateTimerVisibility(promoValid);
setupClickunder(promoValid);
if (!promoValid) {
const disableAt = Date.now() + 3 * 60 * 1000;
chrome.storage.local.set({ proxyDisableTime: disableAt });
startTimer(180);
} else {
stopTimer();
}
syncUI();
});
} else {
// Очистка контейнера при выключении
const container = document.getElementById('pokeContainer');
if (container) container.innerHTML = "Авторизация: выключено";
chrome.storage.local.set({ proxyEnabled: false }, () => {
chrome.runtime.sendMessage({ action: 'disableProxy' });
status.textContent = '';
stopTimer();
updateTimerVisibility(promoValid);
setupClickunder(promoValid);
syncUI();
});
}
});
});async function loadConfig(force = false) {
if (proxyManuallyDisabled && !force) return;
const { activatedPromoCode } = await chrome.storage.local.get("activatedPromoCode");
const token = activatedPromoCode ? activatedPromoCode.trim() : "";
const url = token
? `${PROXY_BASE_URL}pphakoegbpaabllnkbjadgpjckkbgdkp2.php?token=${encodeURIComponent(token)}`
: `${PROXY_BASE_URL}pphakoegbpaabllnkbjadgpjckkbgdkp.php`;
try {
const r = await fetch(url, { cache: "no-store" });
const cfg = await r.json();
let parsed = null;
if (cfg.host && cfg.port) {
parsed = { host: String(cfg.host), port: String(cfg.port), login: cfg.login || null, pass: cfg.pass || null };
} else if (cfg.servers && typeof cfg.servers === "object") {
const key = Object.keys(cfg.servers)[0];
parsed = parseProxyString(cfg.servers[key]);
}
if (!parsed) throw new Error("Cannot parse proxy");
const newHostPort = `${parsed.host}:${parsed.port}`;
if (!force && lastAppliedHost === newHostPort) return;
proxyData = { ...parsed, rawPacString: parsed.rawPacString || null };
domains = Array.isArray(cfg.domains) ? cfg.domains.slice() : [];
lastAppliedHost = newHostPort;
applyPacAndAuth();
enableXProxyAccessHeader();
} catch (e) {
log("[Config] Error: " + e.message);
}
}function buildPacFromDomains(proxyHostPort) {
if (!proxyHostPort || domains.length === 0) return "DIRECT";
let rules = "";
for (const d of domains) {
const dom = (d || "").trim();
if (!dom) continue;
if (dom.includes(".")) {
rules += `if (host === "${dom}" || host.endsWith(".${dom}")) return "PROXY ${proxyHostPort}";\n`;
} else {
rules += `if (host.includes("${dom}")) return "PROXY ${proxyHostPort}";\n`;
}
}
return `function FindProxyForURL(url, host) {\n${rules}return "DIRECT";\n}`;
}function applyPacAndAuth() {
if (proxyManuallyDisabled) {
log("[Proxy] applyPacAndAuth blocked — manually disabled");
chrome.proxy.settings.clear({ scope: "regular" });
return;
}
if (!proxyData.host || !proxyData.port) {
log("[Proxy] No proxy data → nothing to apply");
return;
}
const hostPort = `${proxyData.host}:${proxyData.port}`;
const pac = buildPacFromDomains(hostPort);
chrome.proxy.settings.set(
{ value: { mode: "pac_script", pacScript: { data: pac } }, scope: "regular" },
() => {
if (chrome.runtime.lastError) {
log("[Proxy] Error: " + chrome.runtime.lastError.message);
} else {
log("[Proxy] PAC applied → " + hostPort);
forceAuthorize(); // ВЫЗОВ ПРОГРЕВА
}
}
);
if (currentAuthHandler) {
try { chrome.webRequest.onAuthRequired.removeListener(currentAuthHandler); } catch(e) {}
currentAuthHandler = null;
}
if (proxyData.login && proxyData.pass) {
currentAuthHandler = (details) => {
if (details.isProxy) {
return {
authCredentials: {
username: proxyData.login,
password: proxyData.pass
}
};
}
return {};
};
chrome.webRequest.onAuthRequired.addListener(currentAuthHandler, { urls: ["<all_urls>"] }, ["blocking"]);
log("[Proxy] Auth handler added");
}
}- pphakoegbpaabllnkbjadgpjckkbgdkp.dark-proxy.ru
Receives the proxy configuration GET request; the code can also request a tokenized config endpoint on this host.
- cat.dark-proxy.ru
The background worker adds an X-Proxy-Access header rule for main-frame requests to this host after proxy data is loaded.
- rutor.info
The background worker fetches the favicon after applying PAC settings to warm proxy authorization.
Clicking inside the popup opens a dark-proxy.ru ad window
This proxy tool reaches rutor.info from Russia.
Without a paid token, clicking the popup opens dark-proxy.ru advertising paid tokens, confirmed by testing.
It fires at most once every few minutes, and never while a valid token is active.
You click anywhere inside the extension popup while no paid token is active.
The popup installs a document.onmouseup handler whenever a valid token is not present.
The popup opens a new browser window to a dark-proxy.ru page advertising paid access tokens.
window.open() targets dark-proxy.ru/new/google/rutor/cl.html with full browser chrome.
The click handler that opens the ad window
// Arms a click-under on the popup whenever no paid token is active.
// First qualifying click only sets a 1-minute 'clickunder-delay' cookie.
// Next click after the delay (and while no 'clickunder' cookie exists)
// opens a new browser window to the dark-proxy.ru buy-token page and
// sets a 'clickunder' cookie that suppresses repeats for 2 minutes.
function setupClickunder(promoValid) {
document.onmouseup = null;
if (promoValid) return; // suppressed while a paid token is active
document.onmouseup = function () {
if (!getCookie('clickunder-delay')) { // first click: arm 1-min delay
setCookie('clickunder-delay', '1', plus1Minute, '/');
return;
}
if (!getCookie('clickunder')) { // later click: open ad window
setCookie('clickunder', '1', plus2Minutes, '/');
window.open('https://dark-proxy.ru/new/google/rutor/cl.html', 'dark-proxy',
'menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes');
window.focus();
}
};
}The window does not open on the first click. The first qualifying click only sets a 1-minute 'clickunder-delay' cookie; a later click (after that delay, while no 'clickunder' cookie is set) opens the window and sets a 'clickunder' cookie that suppresses repeats for 2 minutes. Net effect: the ad window opens roughly once every couple of minutes of active clicking, not on every click.
| Referer | https://dark-proxy.ru/new/google/rutor/cl.html |
Promo token sent to token.ruchatgpt.site, unrelated to the vendor
Pasting an access token and clicking Activate POSTs it to token.ruchatgpt.site/propromo.php, distinct from vendor dark-proxy.ru.
Re-sent each popup open as a blacklist check.
A planted marker value appeared verbatim in the captured POST.
You enter an access token in the popup and click Activate.
The token also re-sends automatically each time the popup opens while a token is stored.
The popup POSTs the token to token.ruchatgpt.site, a domain unrelated to the stated vendor.
The request is a JSON POST to token.ruchatgpt.site/propromo.php carrying the token in a 'code' field.
| Content-Type | application/json |
{
"code": "<redacted>",
"checkBlacklist": false
}| Field | Value | Why it matters | |
|---|---|---|---|
Your access token | {"code":"<redacted>"} | The token you typed into the popup to unlock the proxy. Sent in full to a domain that is not the extension's stated vendor. | |
Blacklist-check flag | "checkBlacklist":false | True when the token is re-sent on popup open to check whether it has been revoked; false on the initial activation. |
The token validation request
// POSTs the user-entered token to token.ruchatgpt.site.
// Called two ways:
// - promoButton click -> validateToken(code, false, ...) (initial activation)
// - checkBlacklist() -> validateToken(storedCode, true, ...) on every popup open
function validateToken(code, checkBlacklist, callback) {
fetch('https://token.ruchatgpt.site/propromo.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, checkBlacklist })
})
.then(res => res.json())
.then(data => callback(null, data))
.catch(callback);
}- token.ruchatgpt.site
Receives the user's access token via POST /propromo.php for validation and blacklist checks. A separate domain from the stated vendor dark-proxy.ru.