Raspberry Pi + xray между роутером и телевизором

Поделюсь своим опытом настройки.

Дано

  • SmartTV Samsung c TizenOS (т.е. не умеет в прокси и VPN),
  • роутер с OpenWRT 23.05.0 с современным железом (поддержка WiFi 5 и выше),
  • VPS на территории потанцевального противника

Задача

Реализация желания смотреть Ютуб, злоумышленно эксплуатируя уязвимость в виде статьи 29 Конституции РФ.

Решение

sing-box на роутере + пара правил nftables на нём же.

Подробности:

Ставим sing-box

opkg update && opkg install sing-box

Конфиг sing-box

cat /etc/config/sing-box

config sing-box 'main'
        option enabled '1'
        option user 'sing-box'
        option conffile '/etc/sing-box/config.json'
        option workdir '/usr/share/sing-box'

cat /etc/sing-box/config.json

{
  "log": {
    "level": "warn",
    "disabled": false
  },
  "dns": {
    "servers": [
      {
        "tag": "dns-google",
        "address": "tls://8.8.8.8",
        "detour": "vless-xtls-vision-out"
      },
      { //  в моём случае "address" не "local", т.к. на роутере крутится DNS-сервер для WAN и LAN сетей
        //  и настроены разные view для локальных и внешних клиентов.
        //  На интерфейсе 192.168.1.1 я гарантированно попадаю на view LAN и мой домен резолвится в его локальный IP, а не в белый.
        "tag": "dns-local",
        "address": "192.168.1.1", 
        "detour": "direct-out"
      }
    ], //servers
    "rules": [
      {
        "outbound": [
          "direct-out"
        ],
        "server": "dns-local"
      },
      {
        "domain_suffix": [
          "local",
          "home",
          "isp.local.site"
        ],
        "server": "dns-local"
      },
      {
        "outbound": [
          "vless-xtls-vision-out"
        ],
        "server": "dns-google"
      }
    ]
  }, // dns
  "inbounds": [
    {
     "type": "redirect",
     "tag": "redirect-in",
     "listen": "192.168.1.1",
     "listen_port": 3129,
     "sniff": true,
     "tcp_fast_open": true
    },
    {
      "listen": "192.168.1.1",
      "listen_port": 3130,
      "tag": "vless-xtls-vision-mixed-in",
      "type": "mixed"
    }
  ],
  "outbounds": [
    {
      "flow": "xtls-rprx-vision",
      "packet_encoding": "xudp",
      "server": "REDACTED",
      "server_port": 443,
      "tag": "vless-xtls-vision-out",
      "tls": {
        "enabled": true,
        "server_name": "REDACTED",
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        }
      },
      "type": "vless",
      "uuid": "REDACTED"
    },
    {
      "type": "direct",
      "tag": "direct-out"
    },
    {
      "type": "dns",
      "tag": "dns-out"
    }
  ],
  "route": {
    "rules": [
      { // rule for connecting without proxy
        "domain_suffix": [
          "local",
          "home",
          "isp.local.site"
          ],
         "outbound": "direct-out"
      },
        { // Youtube for Samsung Smart TV
          "inbound": "redirect-in",
          "domain_suffix": [
            "youtube.com",
            "youtu.be",
            "googlevideo.com",
            "ytimg.com"
          ],
          "outbound": "vless-xtls-vision-out"
        },
       {
         "rule_set": "antizapret",
         "outbound": "vless-xtls-vision-out"
       },
       {
         "protocol": "dns",
         "outbound": "dns-out"
        },
        {
          "inbound": "redirect-in",
          "outbound": "direct-out"
        },
        {
          "inbound": "vless-xtls-mixed-in",
          "outbound": "vless-xtls-vision-out"
        }
    ], //rules
    "rule_set": [
      { // Remote rule-set will be cached if experimental.cache_file.enabled.
        "tag": "antizapret",
        "type": "remote",
        "format": "binary",
        "url": "https://github.com/savely-krasovsky/antizapret-sing-box/releases/latest/download/antizapret.srs",
        "download_detour": "vless-xtls-vision-out",
        "update_interval": "1d"
      }
    ]
  }
}

Правила nftables

В формате UCI:

/etc/config/firewall

config rule
        option enabled          1
        option name             SamsungTV-block-quick
        option target           REJECT
        option src              lan
        option dest             wan
        option proto            udp
        option src_ip           'SMART.TV.IP.ADDRESS'
        option dest_port        443
        option family           ipv4

config redirect
        option enabled          1
        option name             SamsungTV-redirect-HTTPS-to-sing-box
        option target           DNAT
        option src              lan
        option dest             wan
        option proto            tcp
        option src_ip           'SMART.TV.IP.ADDRESS'
        option src_dport        443
        option dest_ip          '192.168.1.1'
        option dest_port        3129 # port of 'redirect-in' sing-box inbound
        option family           ipv4

В виде правил nftables:

fw4 print:

        chain forward_lan {
                ip saddr SMART.TV.IP.ADDRESS udp dport 443 counter jump reject_to_wan comment "!fw4: DNAT-SamsungTV-block-quick"
        }
        chain dstnat_lan {
                ip saddr SMART.TV.IP.ADDRESS tcp dport 443 counter dnat 192.168.1.1:3129 comment "!fw4: DNAT-SamsungTV-redirect-HTTPS-to-sing-box"
        }

В данном случае блочим QUICK (UDP/443) и редиректим только HTTPS (TCP/443). Можно редиректить и весь трафик Smart TV, но у меня и так прекрасно работает.

Crontab

crontab -e

# restart sing-box every 2 hours to avoid high memory consumption and OOM-killer spawning
0  */2 * * * /etc/init.d/sing-box restart

Итого

Редиректим HTTPS со смартТВ на “redirect”-вход sing-box и ходим на домены, имеющие отношение к YouTube, через прокси.
Также имеем HTTP/SOCKS прокси.
Маршрутизация несложная: сначала на локальные домены и на сайт провайдера лезем напрямую, затем правило для SmartTV, которое редиректит трафик Ютуба в прокси.
Далее бонусом идёт маршрутизация на основе правил Antizapret в новом формате (SRS).
Ещё далее - это скорее fallbacks, до них дело вряд ли дойдёт.

Каждые два часа рестартим sing-box во избежание прихода OOM-killer.
Тут нужно заметить, что sing-box (как и xray) просто не запускается, если ограничить виртуальную память процесса до менее чем 800 МБ. На роутере, как вы понимаете, пока таких объёмов RAM нет. По умолчанию sing-box заявляет себе 1.2 ГБ виртуальной памяти а мы надеемся что ему не понадобится больше, чем у нас есть (у меня на роутере 256 МБ RAM). Поэтому на всякий случай рестартим sing-box каждые 2 часа. На современном роутере (WiFi 5+) это происходит моментально. Почему эти программы требуют (не потребляют!) так много виртуальной памяти - я не погромист, поэтому не знаю, в коде гошечки не колупался.

Бегло протестировал - Ютуб на ТВ заработал как встарь. Пользуйтесь, друзья!
@ValdikSS , привет тебе из Гудлайновской сети!