Настройка VPN для всей домашней сети

А можете подсказать, как сделать подробную маршрутизацию? А именно Домашний роутер → ru-vps → eu-vps только для заблокированных ресурсов.
Я предполагаю, что на ru-vps стоит что-то наподобие sing box, который все это делает маршрутизирует. Не могу понять, как мне трафик вернуть обратно. Возможно, вопрос глупый, но пока что я не слишком силен в сетях.

Пообщавшись со знакомыми выяснил, что не у всех есть роутеры с нормальной поддержкой openwrt или ресурсов роутера недостаточно. Но что у первых, что у вторых хватает ресурсов на WG/OPN.
Предполагаю, что можно соорудить wg туннель от роутера до ru-vps, который уже возьмет на себя всю ношу маршрутизации (в целом точно также, как вы и описали).

У меня работает так:

Домашний роутер с openwrt. На нем поднят stunnel до vps. На vps обычный прокси без пароля доступный только на localhost (tinyproxy). Таким образом через туннель порт прокси оказывается открыт у меня в домашней сети. На всех устройствах я вношу в настройках, чтобы они подключались через прокси. Таким образом получается vpn без напряга даже на старых устройствах и утюгах.

Бонус: делаю PAC файл, который указывает какие сайты я хочу, чтобы шли через прокси.

Касательно вопроса ОП-а, xray можно поднять где-то в локальной сети или на роутере и также использовать его как прокси с других устройств.

У меня есть специфика - домашний роутер это мини-пк. Поэтому схема реализуется просто. На всех узлах стоит x-ray core. Дома он забирает указанный трафик и гонит на ru-vps как клиент. На ru-vps он же разделяет запросы на условно ru - not-ru, но можно например делить по регионам, если есть vps в разных странах. Он же режет трекеры и прочий мусор. Дальше отдает либо сразу в директ, либо как клиент на удаленные vps.

Соответственно мобильные клиенты сразу по схеме road warrior цепляются на ru-vps.

Насчёт WG - да, можно поднять его до ru-vps и отправлять трафик туда по этому туннелю. Без проблем и это даже быстрее, только и запасной протокол лучше иметь на случай отвала WG.

Никакой трафик “обратно” возвращать не надо. Туда уходят запросы, обратно - ответы. Это не VPN в полном смысле этого слова, хотя сквозь x-ray я пускал и OpenVPN и WG успешно, но накладные расходы всё-таки ощутимы. Тут лучше тогда Cloak

Через NAT.

Если на ru-vps настроены два тунеля входящий tun_ingress и исходящий tun_egress то можно настроить NAT примерно так:

  1. Добавить в /etc/iproute2/rt_tables именованную таблицу, например 128 transit.
  2. Добавить входящий интерфейс в неё ip rule add iif tun_ingress table transit
  3. Добавить шлюз ip route add default via адрес_шлюза_из_tun_egress table transit
  4. В брандмауэре создать зону для входящего трафика firewall-cmd --permanent --new-zone="ingress_zone"
  5. Добавить к ней входящий интерфейс firewall-cmd --permanent --zone="ingress_zone" --add-interface=tun_ingress
  6. Создать зону для исходящего трафика firewall-cmd --permanent --new-zone="egress_zone"
  7. Добавить к ней исходящий интерфейс firewall-cmd --permanent --zone="egress_zone" --add-interface=tun_egress
  8. Включить SNAT в исходящей зоне firewall-cmd --permanent --zone="egress_zone" --add-masquerade
  9. Создать политику транзита firewall-cmd --permanent --new-policy="in_to_e"
  10. Разрешить по умолчанию firewall-cmd --permanent --policy="in_to_e" --set-target=ACCEPT
  11. Добавить входящую зону firewall-cmd --permanent --policy="in_to_e" --add-ingress-zone="ingress_zone"
  12. Добавить исходящую зону firewall-cmd --permanent --policy="in_to_e" --add-egress-zone="egress_zone"
  13. Применить настройки брандмауэра firewall-cmd --reload
  14. ???
  15. PROFIT

Я все-таки предпочитаю для маршрутизации использовать xray, т.к. это позволяет роутить по доменам и geosite (например geosite:google и т.п.). Обычный роутинг по адресам не дает такой гибкости.
Если уже есть зарубежный vps с xray, то наверное самое простое - весь трафки отдавать в wireguard до этого vps, кроме русских ip, в которые выходить напрямую через провайдера. Получить список ru-ip можно, например, с помощью GitHub - furriest/radb-tools: RADB tools, главное чтобы роутер это переварил. Ну а на vps просто натить весь трафик с wg в сторону интернет.

