diff --git a/luci-app-ruantiblock/Makefile b/luci-app-ruantiblock/Makefile index cc872e4..0dbc6ef 100644 --- a/luci-app-ruantiblock/Makefile +++ b/luci-app-ruantiblock/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=1.1-1 +PKG_VERSION:=1.2-0 LUCI_TITLE:=LuCI support for ruantiblock LUCI_DEPENDS:=+ruantiblock LUCI_PKGARCH:=all diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js index 41466c0..5b3244c 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js @@ -47,6 +47,7 @@ return view.extend({ if(data.rules.nftables && data.rules.nftables.length > 1) { for(let i of data.rules.nftables) { if(!i.rule) continue; + let set, bytes; i.rule.expr.forEach(e => { if(e.match) { @@ -262,12 +263,15 @@ return view.extend({ ]); for(let [set, bytes] of nft_data.rules) { + if(!set) { + continue; + }; table_rules.append( E('tr', { 'class': 'tr' }, [ E('td',{ 'class' : 'td left', 'data-title': _('Match-set'), - }, set + ' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq') + ')'), + }, set + ((set.length == 1) ? (' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq') + ')') : '')), E('td', { 'class' : 'td left', 'id' : 'rules.' + set, diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js index 39f05db..36416b5 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js @@ -249,6 +249,17 @@ return view.extend({ bllist_module.value('', _('disabled')); bllist_module.depends({ bllist_preset: new RegExp('^($|' + tools.appName + ')'), '!reverse': true }); + // BYPASS_IP_MODE + o = s.taboption('blacklist_tab', form.Flag, 'bypass_ip_mode', + _('Enable IP exclusion list'), _("List of IP addresses that are excluded from block bypass (always available directly)")); + o.rmempty = false; + o.default = 0; + + // BYPASS_IP_LIST + o = s.taboption('blacklist_tab', form.DynamicList, 'bypass_ip_list', + _('IP exclusion list')); + o.datatype = "ip4addr"; + Object.entries(this.parsers).forEach( e => bllist_module.value(e[1], e[0])); diff --git a/luci-app-ruantiblock/po/ru/ruantiblock.po b/luci-app-ruantiblock/po/ru/ruantiblock.po index 6ff7777..b6fafe3 100644 --- a/luci-app-ruantiblock/po/ru/ruantiblock.po +++ b/luci-app-ruantiblock/po/ru/ruantiblock.po @@ -119,6 +119,9 @@ msgstr "Включить" msgid "Enable FQDN filter" msgstr "Включить FQDN фильтр" +msgid "Enable IP exclusion list" +msgstr "Включить список исключений IP адресов" + msgid "Enable IP filter" msgstr "Включить IP фильтр" @@ -167,6 +170,9 @@ msgstr "IP-адрес" msgid "IP addresses of hosts" msgstr "IP-адреса хостов" +msgid "IP exclusion list" +msgstr "Список исключенных IP адресов" + msgid "IP filter" msgstr "Фильтр IP" @@ -203,6 +209,9 @@ msgstr "Последние записи" msgid "Level" msgstr "Уровень" +msgid "List of IP addresses that are excluded from block bypass (always available directly)" +msgstr "Список IP адресов, которые исключаются из обхода блокировок (всегда доступны напрямую)" + msgid "Loading" msgstr "Загрузка" diff --git a/luci-app-ruantiblock/po/templates/ruantiblock.pot b/luci-app-ruantiblock/po/templates/ruantiblock.pot index 5f77d68..5c1b5f4 100644 --- a/luci-app-ruantiblock/po/templates/ruantiblock.pot +++ b/luci-app-ruantiblock/po/templates/ruantiblock.pot @@ -102,6 +102,9 @@ msgstr "" msgid "Enable FQDN filter" msgstr "" +msgid "Enable IP exclusion list" +msgstr "" + msgid "Enable IP filter" msgstr "" @@ -150,6 +153,9 @@ msgstr "" msgid "IP addresses of hosts" msgstr "" +msgid "IP exclusion list" +msgstr "" + msgid "IP filter" msgstr "" @@ -183,6 +189,9 @@ msgstr "" msgid "Level" msgstr "" +msgid "List of IP addresses that are excluded from block bypass (always available directly)" +msgstr "" + msgid "Loading" msgstr "" diff --git a/ruantiblock-mod-lua/Makefile b/ruantiblock-mod-lua/Makefile index 0b63a51..663f834 100644 --- a/ruantiblock-mod-lua/Makefile +++ b/ruantiblock-mod-lua/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-lua -PKG_VERSION:=1.1 +PKG_VERSION:=1.2 PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot diff --git a/ruantiblock-mod-py/Makefile b/ruantiblock-mod-py/Makefile index 014c160..1f25d04 100644 --- a/ruantiblock-mod-py/Makefile +++ b/ruantiblock-mod-py/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-py -PKG_VERSION:=1.1 -PKG_RELEASE:=1 +PKG_VERSION:=1.2 +PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk diff --git a/ruantiblock/Makefile b/ruantiblock/Makefile index 8be786b..2b49288 100644 --- a/ruantiblock/Makefile +++ b/ruantiblock/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock -PKG_VERSION:=1.1 -PKG_RELEASE:=3 +PKG_VERSION:=1.2 +PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk diff --git a/ruantiblock/files/etc/config/ruantiblock b/ruantiblock/files/etc/config/ruantiblock index 7170cd7..80db80f 100644 --- a/ruantiblock/files/etc/config/ruantiblock +++ b/ruantiblock/files/etc/config/ruantiblock @@ -4,6 +4,7 @@ config main 'config' option proxy_local_clients '1' option nftset_clear_sets '1' option allowed_hosts_mode '0' + option bypass_ip_mode '0' option if_vpn 'tun0' option tor_trans_port '9040' option tor_allow_udp '0' diff --git a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf index e82bb7d..55ac88a 100644 --- a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf +++ b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf @@ -22,6 +22,10 @@ NFTSET_CLEAR_SETS=0 ALLOWED_HOSTS_MODE=0 ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) ALLOWED_HOSTS_LIST="" +### Режим списка IP адресов исключаемых из обхода блокировок (0 - выкл, 1 - вкл) +BYPASS_IP_MODE=0 +### Список IP адресов, которые исключаются из обхода блокировок, через пробел (прим.: 52.49.102.199 52.49.102.200) +BYPASS_IP_LIST="" ### VPN интерфейс для правил маршрутизации IF_VPN="tun0" ### Порт прозрачного прокси Tor (параметр TransPort в torrc) @@ -42,8 +46,12 @@ T_PROXY_PORT_UDP=1100 T_PROXY_ALLOW_UDP=0 ### Приоритет правила отбора пакетов nftables для конфигупации Tor или прозрачного прокси NFT_PRIO_NAT="dstnat - 10" +### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в конфигупации Tor или прозрачного прокси +NFT_PRIO_NAT_LOCAL="filter - 10" ### Приоритет правила отбора пакетов nftables для VPN-конфигурации NFT_PRIO_ROUTE="mangle + 10" +### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в VPN-конфигурации +NFT_PRIO_ROUTE_LOCAL="mangle + 10" ### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл) ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) diff --git a/ruantiblock/files/usr/bin/ruantiblock b/ruantiblock/files/usr/bin/ruantiblock index 23263ae..56c76d7 100755 --- a/ruantiblock/files/usr/bin/ruantiblock +++ b/ruantiblock/files/usr/bin/ruantiblock @@ -37,6 +37,10 @@ export NFTSET_CLEAR_SETS=0 export ALLOWED_HOSTS_MODE=0 ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) export ALLOWED_HOSTS_LIST="" +### Режим списка IP адресов исключаемых из обхода блокировок (0 - выкл, 1 - вкл) +export BYPASS_IP_MODE=0 +### Список IP адресов, которые исключаются из обхода блокировок, через пробел (прим.: 52.49.102.199 52.49.102.200) +export BYPASS_IP_LIST="" ### VPN интерфейс для правил маршрутизации export IF_VPN="tun0" ### Порт прозрачного прокси Tor (параметр TransPort в torrc) @@ -57,8 +61,12 @@ export T_PROXY_PORT_UDP=1100 export T_PROXY_ALLOW_UDP=0 ### Приоритет правила отбора пакетов nftables для конфигупации Tor или прозрачного прокси export NFT_PRIO_NAT="dstnat - 10" +### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в конфигупации Tor или прозрачного прокси +export NFT_PRIO_NAT_LOCAL="filter - 10" ### Приоритет правила отбора пакетов nftables для VPN-конфигурации export NFT_PRIO_ROUTE="mangle + 10" +### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в VPN-конфигурации +export NFT_PRIO_ROUTE_LOCAL="mangle + 10" ### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл) ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) @@ -184,11 +192,13 @@ export IP_DATA_FILE="${DATA_DIR}/${NAME}.ip" export NFT_TABLE="ip r" export NFT_TABLE_DNSMASQ="4#ip#r" export NFTSET_ALLOWED_HOSTS="allowed_ip" +export NFTSET_BYPASS_IP="bypass_ip" export NFTSET_ONION="onion" export NFTSET_CIDR="c" export NFTSET_IP="i" export NFTSET_DNSMASQ="d" export NFTSET_ALLOWED_HOSTS_TYPE="ipv4_addr" +export NFTSET_BYPASS_IP_TYPE="ipv4_addr" export NFTSET_CIDR_TYPE="ipv4_addr" export NFTSET_IP_TYPE="ipv4_addr" export NFTSET_DNSMASQ_TYPE="ipv4_addr" @@ -289,15 +299,20 @@ FlushNftSets() { } AddNftSets() { - local _hosts + local _allowed_hosts _bypass_ips $NFT_CMD add set $NFT_TABLE "$NFTSET_CIDR" { type "$NFTSET_CIDR_TYPE"\; size $NFTSET_MAXELEM_CIDR\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_IP" { type "$NFTSET_IP_TYPE"\; size $NFTSET_MAXELEM_IP\; policy "$NFTSET_POLICY_IP"\; flags dynamic\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_DNSMASQ" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_ONION" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } - $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_IP"\; flags dynamic\; } - _hosts=`printf "$ALLOWED_HOSTS_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'` - if [ -n "$_hosts" ]; then - $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_hosts" } + $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } + _allowed_hosts=`printf "$ALLOWED_HOSTS_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'` + if [ -n "$_allowed_hosts" ]; then + $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_allowed_hosts" } + fi + $NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_IP" { type "$NFTSET_BYPASS_IP_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } + _bypass_ips=`printf "$BYPASS_IP_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'` + if [ -n "$_bypass_ips" ]; then + $NFT_CMD add element $NFT_TABLE "$NFTSET_BYPASS_IP" { "$_bypass_ips" } fi } @@ -336,7 +351,7 @@ SetNetConfig() { DropNetConfig() { DeleteNftRules - FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_CIDR" "$NFTSET_IP" "$NFTSET_DNSMASQ" "$NFTSET_ONION" + FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_BYPASS_IP" "$NFTSET_CIDR" "$NFTSET_IP" "$NFTSET_DNSMASQ" "$NFTSET_ONION" } DestroyNetConfig() { diff --git a/ruantiblock/files/usr/share/ruantiblock/config_script b/ruantiblock/files/usr/share/ruantiblock/config_script index 77a6dfa..4c79e80 100644 --- a/ruantiblock/files/usr/share/ruantiblock/config_script +++ b/ruantiblock/files/usr/share/ruantiblock/config_script @@ -1,6 +1,6 @@ AWK_CMD="awk" UCI_SECTION="ruantiblock.config" -UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list if_vpn tor_trans_port tor_allow_udp onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup" +UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_ip_mode bypass_ip_list if_vpn tor_trans_port tor_allow_udp onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup" eval `uci show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' BEGIN { diff --git a/ruantiblock/files/usr/share/ruantiblock/nft_functions b/ruantiblock/files/usr/share/ruantiblock/nft_functions index b7c02a8..d8e2ff2 100644 --- a/ruantiblock/files/usr/share/ruantiblock/nft_functions +++ b/ruantiblock/files/usr/share/ruantiblock/nft_functions @@ -7,21 +7,30 @@ VPN_ROUTE_TABLE_ID=99 if [ "$PROXY_MODE" = "2" ]; then MAIN_CHAIN_TYPE="type filter hook prerouting priority ${NFT_PRIO_ROUTE}; policy accept;" - LOCAL_CLIENTS_CHAIN_TYPE="type route hook output priority ${NFT_PRIO_ROUTE}; policy accept;" + LOCAL_CLIENTS_CHAIN_TYPE="type route hook output priority ${NFT_PRIO_ROUTE_LOCAL}; policy accept;" else MAIN_CHAIN_TYPE="type nat hook prerouting priority ${NFT_PRIO_NAT}; policy accept;" - LOCAL_CLIENTS_CHAIN_TYPE="type nat hook output priority ${NFT_PRIO_NAT}; policy accept;" + LOCAL_CLIENTS_CHAIN_TYPE="type nat hook output priority ${NFT_PRIO_NAT_LOCAL}; policy accept;" fi case "$ALLOWED_HOSTS_MODE" in "1") - IPT_ALLOWED_HOSTS_RULE="ip saddr @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" + NFT_ALLOWED_HOSTS_RULE="ip saddr @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" ;; "2") - IPT_ALLOWED_HOSTS_RULE="ip saddr != @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" + NFT_ALLOWED_HOSTS_RULE="ip saddr != @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" ;; *) - IPT_ALLOWED_HOSTS_RULE="jump ${NFT_BLLIST_CHAIN}" + NFT_ALLOWED_HOSTS_RULE="jump ${NFT_BLLIST_CHAIN}" + ;; +esac + +case "$BYPASS_IP_MODE" in + "1") + NFT_BYPASS_IP_RULE="ip daddr @${NFTSET_BYPASS_IP} counter accept" + ;; + *) + NFT_BYPASS_IP_RULE="continue" ;; esac @@ -64,7 +73,7 @@ NftMainAdd() { $NFT_CMD add chain $NFT_TABLE "$NFT_ACTION_CHAIN" $NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN" $NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { $MAIN_CHAIN_TYPE } - NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" $IPT_ALLOWED_HOSTS_RULE + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" $NFT_ALLOWED_HOSTS_RULE if [ "$PROXY_MODE" = "2" ]; then NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" mark set $VPN_PKTS_MARK elif [ "$PROXY_MODE" = "3" ]; then @@ -77,8 +86,9 @@ NftMainAdd() { if [ "$TOR_ALLOW_UDP" = "1" ]; then NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" udp dport { 0-65535 } redirect to $TOR_TRANS_PORT fi - _nft_sets="${NFTSET_ONION} ${_nft_sets}" + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_ONION}" counter goto "$NFT_ACTION_CHAIN" fi + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" $NFT_BYPASS_IP_RULE for _set in $_nft_sets do NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${_set}" counter goto "$NFT_ACTION_CHAIN"