Правила - статичная таблица; режим script позволяет куску JavaScript решать судьбу каждого соединения динамически: по времени суток, порту, резолвнутому IP, любой комбинации. Функция Premium-ядра, в CFW работает из коробки.

Включение

Добавьте верхнеуровневую секцию script и поставьте mode: script (в переключателе режимов клиента появится Script):

mode: script
script:
  code: |
    function main(ctx, metadata) {
      // вернуть имя выхода: группа / "DIRECT" / "REJECT"
      if (metadata.host && metadata.host.endsWith("company.com")) {
        return "DIRECT";
      }
      // ночной игровой трафик напрямую, днём через прокси
      const hour = new Date().getHours();
      if (metadata.dst_port === 3074 && hour >= 1 && hour <= 7) {
        return "DIRECT";
      }
      // остальное - обратно движку правил
      return ctx.resolveOutbound(metadata) ?? "Select";
    }

Полезные поля metadata

ПолеСмысл
hostДомен назначения (пустой при соединении на голый IP)
dst_ip / dst_portIP и порт назначения
src_ip / src_portАдрес источника (различать устройства при allow-lan)
networktcp / udp
process_nameПроцесс-инициатор (под TUN)

Контекст даёт и помощников - ctx.geoip(ip), ctx.resolveIP(host) - для логики «сначала резолвим, потом решаем», которую правилами не выразить.

Шорткаты script: лёгкий вариант

Не хочется забирать весь mode - опишите короткие выражения и ссылайтесь на них из обычных правил:

script:
  shortcuts:
    late-night-game: dst_port == 3074 and now.hour < 7

rules:
  - SCRIPT,late-night-game,DIRECT
  - MATCH,Select

Оговорки

  • Скрипт выполняется на каждом соединении; тяжёлая логика умножает задержку. Всё, что выражается правилами, - правилами.
  • Упавший скрипт валит соединение; после правок смотрите Logs.
  • Никогда не запускайте скрипты из чужих конфигов - чем мощнее функция, тем опаснее вредоносный профиль.
Совет: условия по времени и порту лаконичнее всего в shortcuts; полный main пишите, лишь когда нужны вызовы резолвинга или многосоставная логика.