Skip to content

Commit

Permalink
Merge pull request qzeleza#248 from AltGrF13/ip-exclude.225
Browse files Browse the repository at this point in the history
Iptables: исключение петель
  • Loading branch information
qzeleza authored Dec 20, 2024
2 parents e8de647 + 64f5373 commit 1177445
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 34 deletions.
29 changes: 20 additions & 9 deletions opt/bin/libs/debug
Original file line number Diff line number Diff line change
Expand Up @@ -228,22 +228,33 @@ iptables__get_by_chain() {
}

cmd_debug_iptables() {
local output=$(ip route)
local output="$(get_tunnel_ip | xargs)"
if [ -z "${output}" ] ; then
output='Не найден!'
fi

ready 'Модель роутера' && when_ok "$(get_model)"
ready 'Версия ndw' && when_ok "$(get_version)"
ready 'Версия ndw4' && when_ok "$(version_os)"
ready 'Внешний интерфейс' && when_ok "$(get_external_interface)"
ready 'IKEv2 интерфейс' && when_ok "$(get_entware_ikev2_inface)"
# если вызывается как один из дебагов, то можно передать silent/short
if [ -z "${1}" ] ; then
echo 'Проверьте корректность отображаемой информации'
print_line
ready 'Модель роутера' && when_ok "$(get_model)"
ready 'Версия прошивки' && when_ok "$(version_os)"
fi
ready 'Внешний IP' && when_ok "$(get_external_ip)"
ready 'IP тоннеля' && when_ok "${output}"
ready 'Исключённых целевых IPv4 и диапазонов' && when_ok "$(ipset list ${IPSET_DESTINATION_EXCLUDED} | grep -vF ':' | wc -l)"
ready 'Интерфейс для выхода в интернет' && when_ok "$(get_external_interface)"
ready 'IKEv2 интерфейс' && when_ok "$(get_entware_ikev2_inface)"
echo

echo_debug 'Маршруты (подключитесь к гостевой заранее)' "${output}"
echo_debug 'Маршруты (подключитесь к гостевой заранее)' "$(ip route)"

if is_proxy_enabled ; then
output=$(iptables__get_by_chain "${CHAIN_DNAT_TO_PORT}")
output="${CHAIN_DNAT_TO_PORT}"
else
output=$(iptables__get_by_chain "${CHAIN_MARK_TO_TABLE}")
output="${CHAIN_MARK_TO_TABLE}"
fi
output=$(iptables__get_by_chain "${output}")
if [ -z "${output}" ] ; then
output='Правила не найдены!'

Expand Down
64 changes: 63 additions & 1 deletion opt/bin/libs/main
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ is_os_below_4_2() {
}

is_ip_private() {
if echo "$1" | grep -qE '^(192\.168\.|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'; then
if echo "$1" | grep -qE '^(255\.|224\.|0\.|127\.|192\.168\.|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'; then
return
fi

Expand Down Expand Up @@ -655,11 +655,73 @@ dig_frm() {
# Получаем внешний IP роутера через который он выходит в сеть в текущий момент
#
# ------------------------------------------------------------------------------------------

get_external_ip() {
dns=$(get_config_value DNS_STATIC_1)
/opt/sbin/ip route get ${dns} | sed -E 's/.*src (\S+) .*/\1/;t;d'
}

function vpn__get_tunnel_ip() {
if [ -z "${1}" ] ; then
error "[${FUNCNAME}] Не задан обязательный аргумент — название соединения"
return
fi
local api_interface="${1}"

local api_response=$(curl -s "${INFACE_PART_REQUEST}/${api_interface}")
if [ -z "${api_response}" ] ; then
error "[${FUNCNAME}] Не найдено соединение ${api_interface}"
return
fi

# формат L2TP
local ip=$(echo "${api_response}" | jq -r '.peer' | grep -oE "${IP_FILTER}")
if [ -n "${ip}" ] && ! is_ip_private "${ip}" ; then
echo "${ip}"
return
fi

local ips

# формат Wireguard
ips=''
for ip in $(echo "${api_response}" | jq -r '.wireguard.peer[]? .endpoint.address' | grep -oE "${IP_FILTER}") ; do
if [ -n "${ip}" ] && ! is_ip_private "${ip}" ; then
ips="${ips}${ip}"$'\n'
fi
done
if [ -n "${ips}" ]; then
echo "${ips}"
return
fi

# универсальный код по поиску внешнего IP вне allow-ips
#ToDo: проверить на всех типах VPN! Для каждого добавить json-блок выше и исключение сюда мусорных массивов.
ips=''
for ip in $(echo "${api_response}" | sed '/allow-ips/,/]/d' | grep -oE "${IP_FILTER}") ; do
if [ -n "${ip}" ] && ! is_ip_private "${ip}" ; then
ips="${ips}${ip}"$'\n'
fi
done
if [ -n "${ips}" ]; then
echo "${ips}"
return
fi

log_error 'IP сервера VPN найти не удалось'
echo ''
}

get_tunnel_ip() {
if is_shadowsocks_enabled ; then
echo $(get_from_json "${SHADOWSOCKS_CONF}" 'server')
elif is_vless_enabled ; then
echo $(get_from_json "${VLESS_CONFIG_FILE}" 'address' 'outbounds')
else
echo $(vpn__get_tunnel_ip "$(get_config_value INFACE_CLI)")
fi
}

# ------------------------------------------------------------------------------------------
#
# Получаем локальный IP роутера
Expand Down
1 change: 0 additions & 1 deletion opt/etc/conf/reserved.ip
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# https://en.wikipedia.org/wiki/Reserved_IP_addresses
0.0.0.0/8
10.0.0.0/8
78.47.125.180 #my.keenetic.net
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
Expand Down
50 changes: 27 additions & 23 deletions opt/etc/ndm/ndm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ PRIORITY=1778
MARK_NUM=0xd1000
DNS_PORT=9753

IPSET_RESERVED=KVAS_RESERVED
IPSET_DESTINATION_EXCLUDED=KVAS_DESTINATION_EXCLUDED

CHAIN_DNS=KVAS_DNS
TABLE_DNS=nat
Expand Down Expand Up @@ -257,12 +257,25 @@ ip4set_create_table() {
}

# Для постоянного списка исключаемых сетей
ip4__ipset__fill_reserved() {
if ip4__ipset__is_exist "${IPSET_RESERVED}"; then
ip4__ipset__fill_destination_excluded() {
if ip4__ipset__is_exist "${IPSET_DESTINATION_EXCLUDED}"; then
return
fi

ip4__ipset__create "${IPSET_RESERVED}"
ip4__ipset__create "${IPSET_DESTINATION_EXCLUDED}"

# Служебный IP Keenetic, например для my.keenetic.net
ipset -exist add "${IPSET_DESTINATION_EXCLUDED}" '78.47.125.180'

# Был случай, когда ресурс из списка совпадал с IP роутера
# Это приводило к не рабочему DDNS и прочим проблемам
ipset -exist add "${IPSET_DESTINATION_EXCLUDED}" "$(get_external_ip)"

# Исключаем (loopback) адреса тоннеля из попадания в тоннель
# Случай тоже детектирован и чуть более разрушителен
for ip in $(get_tunnel_ip) ; do
ipset -exist add "${IPSET_DESTINATION_EXCLUDED}" "${ip}"
done

while read -r ip_or_range || [ -n "${ip_or_range}" ]; do
# пропускаем строки с комментариями
Expand All @@ -271,7 +284,7 @@ ip4__ipset__fill_reserved() {
# удаляем пробелы
ip_or_range=$(echo "${ip_or_range}" | sed 's/#.*$//g' | tr -s ' ' )

ipset -exist add "${IPSET_RESERVED}" "${ip_or_range}"
ipset -exist add "${IPSET_DESTINATION_EXCLUDED}" "${ip_or_range}"
done < "${FILE_RESERVED}"
}

Expand Down Expand Up @@ -301,8 +314,8 @@ ip4__ipset__destroy_list() {
}

# Для постоянного списка исключаемых сетей
ip4__ipset__destroy_reserved() {
ip4__ipset__destroy "${IPSET_RESERVED}"
ip4__ipset__destroy_destination_excluded() {
ip4__ipset__destroy "${IPSET_DESTINATION_EXCLUDED}"
}


Expand Down Expand Up @@ -383,8 +396,8 @@ ip4__chain__create_for_data() {

ip4__chain__exclude_source_by_config "${table}" "${chain_name}"

ip4__ipset__fill_reserved
iptables -A "${chain_name}" -w -t "${table}" -m set --match-set "${IPSET_RESERVED}" dst -j RETURN
ip4__ipset__fill_destination_excluded
iptables -A "${chain_name}" -w -t "${table}" -m set --match-set "${IPSET_DESTINATION_EXCLUDED}" dst -j RETURN

# если цепочка данных будет подключена выше DNS, то она может
# перехватить направленный вовне трафик
Expand Down Expand Up @@ -459,20 +472,13 @@ ip4__proxy__create_chain() {
fi
port="${3}"

ip="${4}"

{
if ip4__chain__is_exist "${table}" "${chain_name}" ; then
return
fi

ip4__chain__create_for_data "${table}" "${chain_name}"

if [ -n "${ip}" ] ; then
# Исключаем обращения к собственному адресу
ipset -exist add "${IPSET_RESERVED}" "${ip}"
fi

for protocol in udp tcp ; do
# не будет ли задвоения без -w?
iptables -A "${chain_name}" -t "${table}" -p "${protocol}" -j REDIRECT --to-port "${port}"
Expand All @@ -481,17 +487,15 @@ ip4__proxy__create_chain() {
}

ip4__shadowsocks__create_chain() {
local server_ip=$(get_from_json "${SHADOWSOCKS_CONF}" 'server')
local local_port=$(get_config_value SSR_DNS_PORT)

ip4__proxy__create_chain "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}" "${local_port}" "${server_ip}"
ip4__proxy__create_chain "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}" "${local_port}"
}

ip4__vless__create_chain() {
local local_port=$(get_from_json "${VLESS_CONFIG_FILE}" 'port' 'inbounds')
local server_ip=$(get_from_json "${VLESS_CONFIG_FILE}" 'address' 'outbounds')
local local_port=$(get_from_json "${VLESS_CONFIG_FILE}" 'port' 'inbounds')

ip4__proxy__create_chain "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}" "${local_port}" "${server_ip}"
ip4__proxy__create_chain "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}" "${local_port}"
}

# когда ускорение подключено
Expand Down Expand Up @@ -1130,7 +1134,7 @@ ip4__flush() {
ip4__chain__delete_jump "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}"

ip4__chain__delete "${TABLE_DNAT_TO_PORT}" "${CHAIN_DNAT_TO_PORT}"
ip4__ipset__destroy_reserved
ip4__ipset__destroy_destination_excluded
fi
elif fastnet_enabled ; then
if echo "${parts}" | grep -Fq ' jump ' ; then
Expand All @@ -1140,7 +1144,7 @@ ip4__flush() {
ip4__chain__delete_jump "${TABLE_MARK_TO_TABLE}" "${CHAIN_MARK_TO_TABLE}"

ip4__chain__delete "${TABLE_MARK_TO_TABLE}" "${CHAIN_MARK_TO_TABLE}"
ip4__ipset__destroy_reserved
ip4__ipset__destroy_destination_excluded
fi

#if echo "${parts}" | grep -Fq ' table ' ; then
Expand Down

0 comments on commit 1177445

Please sign in to comment.