Closed AltGrF13 closed 3 weeks ago
1.1. роутинг DNS уже пропатчен в #195.
1.2. маркировка для обхода. opt/etc/ndm/ndm
:ip4_firewall_vpn_mark
вместо
ip4tables PREROUTING -t "${table}" -m set --match-set "${IPSET_TABLE_NAME}" dst -j ${VPN_IPTABLES_CHAIN} &>/dev/null
ip4tables OUTPUT -t "${table}" -m set --match-set "${IPSET_TABLE_NAME}" dst -j ${VPN_IPTABLES_CHAIN} &>/dev/null
надо
ip4tables PREROUTING -t "${table}" -i br0 -m set --match-set "${IPSET_TABLE_NAME}" dst -j "${VPN_IPTABLES_CHAIN}" &>/dev/null
2.1. При вызове из консоли
2.1.1. в случае IKEv2. opt/etc/ndm/ndm
:ikev2_net_access_add
ikev2_net_access_add() {
local ikev2_settings=$(curl -s "${LOCALHOST_IP}:79/rci/crypto/virtual-ip-server-ikev2")
# вероятное изменение настроек роутера
ikev2_setup "${ikev2_settings}"
local net_pool=$(echo "${ikev2_settings}" | grep -F -- 'pool-start' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
ready "Добавление гостевого интерфейса \"VPN-сервер IKEv2\" [${net_pool}] завершено" && {
if has_ssr_enable ; then
ip4_add_selected_guest_to_ssr_network 'ikev2'
else
ip4_add_selected_guest_to_vpn_network 'ikev2'
fi
# сохранение в конфигурацию КВАС
add_ikev2_net_to_config
} && when_alert "УСПЕШНО" || when_bad "С ОШИБКОЙ"
}
Ну и к теме этой задачи не относится, но ikev2_setup
сыпал warning'ами, исправил:
ikev2_setup() {
ikev2_data="${1}"
enable=${2:-true}
ikev2_dns=$(get_router_ip)
#TODO: вынести получение параметра в функцию
dns_server=$(echo "${ikev2_data}" | grep -F -- 'dns-server' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
enable=$(echo "${ikev2_data}" | grep -F 'enable' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
nat=$(echo "${ikev2_data}" | grep -F 'nat' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
if [ "${dns_server}" != "${ikev2_dns}" ] || [ "${enable}" != true ] || [ "${nat}" != true ] ; then
# Если DNS отличен от IP роутера, или интерфейс, или NAT отключены
pool_size=$(echo "${ikev2_data}" | grep -F -- 'pool-size' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
pool_start=$(echo "${ikev2_data}" | grep -F -- 'pool-start' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
multi_login=$(echo "${ikev2_data}" | grep -F -- 'multi-login' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
sa_compat=$(echo "${ikev2_data}" | grep -F -- 'sa-compat' | cut -d':' -f2 | sed 's/[\,\" ]//g;')
curl -s -d '{"enable": '"${enable}"', "nat": true, "dns-server": "'"${ikev2_dns}"'", "pool-size": "'"${pool_size}"'", "pool-start": "'"${pool_start}"'", "multi-login": "'"${multi_login}"'", "sa-compat": "'"${sa_compat}"'"}' \
"${LOCALHOST_IP}:79/rci/crypto/virtual-ip-server-ikev2" &> /dev/null
sleep 1
fi
}
2.1.2. в случае именованных интерфейсов при вызове из консоли. bin/libs/vpn
:bridge_access_add
, правила напрямую не добавляются, это произойдёт по триггеру после перезапуска Dnsmasq. Правок нет.
2.2. Триггерное добавление — это в opt/etc/ndm/ndm
цепочка вызовов
ip4_mark_vpn_network
set_guest_nets_rules
ip4_add_guest_to_vpn_network
ip4_add_selected_guest_to_vpn_network
, заменяем последнюю:
# Перенаправляем dns-запросы в dnsmasq
#Example input param:-s 192.168.3.0/24 -i eth3
#Example input param:-i sstp+
#TODO: в ip4_firewall_dns_rules_set использовать вызов этой обёртки
ip4_add_to_dns_routing() {
local iptables_filter="${1}"
local router_ip=$(get_router_ip)
for protocol in tcp udp ; do
if ip4save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${protocol}" | grep -F 53 | grep -F 'DNAT' | grep -F "${router_ip}" | grep -Fq "${DNS_PORT}" ; then
continue
fi
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -A PREROUTING -w -t nat $(echo "${iptables_filter}") -p "${protocol}" --dport 53 -j DNAT --to-destination "${router_ip}":"${DNS_PORT}"
done
}
ip4_add_selected_guest_to_vpn_network() { local net_interface="${1}" if [ -z "${net_interface}" ] ; then error "[${FUNCNAME}] Не передан обязательный параметр — имя интерфейса" fi
if echo "${net_interface}" | grep -q ikev2 ; then
net_interface=$(get_entware_ikev2_inface)
# IKEv2 не имеет отдельного сетевого интерфейса, поэтому запишем и что добавляем, и используемый СИ
local submessage="IKEv2 (${net_interface} "
local net_pool=$(get_ikev2_net_pool)
local iptables_filter="-s ${net_pool} "
else
local submessage="${net_interface} ("
local net_pool=$(get_guest_net "${net_interface}")
local iptables_filter=''
fi
iptables_filter="${iptables_filter}-i ${net_interface}"
log_warning "Подключаем правила гостевого трафика ${submessage}${net_pool}) для VPN."
ip4_add_to_dns_routing "${iptables_filter}"
if fastnet_enabled ; then
if ! iptables-save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${IPSET_TABLE_NAME}" | grep -Fq "${VPN_IPTABLES_CHAIN}" ; then
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -A PREROUTING -w -t mangle $(echo "${iptables_filter}") -m set --match-set "${IPSET_TABLE_NAME}" dst -j "${VPN_IPTABLES_CHAIN}"
fi
else
if [ -z "${net_pool}" ] ; then
error "[${FUNCNAME}] От функции get_guest_net не получен обязательный результат — пул адресов"
fi
# случай основного VPN и отключенного ускорения требует дополнительной проверки
# но именно таким код был изначально, т.е. он точно не "ухудшится"
if ! iptables-save | grep -F 'POSTROUTING' | grep -F "${net_pool}" | grep -F "${net_interface}" | grep -Fq 'MASQUERADE' ; then
iptables -A POSTROUTING -w -t nat -s "${net_pool}" -o "${net_interface}" -j MASQUERADE
fi
fi
}
3. **Отключение роутинга DNS и маркировки для обхода в гостевых**
3.1. в `bin/libs/vpn`:`cmd_bridge_vpn_access_del` добавить строчку
if echo "${guest_bridge_id}" | grep -iq ikev2 ; then
3.2. в bin/libs/vpn
:bridge_vpn_access_del
вместо
# ip4_firewall_rm_selected_guest_net "${guest_bridge_id}"
ip4_firewall_rm_vpn_selected_guest_net "${guest_bridge_id}"
надо
if has_ssr_enable ; then
ip4_firewall_rm_ssr_selected_guest_net "${guest_bridge_id}"
else
ip4_firewall_rm_vpn_selected_guest_net "${guest_bridge_id}"
fi
3.3. opt/etc/ndm/ndm
:ikev2_net_access_del
ikev2_net_access_del() {
ready "Удаление интерфейса \"VPN-сервер IKEv2\" завершено" && {
if has_ssr_enable ; then
ip4_firewall_rm_ssr_selected_guest_net 'ikev2'
else
ip4_firewall_rm_vpn_selected_guest_net 'ikev2'
fi
} && when_alert "УСПЕШНО" || when_bad "С ОШИБКОЙ"
}
3.4. opt/etc/ndm/ndm
:ip4_firewall_rm_vpn_selected_guest_net
# Отключение перехвата dns-запросов в dnsmasq
#Example input param:-s 192.168.3.0/24 -i eth3
#Example input param:-i sstp+
ip4_delete_from_dns_routing() {
local iptables_filter="${1}"
local router_ip=$(get_router_ip)
for protocol in tcp udp ; do
if ! ip4save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${protocol}" | grep -F 53 | grep -F 'DNAT' | grep -F "${router_ip}" | grep -Fq "${DNS_PORT}" ; then
continue
fi
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -D PREROUTING -w -t nat $(echo "${iptables_filter}") -p "${protocol}" --dport 53 -j DNAT --to-destination "${router_ip}":"${DNS_PORT}"
done
}
ip4_firewall_rm_vpn_selected_guest_net() {
local net_interface="${1}"
if [ -z "${net_interface}" ] ; then
error "[${FUNCNAME}] Не передан обязательный параметр — имя интерфейса"
fi
if echo "${net_interface}" | grep -q ikev2 ; then
net_interface=$(get_entware_ikev2_inface)
# IKEv2 не имеет отдельного сетевого интерфейса, поэтому запишем и что добавляем, и используемый СИ
local submessage="IKEv2 (${net_interface} "
local net_pool=$(get_ikev2_net_pool)
local iptables_filter="-s ${net_pool} "
else
local submessage="${net_interface} ("
local net_pool=$(get_guest_net "${net_interface}")
local iptables_filter=''
fi
iptables_filter="${iptables_filter}-i ${net_interface}"
log_warning "Отключаем правила гостевого трафика ${submessage}${net_pool}) для VPN."
ip4_delete_from_dns_routing "${iptables_filter}"
if fastnet_enabled ; then
if iptables-save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${IPSET_TABLE_NAME}" | grep -Fq "${VPN_IPTABLES_CHAIN}" ; then
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -D PREROUTING -w -t mangle $(echo "${iptables_filter}") -m set --match-set "${IPSET_TABLE_NAME}" dst -j "${VPN_IPTABLES_CHAIN}"
fi
else
if [ -z "${net_pool}" ] ; then
error "[${FUNCNAME}] От функции get_guest_net не получен обязательный результат — пул адресов"
fi
# случай основного VPN и отключенного ускорения требует дополнительной проверки
# но именно таким код был изначально, т.е. он точно не "ухудшится"
if iptables-save | grep -F 'POSTROUTING' | grep -F "${net_pool}" | grep -F "${net_interface}" | grep -Fq 'MASQUERADE' ; then
iptables -D POSTROUTING -w -t nat -s "${net_pool}" -o "${net_interface}" -j MASQUERADE
fi
fi
}
Массово пришлось, но наконец-то и код стал более-менее консистентным. При этом исправилась ещё пара мелочей.
Проведём тест (для связки VPN + ускорение)
Роутер рестартим, обход в домашней сети работает, в правилах видим прокидку трафика и DNS (при этом только для локалки, никаких внешних интерфейсов):
Переходим на гостевую сеть устройством. Обход не работает. Через kvas vpn net add
добавим обход гостевой, смотрим правила:
Появился и проброс DNS, и трафика. Обход на устройстве заработал.
Через kvas vpn net del
удалим обход гостевой, смотрим правила:
Всё подчистилось. Обход в гостевой, соответственно, работать перестал.
Уходим тестируемым устройством на мобильную сеть, подключаемся к роутеру через IKEv2. Обход не работает. Накатываем патч #194, через kvas vpn net add
добавим обход IKEv2, смотрим правила:
Появился и проброс DNS, и трафика. Обход на устройстве заработал.
Через kvas vpn net del
удалим обход IKEv2, смотрим правила:
Всё подчистилось. Обход в IKEv2, соответственно, работать перестал.
Большое благодарю за проделанную работу. Правки внесены в следующую бету. Выйдет на этой неделе.
Правки внесены в следующую бету. Выйдет на этой неделе.
Я сейчас дофикшиваю код для случая основного соединения ShadowSocks. Если не сложно, дождитесь ещё его)
Я сейчас дофикшиваю код для случая основного соединения ShadowSocks. Если не сложно, дождитесь ещё его)
Добро, жду.
Буду придерживаться нумерации, как в VPN. Всё, что требуется для работы. Даже если пункты уже сделаны, иначе что-то можно упустить.
1.1. роутинг DNS уже пропатчен в #195.
1.2. роутинг данных в opt/etc/ndm/ndm
:ip4_firewall_set_ssr_rules
уже ограничен локальным интерфейсом, изменений не требуется.
2.1. При вызове из консоли
2.1.1. в случае IKEv2. opt/etc/ndm/ndm
:ikev2_net_access_add
, уже исправлен в случае с VPN.
2.1.2. в случае именованных интерфейсов. Тоже никаких изменений по сравнению со случаем с VPN.
2.2. Триггерное добавление — это в opt/etc/ndm/ndm
цепочка вызовов:
ip4_add_guest_to_ssr_network
ip4_add_selected_guest_to_ssr_network
, её по аналогии с VPN нужно доработать:
ip4_add_selected_guest_to_ssr_network() {
local net_interface="${1}"
local net_pool=${2}
[ -z "${net_interface}" ] && {
error "[${FUNCNAME}] Отсутствует обязательный параметр — имя сетевого интерфейса"
exit 1
}
if echo "${net_interface}" | grep -Fq 'ikev2' ; then
net_interface=$(get_entware_ikev2_inface)
[ -z "${net_pool}" ] && {
net_pool=$(get_ikev2_net_pool)
}
# IKEv2 не имеет отдельного сетевого интерфейса, поэтому запишем и что добавляем, и используемый СИ
local submessage="IKEv2 (${net_interface} "
local iptables_filter="-s ${net_pool} "
else
[ -z "${net_pool}" ] && {
# в случае SS+неIKEv2 используется лишь в лог-сообщении для единобразия
net_pool=$(get_guest_net "${net_interface}")
}
local submessage="${net_interface} ("
local iptables_filter=''
fi
iptables_filter="${iptables_filter}-i ${net_interface}"
log_warning "Подключаем правила гостевого трафика ${submessage}${net_pool}) для ShadowSocks."
ip4_add_to_dns_routing "${iptables_filter}"
local ss_port=$(get_config_value SSR_DNS_PORT)
for protocol in tcp udp ; do
if ip4save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${protocol}" | grep -F "${IPSET_TABLE_NAME}" | grep -F 'REDIRECT' | grep -Fq "${ss_port}" ; then
continue
fi
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -A PREROUTING -w -t nat $(echo "${iptables_filter}") -p "${protocol}" -m set --match-set "${IPSET_TABLE_NAME}" dst -j REDIRECT --to-port ${ss_port}
done
}
3.1. в случае VPN уже были исправлены cmd_bridge_vpn_access_del
, ikev2_net_access_del
и bridge_vpn_access_del
.
3.2. остаётся лишь базовая обёртка для этого случая opt/etc/ndm/ndm
:ip4_firewall_rm_ssr_selected_guest_net
ip4_firewall_rm_ssr_selected_guest_net() {
local net_interface="${1}"
local net_pool=${2}
[ -z "${net_interface}" ] && {
error "[${FUNCNAME}] Отсутствует обязательный параметр — имя сетевого интерфейса"
exit 1
}
if echo "${net_interface}" | grep -Fq 'ikev2' ; then
net_interface=$(get_entware_ikev2_inface)
[ -z "${net_pool}" ] && {
net_pool=$(get_ikev2_net_pool)
}
# IKEv2 не имеет отдельного сетевого интерфейса, поэтому запишем и что добавляем, и используемый СИ
local submessage="IKEv2 (${net_interface} "
local iptables_filter="-s ${net_pool} "
else
[ -z "${net_pool}" ] && {
# в случае SS+неIKEv2 используется лишь в лог-сообщении для единобразия
net_pool=$(get_guest_net "${net_interface}")
}
local submessage="${net_interface} ("
local iptables_filter=''
fi
iptables_filter="${iptables_filter}-i ${net_interface}"
log_warning "Отключаем правила гостевого трафика ${submessage}${net_pool}) для ShadowSocks."
ip4_delete_from_dns_routing "${iptables_filter}"
local ss_port=$(get_config_value SSR_DNS_PORT)
for protocol in tcp udp ; do
if ! ip4save | grep -F 'PREROUTING' | grep -F -- "${iptables_filter}" | grep -F "${protocol}" | grep -F "${IPSET_TABLE_NAME}" | grep -F 'REDIRECT' | grep -Fq "${ss_port}" ; then
continue
fi
# без echo дублирование пробелов (что даёт warning и проблему наличия)
iptables -D PREROUTING -w -t nat $(echo "${iptables_filter}") -p "${protocol}" -m set --match-set "${IPSET_TABLE_NAME}" dst -j REDIRECT --to-port ${ss_port}
done
}
К сожалению, не имею сейчас возможности проверить эти правки. Но код обеих обёрток достаточно единобразен с другими случаями.
Благодарю Вас. Правки внес в основной код 7 беты, появится до конца недели.
Собственно, проблемы сейчас:
В 1.1.9-beta_6 DNS сейчас висит на нестандартном порту, и для его работы в #195 мы прероутим DNS-трафик на нужный порт. Чтобы закрыть уязвимость, делаем мы это строго для br0. Эти правила теперь нужно размножать для каждой сети из гостевых.
В #185 был более-менее причёсан код по расшариванию гостевых для VPN. Но сами правила времени рассмотреть тогда не было, сейчас исправил.
2.1. Правила для шаринга трафика в случае включенного и отключенного ускорения должны быть разными.
2.2. Там та же уязвимость и нагрузка, что были с правилами DNS. Вся магия обхода строится через
Про использование OUTPUT я уже как-то писал, что обычно это правила, когда всё уже пропустили и пытаемся запрыгнуть на подножку уходящего поезда. Когда надо прям обязательно словить все сети. В своё время у SS его убрали, и всё хорошо работает и поныне. Правила PREROUTING сейчас вешаются на все сетевые интерфейсы. Все 30–50 сетевых интерфейсов сверяют трафик с таблицей IPSET_TABLE_NAME, ещё и дважды (возможно западение скорости). И что самое ужасное, это делают и внешние сетевые интерфейсы (скорее всего, у нас снова дыра в безопасности).
Для проверки подключим КВАС через VPN. Ни одну гостевую сеть для обхода я не добавил, но там везде обход работает. По правильному, правило с PREROUTING должно вешаться лишь на br0. И в 4 местах, затронутых в #185, соответствующие правила должны добавляться.
При этом в маркировке для VPN с отключенным ускорением мы правильно ограничены и PREROUTING, и интерфейсом.
Исправления обоих пунктов для VPN и SS пришлю отдельными сообщениями, сейчас они тестируются.