[2026-10-30] eagle: family/how-to/rasputin-router.md
This commit is contained in:
1 parent
950e40d10a
commit
1f2b3f922e
1 file changed
+334
-32
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Rasputin OpenWrt router
|
||||
created: '2026-07-22'
|
||||
updated: '2026-09-17'
|
||||
updated: '2026-10-30'
|
||||
tags:
|
||||
- openwrt
|
||||
- router
|
||||
@@ -12,8 +12,9 @@ tags:
|
||||
---
|
||||
# Rasputin R5S OpenWrt router
|
||||
|
||||
> Status as of 2026-09-22: Rasputin is the OpenWrt edge/LAN router, routing normal LAN traffic through a VLESS/Xray tunnel via `tun0`, with explicit direct-WAN exceptions for upstream LAN access and Mac `cloudflared` QUIC traffic. 🔴 **WAN СНОВА ПЕРЕЕХАЛ (2026-09-22): `eth0` теперь `192.168.1.50/24`, gw `192.168.1.1`, MAC `36:ae:87:04:08:dc`, линк `1000/full`** — Распутин воткнут в сегмент `192.168.1.0/24`, где живут Кра́кен (`.14`/`.15`) и ТВ (`.70`). Прежний `192.168.2.157/24` (gw `192.168.2.2`) больше не активен.
|
||||
> 🔴 **Мак теперь в LAN Распутина** — `192.168.6.173` (en0), а НЕ `192.168.1.57`. Транзит из LAN `192.168.6.0/24` в `192.168.1.0/24` **СЛОМАН** (тот же класс проблемы, что и GPON-сегмент): правила `100` покрывают только `192.168.2.0/24` и `192.168.0.0/24`. См. раздел «🔴 Транзит из LAN в 192.168.1.0/24».
|
||||
Rasputin — LAN-роутер OpenWrt: `192.168.6.1/24`, WAN `eth0` — `192.168.2.157/24`, шлюз `192.168.2.2`. Клиентский TCP-трафик идёт через `tun0` → `badvpn-tun2socks` → SOCKS Xray → TrueNAS → reverse-туннель → Kraken → интернет. Для локальных сетей аплинка и Mac `cloudflared` QUIC действуют прямые исключения.
|
||||
|
||||
DNS клиентов обслуживает отдельная служба `clientdns` через тот же туннель. Системный dnsmasq и DNS самого роутера работают отдельно. SSH: `ssh root@192.168.6.1`.
|
||||
|
||||
## Identity
|
||||
|
||||
@@ -40,21 +41,13 @@ LAN clients
|
||||
-> selected exceptions: table main -> WAN device
|
||||
```
|
||||
|
||||
WAN devices are `eth0` and `usb0` in the `wan` firewall zone. **As of 2026-09-17 `eth0` is the active WAN** (it carries the default route); `usb0` is idle. At the 2026-07-22 capture this was inverted — `eth0` had no carrier and `usb0` held the default route.
|
||||
|
||||
Default route at the 2026-07-22 capture (historical, no longer active):
|
||||
|
||||
```text
|
||||
default via 10.252.240.133 dev usb0 src 10.252.240.230
|
||||
```
|
||||
|
||||
Current default route (2026-09-17):
|
||||
В зоне `wan` находятся `eth0` и `usb0`; активный аплинк — `eth0`.
|
||||
|
||||
```text
|
||||
default via 192.168.2.2 dev eth0 proto static src 192.168.2.157
|
||||
```
|
||||
|
||||
That is, Rasputin gets `192.168.2.157/24` from the upstream router `192.168.2.2` and reaches the internet through it; `192.168.2.2` in turn sits behind GPON `192.168.0.1`.
|
||||
Аплинк: Rasputin → `192.168.2.2` → GPON `192.168.0.1`. Туннель подключается к TrueNAS `192.168.2.197:8443` через локальную сеть аплинка.
|
||||
|
||||
VPN table:
|
||||
|
||||
@@ -137,7 +130,7 @@ dhcp.lan.interface='lan'
|
||||
dhcp.lan.start='100'
|
||||
dhcp.lan.limit='150'
|
||||
dhcp.lan.leasetime='12h'
|
||||
dhcp.lan.dhcp_option='6,1.1.1.1,1.0.0.1'
|
||||
dhcp.lan.dhcp_option='6,192.168.6.1'
|
||||
dhcp.lan.dhcpv4='server'
|
||||
dhcp.lan.dhcpv6='server'
|
||||
dhcp.lan.ra='server'
|
||||
@@ -163,6 +156,233 @@ Backup made before this change:
|
||||
/etc/config/dhcp.bak.20260714-195408
|
||||
```
|
||||
|
||||
## Клиентский DNS через туннель
|
||||
|
||||
DHCP выдаёт клиентам `192.168.6.1`:
|
||||
|
||||
```text
|
||||
dhcp.lan.dhcp_option='6,192.168.6.1'
|
||||
```
|
||||
|
||||
```text
|
||||
LAN-клиент → адрес Rasputin:53 (UDP/TCP)
|
||||
→ firewall dstnat_lan → redirect :1053
|
||||
→ отдельный dnsmasq службы clientdns
|
||||
→ локальные имена: системный dnsmasq 127.0.0.1:53
|
||||
→ внешний DNS: отдельный Xray 127.0.0.1:1054
|
||||
→ SOCKS основного Xray 127.0.0.1:1080
|
||||
→ VLESS → TrueNAS → reverse-туннель → Kraken
|
||||
→ Cloudflare: A/AAAA через DoH; другие типы через DNS-over-TCP
|
||||
```
|
||||
|
||||
`clientdns` не меняет upstream системного dnsmasq и встроенный DNS основного Xray. Системный dnsmasq слушает порт 53 и использует `8.8.8.8` из `/tmp/resolv.conf.d/resolv.conf.auto`; запросы самого роутера не перенаправляются. DNS аплинка `192.168.2.2` настроен на `1.1.1.1` и полученный по WAN `192.168.0.1`.
|
||||
|
||||
Обрабатываются только входящие из LAN TCP/UDP-запросы к DNS-адресам Rasputin: `192.168.6.1`, `fd3b:153e:9be9::1` и `fe80::34ae:87ff:fe04:8dd`. Запросы к произвольным внешним DNS-адресам это правило не перехватывает. При смене LAN IPv6-адресов нужно обновить `/etc/clientdns/redirect.nft`.
|
||||
|
||||
Общая передача клиентского UDP через текущий tun2socks не настроена. Для DNS это не требуется: клиентский UDP заканчивается на Rasputin, а дальше запрос идёт по TCP через прокси. При недоступности основного Xray/reverse-туннеля внешний клиентский DNS также недоступен; прямого fallback через WAN нет.
|
||||
|
||||
### Файлы и параметры clientdns
|
||||
|
||||
`/etc/init.d/clientdns` — отдельная служба procd с двумя экземплярами: `doh` (Xray) и `resolver` (dnsmasq). Автозапуск включён, `START=100`, `STOP=10`; для обоих процессов настроен `respawn 3600 5 5`.
|
||||
|
||||
`/etc/clientdns/dnsmasq.conf`:
|
||||
|
||||
```ini
|
||||
# Dedicated client resolver; the system dnsmasq remains on port 53.
|
||||
port=1053
|
||||
interface=br-lan
|
||||
interface=lo
|
||||
bind-dynamic
|
||||
no-resolv
|
||||
no-poll
|
||||
no-hosts
|
||||
cache-size=1000
|
||||
edns-packet-max=1232
|
||||
server=127.0.0.1#1054
|
||||
# Preserve the existing router's local name service.
|
||||
server=/lan/local/127.0.0.1#53
|
||||
server=//127.0.0.1#53
|
||||
server=/6.168.192.in-addr.arpa/ip6.arpa/127.0.0.1#53
|
||||
user=dnsmasq
|
||||
group=dnsmasq
|
||||
log-facility=/tmp/clientdns-dnsmasq.log
|
||||
```
|
||||
|
||||
Локальные домены `lan`, `local`, имена без доменной части, обратные запросы для `192.168.6.0/24` и `ip6.arpa` передаются прежнему dnsmasq. Клиентский экземпляр не раздаёт DHCP.
|
||||
|
||||
`/etc/clientdns/xray.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning",
|
||||
"access": "/tmp/clientdns-xray-access.log",
|
||||
"error": "/tmp/clientdns-xray-error.log"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "clientdns-in",
|
||||
"listen": "127.0.0.1",
|
||||
"port": 1054,
|
||||
"protocol": "dokodemo-door",
|
||||
"settings": {
|
||||
"address": "1.1.1.1",
|
||||
"port": 53,
|
||||
"network": "tcp,udp"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"tag": "tunnel",
|
||||
"protocol": "socks",
|
||||
"settings": {
|
||||
"servers": [
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"port": 1080
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "dns-out",
|
||||
"protocol": "dns",
|
||||
"settings": {
|
||||
"network": "tcp",
|
||||
"address": "1.1.1.1",
|
||||
"port": 53,
|
||||
"nonIPQuery": "skip"
|
||||
},
|
||||
"proxySettings": {
|
||||
"tag": "tunnel"
|
||||
}
|
||||
}
|
||||
],
|
||||
"routing": {
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": [
|
||||
"clientdns-in"
|
||||
],
|
||||
"outboundTag": "dns-out"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": [
|
||||
"clientdns-upstream"
|
||||
],
|
||||
"outboundTag": "tunnel"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
"https://1.1.1.1/dns-query"
|
||||
],
|
||||
"queryStrategy": "UseIP",
|
||||
"tag": "clientdns-upstream"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
У отдельного Xray нет собственного VLESS-подключения: он использует существующий SOCKS `127.0.0.1:1080`. A/AAAA разрешаются через `https://1.1.1.1/dns-query`; остальные типы (`MX`, `TXT`, `HTTPS` и другие) передаются к `1.1.1.1:53` по TCP через тот же SOCKS. `UseIP` относится только к отдельному DNS-процессу; основной Xray сохраняет `UseIPv4`.
|
||||
|
||||
Подключение правил в `/etc/config/firewall`:
|
||||
|
||||
```uci
|
||||
config include 'clientdns_redirect'
|
||||
option type 'nftables'
|
||||
option path '/etc/clientdns/redirect.nft'
|
||||
option chain 'dstnat_lan'
|
||||
option position 'chain-prepend'
|
||||
```
|
||||
|
||||
`/etc/clientdns/redirect.nft`:
|
||||
|
||||
```nft
|
||||
ip daddr 192.168.6.1 meta l4proto { tcp, udp } th dport 53 counter redirect to :1053 comment "clientdns-v4"
|
||||
ip6 daddr { fd3b:153e:9be9::1, fe80::34ae:87ff:fe04:8dd } meta l4proto { tcp, udp } th dport 53 counter redirect to :1053 comment "clientdns-v6"
|
||||
```
|
||||
|
||||
### Управление и диагностика clientdns
|
||||
|
||||
На роутере:
|
||||
|
||||
```sh
|
||||
/etc/init.d/clientdns status
|
||||
/etc/init.d/clientdns enabled
|
||||
ubus call service list '{"name":"clientdns"}'
|
||||
/usr/bin/xray run -test -config /etc/clientdns/xray.json < /dev/null
|
||||
/usr/sbin/dnsmasq --test -C /etc/clientdns/dnsmasq.conf
|
||||
netstat -lnp | grep -E ':(1053|1054) '
|
||||
uci show firewall.clientdns_redirect
|
||||
nft list chain inet fw4 dstnat_lan
|
||||
```
|
||||
|
||||
Оба экземпляра procd должны быть `running`; при клиентских запросах растут счётчики `clientdns-v4`/`clientdns-v6`.
|
||||
|
||||
Проверка обработчика на роутере и отдельной маршрутизации локальных имён:
|
||||
|
||||
```sh
|
||||
nslookup www.youtube.com 127.0.0.1:1053
|
||||
nslookup rasputin.lan 127.0.0.1:1053
|
||||
```
|
||||
|
||||
Проверка с LAN-клиента через стандартный DNS-порт:
|
||||
|
||||
```sh
|
||||
dig @192.168.6.1 www.youtube.com A
|
||||
dig +tcp @192.168.6.1 www.youtube.com A
|
||||
dig @192.168.6.1 rasputin.lan A
|
||||
dig @192.168.6.1 gmail.com MX
|
||||
dig @192.168.6.1 cloudflare.com TYPE65
|
||||
curl -4 -fsS -o /dev/null --max-time 20 -w 'HTTP %{http_code}\n' https://www.youtube.com
|
||||
```
|
||||
|
||||
`TYPE65` — запись HTTPS; такой синтаксис подходит для штатного macOS dig. Ожидаются ответы DNS и `HTTP 200`. Запрос на роутере к `127.0.0.1:53` проверяет системный DNS, а не клиентский путь.
|
||||
|
||||
Логи отдельной службы:
|
||||
|
||||
```sh
|
||||
tail -100 /tmp/clientdns-dnsmasq.log
|
||||
tail -100 /tmp/clientdns-xray-error.log
|
||||
tail -100 /tmp/clientdns-xray-access.log
|
||||
grep '1.1.1.1:443' /tmp/xray-access.log | tail -10
|
||||
```
|
||||
|
||||
Перезапуск только клиентского DNS:
|
||||
|
||||
```sh
|
||||
/etc/init.d/clientdns restart
|
||||
```
|
||||
|
||||
### Отключение и откат clientdns
|
||||
|
||||
Подключиться по IP: `ssh root@192.168.6.1`. На роутере выполнить:
|
||||
|
||||
```sh
|
||||
sh /etc/clientdns/rollback.sh
|
||||
```
|
||||
|
||||
Эквивалентные ручные команды:
|
||||
|
||||
```sh
|
||||
uci -q delete firewall.clientdns_redirect
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall reload
|
||||
/etc/init.d/clientdns stop
|
||||
/etc/init.d/clientdns disable
|
||||
```
|
||||
|
||||
После этого клиентские запросы снова обрабатывает исходный dnsmasq на порту 53. Менять DHCP или настройки клиентов не нужно. Возвращается обычный DNS через WAN, вместе с его ограничениями.
|
||||
|
||||
Копия скрипта отката и исходные конфиги находятся на роутере в `/root/clientdns-backup-20261030-134826/`: `rollback.sh`, `firewall`, `firewall.uci`, `dhcp`, `xray-config.json`. Для отключения clientdns достаточно удалить его отдельный блок firewall; восстановление всего firewall из копии может затереть другие последующие изменения.
|
||||
|
||||
При полном удалении сначала выполнить откат, затем удалить `/etc/init.d/clientdns` и `/etc/clientdns/`. Нельзя удалять `redirect.nft`, пока на него ссылается включённый блок firewall.
|
||||
|
||||
## VLESS / Xray Stack
|
||||
|
||||
Packages present include:
|
||||
@@ -185,20 +405,23 @@ Runtime processes:
|
||||
|
||||
```text
|
||||
badvpn-tun2socks --tundev tun0 --netif-ipaddr 10.99.0.2 --netif-netmask 255.255.255.252 --socks-server-addr 127.0.0.1:1080 --loglevel none
|
||||
/usr/bin/xray run -confdir /etc/xray -config /etc/xray/config.json -format json
|
||||
/usr/bin/xray run -config /etc/xray/config.json -format json
|
||||
```
|
||||
|
||||
`v2raya` is installed, but the observed UCI service config previously had `enabled='0'`. The active traffic path is the custom `tunvpn` service plus direct Xray config.
|
||||
|
||||
### Xray Config
|
||||
|
||||
File:
|
||||
Основной Xray управляется OpenWrt procd через `/etc/init.d/xray`. Конфиг: `/etc/xray/config.json`; UCI: `/etc/config/xray`; ресурсы: `/usr/share/xray`. Автозапуск включён.
|
||||
|
||||
```text
|
||||
/etc/xray/config.json
|
||||
xray.enabled.enabled='1'
|
||||
xray.config.conffiles='/etc/xray/config.json'
|
||||
xray.config.datadir='/usr/share/xray'
|
||||
xray.config.format='json'
|
||||
```
|
||||
|
||||
Structure:
|
||||
SOCKS-вход: `127.0.0.1:1080`. Выход: VLESS поверх WebSocket/TLS к TrueNAS `192.168.2.197:8443`, SNI/Host `vpn.mallexxx.duckdns.org`, путь `/vless`. UUID в документации скрыт; брать его из действующего конфига.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -222,12 +445,11 @@ Structure:
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "188.239.191.235",
|
||||
"port": 443,
|
||||
"address": "192.168.2.197",
|
||||
"port": 8443,
|
||||
"users": [
|
||||
{
|
||||
"id": "<redacted-vless-user-id>",
|
||||
"flow": "xtls-rprx-vision",
|
||||
"id": "<VLESS_UUID>",
|
||||
"encryption": "none"
|
||||
}
|
||||
]
|
||||
@@ -235,26 +457,104 @@ Structure:
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"serverName": "node3.sysnx.net",
|
||||
"publicKey": "<redacted-reality-public-key>",
|
||||
"shortId": "<redacted-reality-short-id>",
|
||||
"fingerprint": "qq"
|
||||
"network": "ws",
|
||||
"security": "tls",
|
||||
"tlsSettings": {
|
||||
"serverName": "vpn.mallexxx.duckdns.org"
|
||||
},
|
||||
"wsSettings": {
|
||||
"path": "/vless",
|
||||
"headers": {
|
||||
"Host": "vpn.mallexxx.duckdns.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "direct",
|
||||
"protocol": "freedom"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
"protocol": "blackhole"
|
||||
}
|
||||
],
|
||||
"routing": {
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"rules": [
|
||||
{ "type": "field", "outboundTag": "proxy", "network": "tcp,udp" }
|
||||
{
|
||||
"type": "field",
|
||||
"protocol": [
|
||||
"bittorrent"
|
||||
],
|
||||
"outboundTag": "block"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
{
|
||||
"address": "223.5.5.5",
|
||||
"port": 53
|
||||
},
|
||||
{
|
||||
"address": "8.8.8.8",
|
||||
"port": 53
|
||||
}
|
||||
],
|
||||
"queryStrategy": "UseIPv4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Secrets are intentionally redacted in this note. The live file on the router contains the actual VLESS UUID and REALITY parameters.
|
||||
### Перезапуск и диагностика Xray
|
||||
|
||||
Команды выполняются на Rasputin после `ssh root@192.168.6.1`.
|
||||
|
||||
Проверить конфиг перед перезапуском; успешный результат — `Configuration OK.`:
|
||||
|
||||
```sh
|
||||
/usr/bin/xray run -test -config /etc/xray/config.json < /dev/null
|
||||
```
|
||||
|
||||
Перезапустить только основную службу Xray:
|
||||
|
||||
```sh
|
||||
/etc/init.d/xray restart
|
||||
/etc/init.d/xray status
|
||||
```
|
||||
|
||||
Проверить автозапуск и состояние процесса под procd:
|
||||
|
||||
```sh
|
||||
/etc/init.d/xray enabled
|
||||
ubus call service list '{"name":"xray"}'
|
||||
uci show xray
|
||||
netstat -lnp | grep '127.0.0.1:1080'
|
||||
```
|
||||
|
||||
`status` должен выводить `running`; `enabled` завершается с кодом 0, если автозапуск включён. В ответе ubus у экземпляра `xray` должно быть `"running": true`; TCP-порт `127.0.0.1:1080` должен слушаться.
|
||||
|
||||
Логи:
|
||||
|
||||
```sh
|
||||
tail -100 /tmp/xray-error.log
|
||||
tail -100 /tmp/xray-access.log
|
||||
logread -e xray
|
||||
```
|
||||
|
||||
Файлы в `/tmp` очищаются при перезагрузке. В access-log `[socks-in >> proxy]` означает передачу запроса в основной VLESS-выход.
|
||||
|
||||
Сквозная проверка основного прокси с удалённым разрешением имени:
|
||||
|
||||
```sh
|
||||
curl -4 -fsS --max-time 20 --socks5-hostname 127.0.0.1:1080 https://api.ipify.org
|
||||
curl -4 -fsS -o /dev/null --max-time 20 --socks5-hostname 127.0.0.1:1080 -w 'HTTP %{http_code}\n' https://www.youtube.com
|
||||
```
|
||||
|
||||
Первый запрос должен показать текущий внешний IP Kraken, второй — `HTTP 200`. IP Kraken динамический; для сравнения получить его непосредственно на Kraken.
|
||||
|
||||
`xray`, `tunvpn` и `clientdns` — разные службы. Перезапуск `xray` не пересоздаёт `tun0` и policy routing; для их проверки использовать `ip rule show`, `ip route show table vpn` и `ip link show tun0`. Команда `/etc/init.d/tunvpn restart` перезапускает tun2socks и маршрутизацию. Клиентский DNS перезапускается через `/etc/init.d/clientdns restart`. Не использовать `killall xray`: он остановит также отдельный процесс Xray службы `clientdns`.
|
||||
|
||||
## `tunvpn` Service
|
||||
|
||||
@@ -789,7 +1089,9 @@ Allow-Mac-cloudflared-QUIC-direct
|
||||
Mac 192.168.6.104 UDP/7844 -> main routing table -> WAN direct
|
||||
Mac 192.168.6.173 UDP/7844 -> main routing table -> WAN direct
|
||||
Any LAN client -> 192.168.2.0/24 -> main routing table -> WAN/upstream LAN
|
||||
Other LAN traffic -> vpn routing table -> tun0 -> Xray/VLESS
|
||||
LAN DNS to Rasputin:53 -> clientdns -> SOCKS/Xray -> TrueNAS -> Kraken
|
||||
Other LAN TCP traffic -> vpn routing table -> tun0 -> Xray/VLESS
|
||||
General client UDP via tun2socks -> not configured
|
||||
LAN -> WAN not explicitly allowed -> rejected by KillSwitch
|
||||
```
|
||||
|
||||
|
||||
Reference in new issue
Block a user