ipset-dns на ОС Entware

Тут будет некоторая информация по keenetic
Аватара пользователя
Артём Мамзиков
Admin
Сообщения: 866
Стаж: 5 лет 9 месяцев
Откуда: Вологодская область
Поблагодарили: 41 раз
Контактная информация:

ipset-dns на ОС Entware

Сообщение Артём Мамзиков »

ipset-dns— это легкий сервер пересылки DNS, который добавляет все разрешенные IP-адреса в заданный netfilter ipset или тут ipset-dns . Он предназначен для использования в сочетании с dnsmasq директивой upstream server.

Практические примеры использования включают маршрутизацию трафика через заданный шлюз для определенных веб-сервисов или веб-страниц, которые не имеют заранее предсказуемых IP-адресов и вместо этого полагаются на головокружительные массивы разрешений DNS.

Например нам нужно vk.com пустить через другую сеть, в текущий момент у нас отбился 1 IP адрес, чуть позже другой и заносить все их в правило очень не удобно, утилита же сама из доменного имени vk.com берет ip адреса и подставляет в правила.

Из пакета установка ipset-dns-keenetic_0.2-1_all.ipk

Для keneetic из пакета Взято тут

Код: Выделить всё

opkg install http://bin.entware.net/mipselsf-k3.4/test/ipset-dns-keenetic_0.2-1_all.ipk
Занесенный через веб форму адрес сайта днс => передается на порт 5353 запущеной службы ipset-dns
=> ipset-dns => берет данные какое подключение использовать, через какую подсеть, какой днс из bypass.conf =>
далее команда ipset-dns получает имя с порт 5353 и переводит его в IP и заносит в набор bypass
далее => проверяются различные данные что существует и подключено все что нужно, если да =>
создается маршрут route и правила iptables.

Для настройки вам понадобится имя и подсеть VPN-интерфейса.
Просмотреть

Код: Выделить всё

ip address
В примере это nwg1 и 10.7.0.0/24:
37: nwg1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1324 qdisc noqueue qlen 50
link/[65534]
inet 10.7.0.8/24 scope global nwg1

Прописываем в переменные VPN_NAME и VPN_SUBNET

Код: Выделить всё

mcedit /opt/etc/bypass.conf
Стартуем службу ipset-dns

Код: Выделить всё

/opt/etc/init.d/S52ipset-dns start
Советую перенести на другой порт. Порт 5353 может использоваться
Проверка свободности порта

Код: Выделить всё

netstat -nlpu | grep :5353
udp 0 0 0.0.0.0:5353 0.0.0.0:* 658/avahi-daemon
если используется smb и/или mdns
Ошибка при старте если порт занят "Race Condition"
О работе утилиты
Показать
Нет, если указать другой порт, служба ipset-dns может не понять, что поступившие данные являются DNS-запросом.

Почему это происходит:
Стандартные порты для DNS:

DNS-запросы обычно обрабатываются на портах 53 (UDP или TCP) для обычных DNS-запросов и ответов, а также на порте 5353 для Multicast DNS (mDNS). Эти порты являются стандартом и используются по умолчанию для идентификации DNS-трафика.
Связь между портом и протоколом:

Многие сетевые службы ожидают, что определенные типы данных будут приходить на конкретные порты. Например, HTTP-серверы ожидают HTTP-запросы на порте 80 или 443. Точно так же, если служба получает данные на DNS-портах, она ожидает, что это DNS-запросы.
Если изменить порт, например, на 8080 или 22, это может вызвать недоразумение, так как служба будет ожидать другой тип данных.
Анализ данных:

Хотя анализ данных на уровне пакетов возможен, и теоретически можно попытаться определить, что поступающие данные соответствуют формату DNS-запроса, это не является стандартным поведением для большинства служб. Обычно службы работают в рамках стандартных портов для упрощения конфигурации и надежности.
Конфигурация службы:

Если настроить ipset-dns на использование нестандартного порта, то это будет работать только в случае, если другая служба или клиент также настроены на отправку DNS-запросов именно на этот порт.
Это может усложнить настройку и взаимодействие с другими системами, поскольку большинство клиентов и DNS-серверов предполагают использование стандартных портов.
Вывод:
ipset-dns будет ожидать DNS-запросы на стандартных портах. Если вы укажете другой порт, служба может не распознать данные как DNS-запросы, и в результате DNS-запросы не будут корректно обработаны. Чтобы гарантировать корректную работу, лучше придерживаться стандартных портов для DNS.

для получения IP-адреса доменного имени example.com с использованием DNS-сервера 8.8.8.8, служба ipset-dns выполняет эквивалент команды dig @8.8.8.8 example.com

Служба ipset-dns не вызывает dig или любую другую утилиту напрямую. Вместо этого она работает на более низком уровне, взаимодействуя с DNS-серверами через сетевые протоколы, что позволяет ей идентифицировать и обрабатывать DNS-запросы.

Как ipset-dns понимает, что это DNS-запрос:
Работа на уровне сетевых сокетов:

ipset-dns слушает на определенном порту (в вашем случае на 5353). Этот порт предназначен для приема DNS-запросов.
Когда поступает запрос, служба читает данные, поступающие через этот сокет, и определяет, что это DNS-запрос, на основе содержимого и формата пакетов.
Формат DNS-запросов:

DNS-запросы имеют строго определенный формат. Запрос состоит из заголовка и тела, которые включают информацию о типе запроса (например, A-запись), доменном имени, типе записи и других параметрах.
ipset-dns анализирует этот формат, чтобы понять, что поступивший запрос является DNS-запросом.
Взаимодействие с DNS-сервером:

ipset-dns создает DNS-запрос в соответствии с протоколом DNS и отправляет его на указанный DNS-сервер (например, 8.8.8.8).
Этот запрос отправляется напрямую через UDP или TCP сокет, что и является основным механизмом работы службы.
Почему не используется dig:
Прямое взаимодействие: ipset-dns напрямую работает с протоколом DNS, отправляя и получая пакеты на уровне сети. Утилиты, такие как dig, используются в основном для удобства пользователей в командной строке и для диагностики, но службе, работающей на уровне сети, не нужно использовать такие утилиты.

Низкоуровневое программирование: Программа ipset-dns написана на языке, который позволяет ей взаимодействовать с сокетами (например, C или Python с библиотеками для работы с сетью). Это позволяет ей отправлять DNS-запросы и получать ответы без использования внешних инструментов.

Таким образом, ipset-dns понимает, что это DNS-запрос, на основании формата поступающих данных и правильно обрабатывает их, отправляя запросы на указанный DNS-сервер, не вызывая при этом утилиты вроде dig
В веб интерфейсе роутера Сетевые правила → Интернет фильтры → Настройка DNS
нажимаем +Добавить сервер
Тип сервера DNS: По умолчанию
Адрес сервера DNS: 192.168.1.1:5353
Домен: имя-сайта.ru
Подключение: Любой интерфейс
или через CLI-интерфейс:
ip name-server 192.168.1.1:5353 имя-сайта.ru

где 192.168.1.1 — IP-адрес роутера
Число записей ограничено 64.
Изменение списка доменов применяется налету. Для того, чтобы новые настройки вступили в силу ничего делать не надо.

Имя пакета: ipset-dns-keenetic версия: 0.2-1
Зависимые пакеты:
libc, libssp, librt, libpthread, ipset, ipset-dns, iptables

Системные переменные keenetic

/opt/etc/init.d/S52ipset-dns

Код: Выделить всё

#!/bin/sh

# ----------------------------------------------------------------------------
# Описание скрипта:
#
# Этот скрипт предназначен для настройки и запуска системы обхода (bypass) для
# определенных DNS-записей. Он создает набор IP-адресов, добавляет в него
# DNS-сервер, настраивает правило маршрутизации и запускает службу обхода
# DNS-записей.
#
# ----------------------------------------------------------------------------

# Установка пути к исполняемым файлам
PATH=/opt/sbin:/opt/bin:/opt/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Чтение файла конфигурации
. /opt/etc/bypass.conf