Если же вы хотите сделать более секурную схему, то тогда такой вариант - берется русский vps, до которого кидается WG. Весь трафик заворачивается в WG (default gateway). Как завернуть default и не сломать себе интернет - примеры есть на сайте wireguard.
Далее на ru-vps подхватываете трафик из туннеля wireguard в xray. Например вот так:

table ip xray {
	chain prerouting {
		type filter hook prerouting priority filter; policy accept;
		ip daddr 127.0.0.0/8 counter return
		ip daddr 224.0.0.0/4 counter return
		ip daddr 240.0.0.0/4 counter return
		ip daddr 255.255.255.255 counter return
		iifname "wg0" ip daddr { <здесь DST-сети и адреса, которые не надо заворачивать в xray> } counter return comment "ip no tproxy"
		ip saddr { <здесь SRC-сети и адреса, которые не надо заворачивать в xray > } counter return
		iifname "wg0" meta l4proto { tcp, udp } th dport { 80, 443 } counter meta mark set 0x00000001 tproxy to 127.0.0.1:12345 accept comment "capture to tproxy"
	}
}

Соответственно весь трафик на 80 и 443 попадает на порт 12345, где слушает xray:

  "inbounds": [
    {
      "tag": "in-tproxy",
      "listen":"127.0.0.1","port": 12345,
      "protocol": "dokodemo-door",
      "settings": {
        "followRedirect": true,
        "network":"tcp,udp"
      },
      "streamSettings": {
        "sockopt": {
          "tproxy": "tproxy"
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic", "fakedns"],
        "routeOnly": true
      }
    },
...

Затем уже внутри роутинга xray крутите куда угодно по странам, доменам, адресам, протоколам - часть напрямую, часть в бан, часть на зарубежные vps (причем любым способом связи - vless/wg/shadowsocks)

Ну либо есть еще один хитрый способ выделять нужный трафик и отправлять его в xray - fakeDNS. Когда xray работает как DNS-сервер, он может отдавать вместо реальных ip указанный вами диапазон:

	"dns": {
    	"servers": [
    		{
        		"address": "127.0.0.1","skipFallback": false   # -- это выход на локальный dns-ресолвер (unbound/dnscrypt)
    		},
			{
				"address": "fakedns",
				"domains": [
                	"geosite:instagram",
                	"geosite:microsoft",
                	"geosite:facebook",
                	"geosite:dell",
                	"geosite:twitter",
                	"full:play.google.com",
                	"full:yt3.ggpht.com",
                	"domain:proton.me",
                	"domain:sagernet.org"
		]
	},
	"fakedns": {
    	"ipPool": "192.168.192.0/22",
    	"poolSize": 1022
    }

Дальше нужно только подхватить все пакеты на этот пул и отправить куда вам надо для обхода - wireguard / tproxy / socks… Но подхватить этот трафик должен тот xray, который выдал fake-адреса, потому что он выполняет обратную подмену на реальные ip.

У меня как раз настроена схема с мини-пк. На минипк установлен proxmox, а также вставлена сетевуха на 4 порта по 2,5 Гбит. На proxmox настроена виртуалка с openwrt и туда проброшена сетевуха. Что касается роутинга, то настроить схему - заблокированные ресурсы через европейский vds, а остальные через ru vds очень просто - ставите sing box на openwrt и далее создаете два outbound (один для русского vds, а второй для европейского)и далее в роутинге прописываете какие домены идут в ru outbound, а какие в eu outbound

У меня уже достаточно давно живёт такая схема. Есть апельсинка (Orange PI zero 3, сменила Raspberry pi 2B на этом посту), на которой крутятся всевозможные роутеры в скрытосети и прочие радости(i2p, tor, yggdrasil, opera proxy, dpitunnel) и собственно инсталляция xray, которая на входе имеет Wireguard интерфейс, а выходом смотрит либо в дикий интернет(туда заворачивается траффик на ру домены и торренты), либо через VLESS на импортный VPS. В качестве роутера некротик, где заворот траффика в local-wireguard(идущий в xray) осуществялется либо по ручками добавленным адрес листам, либо правилом по tls-host, которым в эти же листы адреса добавляются временно на 48 часов(актуально для сервисов с диким количеством хостов, типа как раз ютьюба). При этом всей домашней сети сам некротик прописан как DNS сервер, так что такой заворот работат в т.ч. и для хостов за CDN (т.к. получается что компы в ЛВС резолвят адрес хоста в тот же IP, что и в адрес листах самого некротика ибо подхватывают их из кеша). Ну и соотв. весь траффик, идущий на эти адреса mangle-ом отправляются в отдельную таблицу маршрутизации, которая заворачивается в этот самый локальный wireguard. Задержки оно почти не добавляет, буквально +1мс пинга. На импортном VPS соотв тоже есть выходы в дикий интернет и в Cloudflare WARP(куда заворачиваются опять же все РУ адреса по гео. Очень важно не ходить с иностранного впс до ру доменов, высоки шансы блокировки)
Ну и для i2p\tor заворот осуществляется через виртуальные DNS записи для всех i2p и onion хостов, а для yggdrasil я когда-то мануал постил на их вику на соотв. странице в комментах, там длинно.

Я не совсем понял, а зачем вы в двух местах это делаете?

Потому что я туда же иногда подключаюсь напрямую с телефона когда не дома.

Спасибо, конфиги очень помогут в понимании!

У меня только есть пару вопросов: что именно нужно указывать в следующие строки конфигурации nftables

Насколько критично то, что я ничего не указывал? Можете привести какой-нибудь пример?

В процессе настройки я столкнулся со следующим, довольно странным поведением:

  1. Купил RU-VPS в МСК
  2. Поставил wg-easy и создал туннель
  3. Присоединился с телефона, в итоге доступен, например, инстаграмм. Никаких конфигов nft, никаких sing-box я не ставил. Но позже я проверил, что недоступен ntc.party, linkedin.com.

Проверил на двух разных RU-VPS у двух разных провайдеров. Поведение идентичное. С чем оно может быть связано?

Но благодаря вашим примерам конфигов я смог настроить схему WG client → VPS (wg tun to port 12345, sing-box inbound 127.0.0.1:12345 → eu vps).

Я могу как-то 100% убедиться в том, что sing-box работает? Логи и прочее.
Когда была схема подключения iOS client → eu-vps, там я отчетливо видел, что при посещении каких-либо ру сайтов, которые определяют местоположение по IP, они определяли что я в России. В то время speedtest.net показывал мне локацию EU-VPS.
При реализации схемы с двумя VPS (Ru + Eu) перестали работать различные сервисы, например chatGTP (openai.com). При прямом подключении к eu vps - работает отлично (openai)

Здесь Я указываю адреса, которые не должны попадать в xray (в вашем случае в singbox). Например: телефон в домашней сети и я хочу с него подключиться к ru-черверу в МСК (просто проверить работу v2ray после правок) если не указать здесь dst-адрес сервера, то подключение пойдет через tproxy - home_inbound - wg-out - wg-in - msk_inbound, а это не нужно.

Насчёт логов в singbox не подскажу, но в xray (который по сути форк), есть раздел logs, который позволяет настроить логгирование dns, а также access.log, error.log и уровень событий.

Что и как блокирует провайдер и блокирует ли - непредсказуемо. Зависит от его масштаба и юрисдикции. И наличия Ревизора и ТСПУ, а также провайдеров на аплинке. Бывает что практически блокировок нет, только DNS местный, который и убивает ответы на запрещенку. А бывает что все прикрыто “как положено”, но рутрекер работает)

Тогда не совсем понимаю, почему не работает openai? Почему-то пытаемся его получить из ru vps?

Нужно проверять, что происходит после попадания трафика в ядро singbox. Во-первых, как обрабатывается dns в этой схеме. Во-вторых, работает ли sniffing. Запросы с transparent proxy не содержат никакой информации о домене и приложение должно их получить из сессии, чтобы роутинг мог понять, в какой outbound направлять трафик.

У меня очень давно работает такая схема
Vps сервер с протоколом VPN ↔ роутер с системой OpenWRT
На роутере настроено следующее:
Sing-box с протоколом vless reality в качестве интерфейса vpn
Ruantiblock для умного перенаправления трафика
Хороший трафик идет напрямую, заблокированный через vpn

Последний раз переделывал все по этому гайду с 4pda но вместо shadowsocks за строкой outbounds прописывал свой протокол vless reality
Конфигурацию вытащил из nekobox путем импорта в файл
Копируется все начиная от открытой квадратной скобки
Outbounds [
До закрытия этой скобки
]
Все остальное расписано в гайде, гайд доступен только при использовании vpn

Спойлер

P.s данные сервера изменены, не пытайтесь подключиться - бесполезно

В списках пользователя добавляю такие домены

Спойлер

#YOUTUBE
youtube.com
google.com
www.youtube.com
m.youtube.com
s.youtube.com
ytimg.com
s.ytimg.com
i.ytimg.com
ytimg.l.google.com
youtube.l.google.com
i.google.com
googlevideo.com
youtu.be
yt.be
accounts.youtube.com
consent.youtube.com
realtimesupport.youtube.com
studio.youtube.com
i9.ytimg.com
i.ytimg.com
yt3.ggpht.com
ggpht.com
youtubekids.com
googleusercontent.com
googleapis.com
youtubei.googleapis.com
notifications-pa.googleapis.com
gstatic.com
suggestqueries.google.com
# Прочее
habr.com
hdrezka.ag
rezka.ag
ntc.party
#Темная сторона 4pda
4pda.ru
4pda.ws
4pda.to

Тут ещё стоит отметить, что OpenAI не любит IP адреса всяких хостеров VPS (non-residental ip). Я с этим столкнулся и решил с помощью направления трафика с прокси в европе для домена openai на Cloudflare Warp. Делал как в этом коментарии. Таким образом у меня работают ChatGPT и MS Copilot.

У меня стоит похожая задача. Хочу настроить раздачу wifi с ВПН (vless+xtls-reality), чтобы все подключившиеся клиентские устройства прозрачно через него ходили. Вопрос что для этого проще всего взять? Есть базовое понимание работы с Linux, могу что-то настроить по гайдам. Думаю взять raspberry pi, подключить его к основному роутеру кабелем и раздавать с него wifi. Но вот конкретного гайда что ставить на расбери и как это настраивать я не нашел. Я даже не знаю какой расбери для этого лучше взять, что именно на него ставить и как это настраивать. Есть какой-то гайд на эту тему?

раздавать вайфай с raspberry не обязательно, написал в лс

Добрый день!

Пробую по такому же пути поднять следующую схему:

В гипервизоре две карты, виртуалка с Debian 12 является шлюзом всей сети.

И после запуска Sign-box интернет заканчивается на всех устройствах кроме Router.
Понимаю, что либо не доделал что-то в конфиге sign-box, либо в nftables.
Вот конфиг sing-box:

{
  "log": {
    "disabled": false,
    "level": "debug",
    "output": "/tmp/sing-box.log",
    "timestamp": true
  },
  "dns": {
    "strategy": "ipv4_only",
    "servers": [
      {
        "tag": "google",
        "address": "https://8.8.8.8/dns-query",
        "detour": "direct"
      },
      {
        "tag": "cloudflare",
        "address": "https://1.1.1.1/dns-query",
        "detour": "direct"
      }
    ]
  },
  "inbounds": [
      {
        "type": "tun",
        "interface_name": "tun0",
        "domain_strategy": "ipv4_only",
        "address": "172.16.250.1/30",
        "auto_route": true,
        "strict_route": false,
        "auto_redirect": true,
        "sniff": true,
        "sniff_override_destination": true
     }
    ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    },
        {
            "domain_strategy": "",
            "flow": "xtls-rprx-vision",
            "packet_encoding": "",
            "server": "server_ip",
            "server_port": 443,
            "tag": "proxy",
            "tls": {
                "enabled": true,
                "reality": {
                    "enabled": true,
                    "public_key": "public_key",
                    "short_id": ""
                },
                "server_name": "server_name",
                "utls": {
                    "enabled": true,
                    "fingerprint": "chrome"
                }
            },
            "type": "vless",
            "uuid": "uuid",
        }
  ],
"route": {
    "rules": [
      {
        "protocol": "dns",
        "action": "hijack-dns"
      },
    {
        "domain": [
          "2ip.ru",
          "2ip.io"
        ],
        "domain_keyword": [],
        "domain_regex": [],
        "domain_suffix": [],
        "geosite": [],
        "outbound": "proxy"
},
      {
        "ip_is_private": true,
        "outbound": "direct"
      },
    {
        "rule_set": [
          "antizapret"
        ],
        "outbound": "proxy"
      }
    ],
    "rule_set": [
      {
    "tag": "antizapret",
    "type": "remote",
    "format": "binary",
    "url": "https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-geosite/geosite-ru-blocked.srs",
    "download_detour": "proxy",
    "update_interval": "1d"
  },
    ],
    "final": "direct",
   "auto_detect_interface": true
  }
}

Вот вывод nft -a list ruleset после запуска sing-box.

table inet FILTER { # handle 33
        chain FROM_WAN { # handle 1
                ip saddr { 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } counter packets 0 bytes 0 drop # handle 6
                counter packets 467 bytes 484950 drop # handle 7
        }

        chain FROM_LAN { # handle 2
                tcp dport { 22, 53, 179, 2080, 3978, 12345 } counter packets 69 bytes 3588 accept # handle 9
                udp dport { 53, 67, 161, 2080, 3978, 12345 } counter packets 865 bytes 65834 accept # handle 11
                counter packets 32702 bytes 2358829 drop # handle 12
        }

        chain INPUT { # handle 3
                type filter hook input priority filter; policy accept;
                ct state established,related counter packets 50661 bytes 120505515 accept # handle 13
                ct state invalid counter packets 277 bytes 13629 drop # handle 14
                icmp type echo-request meta length 1529-65535 counter packets 0 bytes 0 drop # handle 15
                ip protocol icmp limit rate 30/minute counter packets 0 bytes 0 accept # handle 16
                iifname "lo" ip daddr != 127.0.0.0/8 counter packets 0 bytes 0 drop # handle 17
                iifname "lo" counter packets 16 bytes 960 accept # handle 18
                iifname "br0" counter packets 467 bytes 484950 jump FROM_WAN # handle 19
                iifname "br1" counter packets 33636 bytes 2428251 jump FROM_LAN # handle 20
                counter packets 43 bytes 2781 drop # handle 21
        }

        chain FORWARD { # handle 4
                type filter hook forward priority filter; policy accept;
                ct state established,related counter packets 691531 bytes 1040684086 accept # handle 22
                ct state invalid counter packets 3244 bytes 413839 drop # handle 23
                iifname { "lo", "br1" } counter packets 2481 bytes 337068 accept # handle 25
                counter packets 0 bytes 0 drop # handle 26
        }
}
table inet NAT { # handle 34
        chain POSTROUTING { # handle 1
                type nat hook postrouting priority filter; policy accept;
                oifname "br0" masquerade # handle 2
        }
}
table inet sing-box { # handle 35
        set inet4_local_address_set { # handle 1
                type ipv4_addr
                flags interval
                elements = { 10.0.1.0/24, 100.80.0.0/14,
                             127.0.0.0/8, 172.16.250.0/30 }
        }

        chain output { # handle 2
                type nat hook output priority mangle; policy accept;
                oifname "tun0" meta nfproto ipv4 meta l4proto tcp counter packets 0 bytes 0 redirect to :40635 return # handle 3
        }

        chain prerouting { # handle 4
                type nat hook prerouting priority dstnat + 1; policy accept;
                meta nfproto ipv4 meta l4proto { tcp, udp } th dport 53 dnat ip to 172.16.250.2 counter packets 0 bytes 0 # handle 6
                ip daddr @inet4_local_address_set counter packets 334 bytes 305218 return # handle 7
                meta nfproto ipv4 meta l4proto tcp counter packets 181 bytes 96235 redirect to :40635 return # handle 8
                meta mark set 0x00002023 ct mark set meta mark counter packets 3 bytes 1917 # handle 9
        }
}

ЧЯДНТ? Или если есть готовый конфиг или ссылка на настройку - буду премного благодарен.

Пытался сделать и через Xray, чтобы удобно роутить через x-ui, но потерпел фиаско с тем, что при попытке изменения конфига через JSON получал постоянные 500 и 502 после попытки перезапуска Xray из x-ui.

вы не указали версию, но в новых sniff в inbound это deprecated и вызывает проблемы (напр в тг на андроид не отправляются фотки), и в версии 1.11.6 или 1.11.7 были изменения по поводу авто роутинга

Я извиняюсь за оффтопик, но после того, как просмотрел простыни документации singbox и их стремительный перевод кучи всего в legacy с каждой версией, теврдо решил остаться на Xray core )