Это называется split tunneling + policy routing.
Для залоченного трафика
Chrome + RnD(PAC) → SOCKS5 :1081 → Xray (fwmark=100) → ip rule/table 100 → tun0 (OpenVPN route-nopull)
Для остального
Chrome → direct(через локального провайдера)
1) Фильтрую трафик на уровне браузера - PAC(Proxy Auto-Config) Принцип работы: Браузер загружает файл .pac, содержащий функцию FindProxyForURL(url, host). Эта функция анализирует адрес сайта и возвращает инструкцию: DIRECT (напрямую) или PROXY host:port.
Пишем расширение. Я писал под chrome. Кладем файлы в одну папку.
{
"manifest_version": 3,
"name": "RnDProxy — Ray’n’Dms proxy",
"version": "0.1.0",
"description": "Domain-based SOCKS5 proxy switcher (SOCKS5 127.0.0.1:1080).",
"permissions": [
"proxy",
"storage"
],
"host_permissions": [
"
],
"background": {
"service_worker": "bg.js"
},
"action": {
"default_title": "RnDProxy"
}
}
const PROXY_HOST = "127.0.0.1";
const PROXY_PORT = 1080;
const PROXY_DOMAINS = [
// chatGPT
"chatgpt.com",
"chat.openai.com",
"openai.com",
"oaistatic.com",
"oaiusercontent.com",
"auth0.com",
// Strava
"strava.com",
// Windguru
"windguru.cz",
"facebook.com",
"fbcdn.net",
"fbsbx.com",
"messenger.com",
"instagram.com",
"cdninstagram.com",
// YouTube
"youtube.com",
"googlevideo.com",
"ytimg.com",
"googleapis.com",
"gvt1.com"
];
function buildPac(domains) {
return `
function FindProxyForURL(url, host) {
const targets = ${JSON.stringify(domains)};
for (let i = 0; i < targets.length; i++) {
const d = targets[i];
if (host === d || host.endsWith("." + d)) {
return "SOCKS5 ${PROXY_HOST}:${PROXY_PORT}; DIRECT";
}
}
return "DIRECT";
}
`;
}
async function setBadge(enabled) {
await chrome.action.setBadgeText({ text: enabled ? "ON" : "OFF" });
}
async function apply(enabled) {
await setBadge(enabled);
if (!enabled) {
await chrome.proxy.settings.set({
value: { mode: "direct" },
scope: "regular"
});
return;
}
const pacScript = buildPac(PROXY_DOMAINS);
await chrome.proxy.settings.set({
value: {
mode: "pac_script",
pacScript: { data: pacScript }
},
scope: "regular"
});
}
async function loadStateAndApply() {
const { enabled } = await chrome.storage.local.get({ enabled: true });
await apply(enabled);
}
chrome.runtime.onInstalled.addListener(l
chrome.runtime.onStartup.addListener(loa
chrome.action.onClicked.addListener(
async () => {
const { enabled } = await chrome.storage.local.get({ enabled: true });
const next = !enabled;
await chrome.storage.local.set({ enabled: next });
await apply(next);
}
);
В браузере прописываем прокси. У меня хром вывел на системный диалог Параметры сети.
Прокси-сервер - метод "Вручную" - Socks узел 127.0.0.1:1080
Подключаем расширение в хроме. Управление расширениями. Включить режим разработчика и нажать на кнопочку "Загрузить распакованное расширение" - выбрать папку, где сохранены вышеупомянутые файлы.
Включать будем потом, когда все готово будет.
2) Устанавливаем xray. В репах его нет и не предвидится, тк он специально предназначен для обхода всяких запретов.
bash <(curl -Ls https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh)
Проверяем - xray version
Теперь пишем к нему файл конфигурации.
{
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 1080,
"protocol": "socks",
"settings": {
"udp": false
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {},
"streamSettings": {
"sockopt": {
"mark": 100
}
}
}
],
"routing": {
"final": "direct"
},
"log": {
"loglevel": "warning"
}
}
Идея такая, на входе слушаем 127.0.0.1:1080 (лоченный трафик) на выходе ставим метку(fwmark) 0x64(100) на каждый пакет и отравляем в ядро.
3) Ядро получает такой пакет, смотрит правило
sudo ip rule add fwmark 0x64 table 100
которое мы добавили отправляет его в таблицу 100
А таблица 100 роутит весь входящий в нее трафик в tun0
sudo ip route replace default dev tun0 table 100
4) Есть одно но. Обычно файл конфигурации *.ovpn берет весь трафик компа и направляет его через tun0. А нам такое не нужно, нам нужно только тот трафик, что мы ему роутим.
Поэтому мы подравляем ovpn файл и добавляем
route-nopull
пусть где-то после предложения remote ...
теперь при запуске openvpn клиента, он вообще не назначает роутинг, мы делаем это сами, в пункте 3).
5) Теперь поднимаем весь vpn.
sudo openvpn --daemon dms --config "отредактированный файл ovpn в 4)"
Проверяем конфиг у xray
sudo xray run --test --config "/usr/local/etc/xray/config.json"
Если пишет ОК, запускаем
sudo xray run --config "/usr/local/etc/xray/config.json"
А теперь в браузере включаем расширение RnD.
Вот в принципе и все.