# ----------------------------------------------------------------------------
# Параметры скрипта:
#
# $SET_NAME - имя набора IP-адресов, который будет создан и использован для обхода
# $DNS - DNS-сервер, который будет использован для разрешения DNS-записей
#
# ----------------------------------------------------------------------------

#При запуске входной аргумент(переменная) $1 у нас start  /opt/etc/init.d/S52ipset-dns start
#Проверка что команда start=start  если да выполняем скрипт дальше

if [ "$1" = "start" ]; then
    # Создание набора IP-адресов с именем $SET_NAME и типом hash:ip (с использованием хэш-таблицы для хранения IP-адресов.)
    ipset create $SET_NAME hash:ip

    # Добавление DNS-сервера $DNS в набор $SET_NAME
    # Пример Добавляет IP-адрес 8.8.8.8 (публичный DNS-сервер Google) в набор "bypass".
    ipset add $SET_NAME $DNS

    # Настройка правила маршрутизации, которое перенаправляет пакеты с меткой fwmark 1001 в таблицу маршрутизации 1001
    # Метка "fwmark" используется для пометки пакетов в iptables.
    ip rule add fwmark 1001 table 1001

    # Запуск службы обхода DNS-записей с помощью команды ipset-dns 
    # по имени сайта из веб интерфейса получаем IP и заносим в список $SET_NAME
    ipset-dns $SET_NAME $SET_NAME 0.0.0.0:5353 $DNS
    #Пример: Команда ipset-dns используется для динамического обновления наборов IP-адресов на основе DNS-записей
    #Добавляет DNS-запись для набора "bypass" с использованием DNS-сервера 8.8.8.8.
     #Параметр 0.0.0.0:5353 указывает на локальный DNS-сервер, который слушает на порту 5353.
fi
/opt/etc/ndm/ifstatechanged.d/010-bypass-table.sh

Код: Выделить всё

#!/bin/sh

# ----------------------------------------------------------------------------
#
# Этот скрипт предназначен для настройки маршрутизации для системы обхода (bypass)
# при подключении к VPN. Он проверяет состояние подключения и настраивает
# маршрутизацию для таблицы 1001.
#
# ----------------------------------------------------------------------------

# Чтение файла конфигурации
. /opt/etc/bypass.conf

# ----------------------------------------------------------------------------
# Проверка параметров запуска скрипта:
# $1 - параметр запуска скрипта, должен быть равен "hook" если нет выход
# $system_name - имя системы, должно быть равно $VPN_NAME если нет выход
# bypass - набор IP-адресов, должен быть не пустым если пусто выход
# connected, link, up - состояние подключения, должны быть равны "yes-up-up" если нет выход
# На 4.0А20 link-yes-up-up не появляется Видимо в 4.0 что то изменилось  вот так , link-no-up-up > connected-yes-up-up
# ----------------------------------------------------------------------------

[ "$1" == "hook" ] || exit 0
[ "$system_name" == "$VPN_NAME" ] || exit 0
[! -z "$(ipset --quiet list bypass)" ] || exit 0
[ "${connected}-${link}-${up}" == "yes-up-up" ] || exit 0

# ----------------------------------------------------------------------------
# Настройка маршрутизации для таблицы 1001:
# Если маршрут по умолчанию не установлен для таблицы 1001, то добавляем его
# ----------------------------------------------------------------------------

if [ -z "$(ip route list table 1001)" ]; then
    ip route add default dev $system_name table 1001
fi
/opt/etc/ndm/netfilter.d/010-bypass-netfilter.sh

Код: Выделить всё

#!/bin/sh

# ----------------------------------------------------------------------------
# Описание скрипта:
#
# Этот скрипт предназначен для настройки правил iptables для системы обхода (bypass)
# при подключении к VPN. Он проверяет состояние подключения и настраивает
# правила iptables для таблицы mangle.
#
# ----------------------------------------------------------------------------

# Чтение файла конфигурации
. /opt/etc/bypass.conf

# ----------------------------------------------------------------------------
# Проверка параметров запуска скрипта:
# $type - тип таблицы, должен быть не равен "ip6tables" если равен ipv6 выходим
# $table - имя таблицы, должно быть равно "mangle" если равно выходим
# $VPN_NAME - имя VPN-интерфейса, должно быть доступно если имя не найдено выходим
# bypass - набор IP-адресов, должен быть не пустым если пусто выходим
# ----------------------------------------------------------------------------

[ "$type" == "ip6tables" ] && exit
[ "$table"!= "mangle" ] && exit
[ -z "$(ip link list | grep $VPN_NAME)" ] && exit
[ -z "$(ipset --quiet list bypass)" ] && exit

# ----------------------------------------------------------------------------
# Настройка правил iptables для таблицы mangle:
# Если правила для bypass не установлены, то добавляем их
# ----------------------------------------------------------------------------
if [ -z "$(iptables-save | grep bypass)" ]; then
    # Правило проверяет пакеты, которые не исходят из подсети, хранящейся в переменной VPN_SUBNET,
    # имеют состояние NEW в conntrack и совпадают с набором "bypass" в ipset.
    # Если пакет удовлетворяет этим условиям, ему присваивается метка 1001.
    iptables -w -t mangle -A PREROUTING! -s $VPN_SUBNET -m conntrack --ctstate NEW -m set --match-set bypass dst -j CONNMARK --set-mark 1001

    # Добавляем правило для восстановления метки соединения
    # добавляет новое правило iptables в таблицу "mangle".
    # Правило проверяет пакеты, которые не исходят из подсети, хранящейся в переменной VPN_SUBNET, и совпадают с набором "bypass" в ipset.
   # Если пакет удовлетворяет этим условиям, ему восстанавливается метка, которая была ранее присвоена.
    iptables -w -t mangle -A PREROUTING! -s $VPN_SUBNET -m set --match-set bypass dst -j CONNMARK --restore-mark
fi
Файл конфигурации:
/opt/etc/bypass.conf

Код: Выделить всё

# Указать через какой DNS проверять доменное имя
DNS=8.8.8.8
# Имя
SET_NAME=bypass
# Имя через которое подключатся (vpn)
VPN_NAME=nwg1
# Адресация данной сети
VPN_SUBNET=10.7.0.0/24
отлов нужных событий сперва собираю все возможные варианты, положив в нужную папку /opt/etc/ndm/<name it>.d такое:

Код: Выделить всё

#!/bin/sh

LOG='/opt/tmp/hook.log'

echo -e "\n\n--- $(date '+%T') $0 fired ---" >> $LOG
echo $@ >> $LOG
set | grep -vE "^'\$|^HOME|^HOSTNAME|^IFS|^LANG|^LD_|^LINENO|^LOG|^NDM_MOUNT|^OPTIND|^PATH|^PPID|^PS|^PWD|^SHELL|^SHLVL|^TERM|^timezone|^USER|^FUNCNAME"  >> $LOG

exit 0
Пример работы
если направлено имя сайта ya.ru на порт 5353 при помощи команды ipset-dns bypass bypass 0.0.0.0:5353 8.8.8.8, то оно будет переведено в IP-адрес.
Когда вы запускаете команду ipset-dns bypass bypass 0.0.0.0:5353 8.8.8.8, она отправляет DNS-запрос на сервер 8.8.8.8 для разрешения имени ya.ru
и получает в ответ IP-адрес, соответствующий этому имени.
После получения IP-адреса, команда ipset-dns добавляет этот IP-адрес в набор bypass. Таким образом, IP-адрес ya.ru будет добавлен в набор bypass
и будет доступен для использования в правилах маршрутизации.
Например, если ya.ru имеет IP-адрес 87.250.250.242, то команда ipset-dns bypass bypass 0.0.0.0:5353 8.8.8.8 добавит этот IP-адрес в набор bypass.
Вы можете проверить содержимое набора bypass с помощью команды ipset list bypass, чтобы увидеть добавленный IP-адрес.

Вопросы ответы с форума собраны в одном месте

В реальном времени происходит обращение к этой утилите по домену прописанному через форму добавления DNS серверов в Интернет фильтрах. Утилита резолвит домен и хранит в оперативной памяти список полученных IP адресов и создает пользовательские маршруты к ним через настроенный в конфиге VPN. Каждое новое обращение к этому домену может добавлять в этот список новые IP адреса, если у домена их множество.
если DNS-сервер в ответ присылает сразу несколько A/AAAA-записей, то они заносятся в ipset сразу все.

1) Я правильно понимаю, что этот список адресов и маршруты не сохраняется на флэш память устройства не расходуя её ресурс, а при перезагрузке теряются и пополняются заново по мере обращения?
Да, всё в памяти. Решение, по сути, три статичных файла (010-bypass-netfilter.sh, 010-bypass-table.sh, bypass.conf, S52ipset-dns) обвязки вокруг iptables и ipset.
Никаких логов или динамических конфигов у приведённого решения нет, все файлы статичные. Ни USB-флешку, ни флешку роутера протирать не будут.

2) Что происходит если VPN не подключен? Маршрут по умолчанию?
Ничего. Таблица наполняется адресами, но роутинг ничем не отличается от роутинга по умолчанию.

3) Адреса субдоменов автоматом также добавляются при обращении к ним. Это уже прошивка сама перенаправляет DNS запросы к субдоменам на резолвер утилиты? Какова глубина субдоменов?
Прошивка. Глубина бесконечна.

4) Очистка списка IP адресов от устаревших происходит только путем перезагрузки устройства?
Да. Понимаю, что при высоких аптаймах сет может накапливать лишнее, но при точечном обходе я бы не стал заморачиваться. Если хочется такое реализовать, то создавайте ipset сразу указывая время жизни элементов и ограничивайте TTL записей DNS-кэша в прошивочном сервисе с помощью dns-proxy max-ttl …

5) Будет ли видно эти маршруты в веб-интерфейсе роутера?
Нет. Прошивка не отображает роутинг по таблицам/сетам.

6) будет ли это работать, если в качестве DNS на роутере прописаны DOT или DOH? Обычные запросы ведь при этом отсекаются или перенаправляются. Сработает ли направление по домену на DNS утилиты?
Работает по домену.
Можно выбрать любой DNS-сервер для работы утилиты ipset-dns в конфиге /opt/etc/bypass.conf
Он первым делом добавится в ipset, следственно, обращения к нему будут идти тем же путём, что и к выбранным для выборочного роутинга ресурсам.
DOT или DOH? можно, только в общем случае не нужно
А если очень надо то
смотрим под какими портами у нас DOH и DOT, вводим команду

Код: Выделить всё

cat /tmp/ndnproxymain.stat
с портами 40500-405++ как раз doh или dot. Запоминаем порты после смотрим какой более быстрее работает тот и оставляем.

Код: Выделить всё

while true; do dig google.com @127.0.0.1 -p 40509 | grep time; sleep 1; done
Меняем DNS в ipset-dns

Код: Выделить всё

mcedit /opt/etc/bypass.conf
DNS=127.0.0.1:40509

При попытке использовать прошивочный DoT/DOH резолвер в логах спамятся ошибки
При этом вроде все работает, странно.

для dot и doh dns из другой оперы для сервера
server=127.0.0.1#40508

При включенном DoH в мозиле или на устройстве, работать не будет правильно?
Не будет. Работает только через прямой DNS запрос к роутеру. Вернее работать то оно в мозиле с DoH сможет, но только при условии что ранее были обращения к этим ресурсам из других браузеров напрямую.

Каждый новый день, когда подключаю VPN (OpenVPN), роутинг на прописанные маршруты сразу же не идёт.
Если снова пере подключить VPN то чаще всего сразу всё начинает бегать как нужно.
Но иногда и с 3-го раза начинает. Что-то там с механизмом обнаружения соединения не совсем в порядке.

После перезагрузки роутера служба иногда не стартует, приходится запускать ее вручную через /opt/etc/init.d/S52ipset-dns start
временное решение ожидание 30 секунд между командами в S52ipset-dns
ipset-dns $SET_NAME $SET_NAME 0.0.0.0:5353 $DNS
sleep 30s
ipset-dns $SET_NAME $SET_NAME 0.0.0.0:5353 $DNS

Другие решения
Что-нибудь основанное на dnsmasq или adguardhome, они так же умеют наполнять ipset по результатам разрешения DNS-имён.



Исходный код ipset-dns

Код: Выделить всё

ipset-dns name-of-v4-ipset name-of-v6-ipset listening-port upstream-dns-server
ipset-dnsпривязывается только к localhost. Демонизируется, если не NO_DAEMONIZE задана переменная окружения. Если name-of-v4-ipsetили name-of-v6-ipsetявляются пустыми строками, то ipset для соответствующего семейства адресов не будет использоваться.

Исходный код github ipset-dns

sample-script.sh

Код: Выделить всё

#!/bin/sh
set -x

#  Внутри dnsmasq.conf у нас есть:
#
#     server=/имя-сайта1/127.0.0.1#39128
#     server=/имя-сайта2/127.0.0.1#39129
#
#Устройства tn11 и tn12 являются сетевыми интерфейсами OpenVPN tun.
#
# Этот скрипт перенаправляет видео с сайт1 через tun12 и сайт2 через tun11.

sets() {
	iptables -t mangle -D PREROUTING -m set --set "$1" dst,src -j MARK --set-mark "$2" 2>/dev/null
	ipset -X "$1" 2>/dev/null
	ipset -N "$1" iphash
	iptables -t mangle -A PREROUTING -m set --set "$1" dst,src -j MARK --set-mark "$2"
}

sets сайт1 1
sets сайт2 2

routes() {
	echo 0 > /proc/sys/net/ipv4/conf/$2/rp_filter
	ip route flush table $1 2>/dev/null
	ip rule del table $1 2>/dev/null
	ip rule add fwmark $1 table $1 priority 1000
	ip route add default via "$(ip route show dev $2 | head -n 1 | cut -d ' ' -f 1)" table $1
}

routes 1 tun12
routes 2 tun11

killall ipset-dns 2>/dev/null
ipset-dns сайт1 "" 39128 8.8.8.8
ipset-dns сайт2 "" 39129 8.8.8.8

killall -SIGHUP dnsmasq # Clear dnsmasq's cache
В файле конфигурации dnsmasq.conf

Код: Выделить всё

server=/имя-сайта/127.0.0.1#1919
Создайте ipset:

Код: Выделить всё

ipset -N имя-сайта iphash
Запустите ipset-dnsсервер:

Код: Выделить всё

ipset-dns имя-сайта 1919 8.8.8.8
Запрос имени хоста:

Код: Выделить всё

host r4---bru02t12.имя-сайта
r4---bru02t12.имя-сайта is an alias for r4.bru02t12.имя-сайта.
r4.bru02t12.имя-сайта has address 74.125.216.51
Обратите внимание, что он был добавлен в ipset:

Код: Выделить всё

ipset -L имя-сайта
Name: имя-сайта
Type: iphash
References: 1
Header: hashsize: 1024 probes: 8 resize: 50
Members:
74.125.216.51


Так же IP сайта можно получить в командной строке командами
некоторые из них:
ping сайт.com
nslookup сайт.com
resolveip сайт.com
nmap -sP сайт.com
named -v сайт.com
dig сайт.com
host сайт.com
getent hosts сайт.com
nslookup
getent



Как обойти перехват DNS
Утечку DNS можете отследить тут
Если у вас настроен DOT, то обращений к незащищенным DNS серверам, в том числе провайдера быть не должно (за исключением некоторых служебных). Дополнительно можно поставить галочку Игнорировать DNS (провайдера) в настройках сети вашего провайдера.
Устанавливаем и настраиваем по инструкции DOH и DOT. Список доступных DOH и DOT тут.
Разрешен транзит запросов галочка означает что если у вас на ПК, Телефоне или любом другом устройстве указан свой DNS он будет работать, если галочку убрать нет только DNS указанный на роутере.
Важно! При включении протокола DoT/DoH все DNS-запросы будут направляться на указанный при настройке адрес сервера. Полученные ранее DNS-серверы от вашего интернет-провайдера и прописанные вручную DNS-серверы использоваться не будут.
Если добавлено в общий профиль домашней сети, либо создать отдельный профиль, после в разделе "интернет фильтры Публичные резолверы" закрепить за устройством.
количество слов: 1224

Вернуться в «Keenetic»