pbr: update to 1.1.4-5
This update includes the following changes: 1. Makefile * update copyright * attempt to implement the proper variants to avoid luci-app dependency on both variants * quietly stop service on uninstall 2. Config-file * add the list of dnsmasq instances to target in supported dnsmasq modes * for default pbr variant, set the `resolver_set` to `dnsmasq.nftset` * for iptables pbr variant, set the `resolver_set` to `dnsmasq.ipset` * add the `nft_file_support` (disabled by default) * introduce `procd_boot_delay` to delay service start on boot * introduce the following nft set creation options: * nft_set_auto_merge * nft_set_counter * nft_set_flags_interval * nft_set_flags_timeout * nft_set_gc_interval * nft_set_policy * nft_set_timeout * add the pbr.user.wg_server_and_client custom user script to allow running wg server and client at the same time * add the "Ignore Local Requests" sample policy 3. Hotplug firewall/interface scripts * better logged messages 4. The pbr and pbr-iptables uci defaults script * use functions from the init script * improve vpn-policy-routing migration 5. The pbr-netifd uci defaults script * use functions from the init script * improve uci operations 6. Introduce the firewall.include file 7. Improve pbr.user.aws custom user script 8. Improve pbr.user.netflix custom user script 9. Introduce pbr.user.wg_server_and_client custom user script 10. Update the init file: * refactor some code to allow the init script file to be sourced by the uci defaults scripts and the luci rpcd script for shared functions * add support for `nft_file_mode` in which service prepares the fw4-compatible atomic nft/include file for faster operations on service reload * improve Tor support (nft mode only) * implement support for nft set options * update validation functions for new options/parameters Signed-off-by: Stan Grishin <stangri@melmac.ca>
This commit is contained in:
parent
c7f77bded7
commit
790753f6a6
|
@ -1,73 +1,80 @@
|
||||||
# Copyright 2017-2022 Stan Grishin (stangri@melmac.ca)
|
# Copyright 2017-2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
|
||||||
# This is free software, licensed under the GNU General Public License v3.
|
# This is free software, licensed under the GNU General Public License v3.
|
||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=pbr
|
PKG_NAME:=pbr
|
||||||
PKG_VERSION:=1.1.1
|
PKG_VERSION:=1.1.4
|
||||||
PKG_RELEASE:=7
|
PKG_RELEASE:=5
|
||||||
PKG_LICENSE:=GPL-3.0-or-later
|
PKG_LICENSE:=GPL-3.0-or-later
|
||||||
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
|
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
define Package/pbr/Default
|
define Package/pbr-service/Default
|
||||||
SECTION:=net
|
SECTION:=net
|
||||||
CATEGORY:=Network
|
CATEGORY:=Network
|
||||||
SUBMENU:=Routing and Redirection
|
SUBMENU:=Routing and Redirection
|
||||||
TITLE:=Policy Based Routing Service
|
TITLE:=Policy Based Routing Service
|
||||||
URL:=https://docs.openwrt.melmac.net/pbr/
|
URL:=https://docs.openwrt.melmac.net/pbr/
|
||||||
DEPENDS:=+ip-full +jshn +jsonfilter +resolveip
|
DEPENDS:=+ip-full +jshn +jsonfilter +resolveip
|
||||||
|
DEPENDS+=+!BUSYBOX_DEFAULT_AWK:gawk
|
||||||
|
DEPENDS+=+!BUSYBOX_DEFAULT_GREP:grep
|
||||||
|
DEPENDS+=+!BUSYBOX_DEFAULT_SED:sed
|
||||||
|
PROVIDES:=pbr-service
|
||||||
CONFLICTS:=vpnbypass vpn-policy-routing
|
CONFLICTS:=vpnbypass vpn-policy-routing
|
||||||
PKGARCH:=all
|
PKGARCH:=all
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr
|
define Package/pbr
|
||||||
$(call Package/pbr/Default)
|
$(call Package/pbr-service/Default)
|
||||||
TITLE+= with nft/nft set support
|
TITLE+= with nft/nft set support
|
||||||
DEPENDS+=+kmod-nft-core +kmod-nft-nat +nftables-json
|
DEPENDS+=+kmod-nft-core +kmod-nft-nat +nftables-json
|
||||||
VARIANT:=nftables
|
|
||||||
PROVIDES:=vpnbypass vpn-policy-routing
|
|
||||||
DEFAULT_VARIANT:=1
|
DEFAULT_VARIANT:=1
|
||||||
|
VARIANT:=nftables
|
||||||
|
PROVIDES+=pbr vpnbypass vpn-policy-routing
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-iptables
|
define Package/pbr-iptables
|
||||||
$(call Package/pbr/Default)
|
$(call Package/pbr-service/Default)
|
||||||
TITLE+= with iptables/ipset support
|
TITLE+= with iptables/ipset support
|
||||||
DEPENDS+=+ipset +iptables +kmod-ipt-ipset +iptables-mod-ipopt
|
DEPENDS+=+ipset +iptables +kmod-ipt-ipset +iptables-mod-ipopt
|
||||||
VARIANT:=iptables
|
VARIANT:=iptables
|
||||||
PROVIDES:=pbr
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-netifd
|
define Package/pbr-netifd
|
||||||
$(call Package/pbr/Default)
|
$(call Package/pbr-service/Default)
|
||||||
TITLE+= with netifd support
|
TITLE+= with netifd support
|
||||||
VARIANT:=netifd
|
VARIANT:=netifd
|
||||||
PROVIDES:=pbr
|
endef
|
||||||
|
|
||||||
|
define Package/pbr-service/description
|
||||||
|
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr/description
|
define Package/pbr/description
|
||||||
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
|
$(call Package/pbr-service/description)
|
||||||
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
|
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-iptables/description
|
define Package/pbr-iptables/description
|
||||||
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
|
$(call Package/pbr-service/description)
|
||||||
This version supports OpenWrt with firewall3/ipset/iptables.
|
This version supports OpenWrt with firewall3/ipset/iptables.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-netifd/description
|
define Package/pbr-netifd/description
|
||||||
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
|
$(call Package/pbr-service/description)
|
||||||
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
|
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
|
||||||
This version uses OpenWrt native netifd/tables to set up interfaces. This is WIP.
|
This version uses OpenWrt native netifd/tables to set up interfaces. This is WIP.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr/conffiles
|
define Package/pbr-service/conffiles
|
||||||
/etc/config/pbr
|
/etc/config/pbr
|
||||||
endef
|
endef
|
||||||
|
|
||||||
Package/pbr-iptables/conffiles = $(Package/pbr/conffiles)
|
Package/pbr/conffiles = $(Package/pbr-service/conffiles)
|
||||||
Package/pbr-netifd/conffiles = $(Package/pbr/conffiles)
|
Package/pbr-iptables/conffiles = $(Package/pbr-service/conffiles)
|
||||||
|
Package/pbr-netifd/conffiles = $(Package/pbr-service/conffiles)
|
||||||
|
|
||||||
define Build/Configure
|
define Build/Configure
|
||||||
endef
|
endef
|
||||||
|
@ -75,31 +82,33 @@ endef
|
||||||
define Build/Compile
|
define Build/Compile
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr/default/install
|
define Package/pbr-service/install
|
||||||
$(INSTALL_DIR) $(1)/etc/init.d
|
$(INSTALL_DIR) $(1)/etc/init.d
|
||||||
$(INSTALL_BIN) ./files/etc/init.d/pbr.init $(1)/etc/init.d/pbr
|
$(INSTALL_BIN) ./files/etc/init.d/pbr $(1)/etc/init.d/pbr
|
||||||
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/pbr
|
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/pbr
|
||||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
|
||||||
$(INSTALL_DATA) ./files/etc/hotplug.d/iface/70-pbr $(1)/etc/hotplug.d/iface/70-pbr
|
|
||||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||||
$(INSTALL_BIN) ./files/etc/uci-defaults/90-pbr $(1)/etc/uci-defaults/90-pbr
|
$(INSTALL_BIN) ./files/etc/uci-defaults/90-pbr $(1)/etc/uci-defaults/90-pbr
|
||||||
$(INSTALL_DIR) $(1)/usr/share/pbr
|
$(INSTALL_DIR) $(1)/usr/share/pbr
|
||||||
|
$(INSTALL_DATA) ./files/usr/share/pbr/.keep $(1)/usr/share/pbr/.keep
|
||||||
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.aws $(1)/usr/share/pbr/pbr.user.aws
|
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.aws $(1)/usr/share/pbr/pbr.user.aws
|
||||||
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.netflix $(1)/usr/share/pbr/pbr.user.netflix
|
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.netflix $(1)/usr/share/pbr/pbr.user.netflix
|
||||||
|
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.wg_server_and_client $(1)/usr/share/pbr/pbr.user.wg_server_and_client
|
||||||
endef
|
endef
|
||||||
|
# $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||||
|
# $(INSTALL_DATA) ./files/etc/hotplug.d/iface/70-pbr $(1)/etc/hotplug.d/iface/70-pbr
|
||||||
|
|
||||||
define Package/pbr/install
|
define Package/pbr/install
|
||||||
$(call Package/pbr/default/install,$(1))
|
$(call Package/pbr-service/install,$(1))
|
||||||
$(INSTALL_DIR) $(1)/etc/config
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
|
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
|
||||||
$(INSTALL_DIR) $(1)/usr/share/pbr
|
$(INSTALL_DIR) $(1)/usr/share/pbr
|
||||||
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.firewall.include $(1)/usr/share/pbr/pbr.firewall.include
|
$(INSTALL_DATA) ./files/usr/share/pbr/firewall.include $(1)/usr/share/pbr/firewall.include
|
||||||
$(INSTALL_DIR) $(1)/usr/share/nftables.d
|
$(INSTALL_DIR) $(1)/usr/share/nftables.d
|
||||||
$(CP) ./files/usr/share/nftables.d/* $(1)/usr/share/nftables.d/
|
$(CP) ./files/usr/share/nftables.d/* $(1)/usr/share/nftables.d/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-iptables/install
|
define Package/pbr-iptables/install
|
||||||
$(call Package/pbr/default/install,$(1))
|
$(call Package/pbr-service/install,$(1))
|
||||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
|
$(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
|
||||||
$(INSTALL_DATA) ./files/etc/hotplug.d/firewall/70-pbr $(1)/etc/hotplug.d/firewall/70-pbr
|
$(INSTALL_DATA) ./files/etc/hotplug.d/firewall/70-pbr $(1)/etc/hotplug.d/firewall/70-pbr
|
||||||
$(INSTALL_DIR) $(1)/etc/config
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
|
@ -107,7 +116,7 @@ $(call Package/pbr/default/install,$(1))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/pbr-netifd/install
|
define Package/pbr-netifd/install
|
||||||
$(call Package/pbr/default/install,$(1))
|
$(call Package/pbr-service/install,$(1))
|
||||||
$(INSTALL_DIR) $(1)/etc/config
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
|
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
|
||||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||||
|
@ -133,7 +142,7 @@ define Package/pbr/prerm
|
||||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||||
uci -q delete firewall.pbr || true
|
uci -q delete firewall.pbr || true
|
||||||
echo "Stopping pbr service... "
|
echo "Stopping pbr service... "
|
||||||
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr stop quiet && echo "OK" || echo "FAIL"
|
||||||
echo -n "Removing rc.d symlink for pbr... "
|
echo -n "Removing rc.d symlink for pbr... "
|
||||||
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
||||||
fi
|
fi
|
||||||
|
@ -165,7 +174,7 @@ define Package/pbr-iptables/prerm
|
||||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||||
uci -q delete firewall.pbr || true
|
uci -q delete firewall.pbr || true
|
||||||
echo "Stopping pbr-iptables service... "
|
echo "Stopping pbr-iptables service... "
|
||||||
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr stop quiet && echo "OK" || echo "FAIL"
|
||||||
echo -n "Removing rc.d symlink for pbr-iptables... "
|
echo -n "Removing rc.d symlink for pbr-iptables... "
|
||||||
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
||||||
fi
|
fi
|
||||||
|
@ -188,7 +197,7 @@ define Package/pbr-netifd/prerm
|
||||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||||
uci -q delete firewall.pbr || true
|
uci -q delete firewall.pbr || true
|
||||||
echo "Stopping pbr-netifd service... "
|
echo "Stopping pbr-netifd service... "
|
||||||
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr stop quiet && echo "OK" || echo "FAIL"
|
||||||
echo -n "Removing rc.d symlink for pbr... "
|
echo -n "Removing rc.d symlink for pbr... "
|
||||||
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -2,14 +2,23 @@ config pbr 'config'
|
||||||
option enabled '0'
|
option enabled '0'
|
||||||
option verbosity '2'
|
option verbosity '2'
|
||||||
option strict_enforcement '1'
|
option strict_enforcement '1'
|
||||||
option resolver_set 'none'
|
option resolver_set 'dnsmasq.nftset'
|
||||||
|
list resolver_instance '*'
|
||||||
option ipv6_enabled '0'
|
option ipv6_enabled '0'
|
||||||
list ignored_interface 'vpnserver'
|
list ignored_interface 'vpnserver'
|
||||||
list ignored_interface 'wgserver'
|
option nft_file_support '0'
|
||||||
option boot_timeout '30'
|
option boot_timeout '30'
|
||||||
option rule_create_option 'add'
|
option rule_create_option 'add'
|
||||||
|
option procd_boot_delay '0'
|
||||||
option procd_reload_delay '1'
|
option procd_reload_delay '1'
|
||||||
option webui_show_ignore_target '0'
|
option webui_show_ignore_target '0'
|
||||||
|
option nft_set_auto_merge '1'
|
||||||
|
option nft_set_counter '1'
|
||||||
|
option nft_set_flags_interval '1'
|
||||||
|
option nft_set_flags_timeout '0'
|
||||||
|
option nft_set_gc_interval ''
|
||||||
|
option nft_set_policy 'performance'
|
||||||
|
option nft_set_timeout ''
|
||||||
list webui_supported_protocol 'all'
|
list webui_supported_protocol 'all'
|
||||||
list webui_supported_protocol 'tcp'
|
list webui_supported_protocol 'tcp'
|
||||||
list webui_supported_protocol 'udp'
|
list webui_supported_protocol 'udp'
|
||||||
|
@ -18,11 +27,21 @@ config pbr 'config'
|
||||||
|
|
||||||
config include
|
config include
|
||||||
option path '/usr/share/pbr/pbr.user.aws'
|
option path '/usr/share/pbr/pbr.user.aws'
|
||||||
option enabled 0
|
option enabled '0'
|
||||||
|
|
||||||
config include
|
config include
|
||||||
option path '/usr/share/pbr/pbr.user.netflix'
|
option path '/usr/share/pbr/pbr.user.netflix'
|
||||||
option enabled 0
|
option enabled '0'
|
||||||
|
|
||||||
|
config include
|
||||||
|
option path '/usr/share/pbr/pbr.user.wg_server_and_client'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
|
config policy
|
||||||
|
option name 'Ignore Local Requests'
|
||||||
|
option interface 'ignore'
|
||||||
|
option dest_addr '10.0.0.0/24 10.0.1.0/24 192.168.100.0/24 192.168.1.0/24'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
config policy
|
config policy
|
||||||
option name 'Plex/Emby Local Server'
|
option name 'Plex/Emby Local Server'
|
||||||
|
|
|
@ -3,11 +3,12 @@ config pbr 'config'
|
||||||
option verbosity '2'
|
option verbosity '2'
|
||||||
option strict_enforcement '1'
|
option strict_enforcement '1'
|
||||||
option resolver_set 'dnsmasq.ipset'
|
option resolver_set 'dnsmasq.ipset'
|
||||||
|
list resolver_instance '*'
|
||||||
option ipv6_enabled '0'
|
option ipv6_enabled '0'
|
||||||
list ignored_interface 'vpnserver'
|
list ignored_interface 'vpnserver'
|
||||||
list ignored_interface 'wgserver'
|
|
||||||
option boot_timeout '30'
|
option boot_timeout '30'
|
||||||
option rule_create_option 'add'
|
option rule_create_option 'add'
|
||||||
|
option procd_boot_delay '0'
|
||||||
option procd_reload_delay '1'
|
option procd_reload_delay '1'
|
||||||
option webui_show_ignore_target '0'
|
option webui_show_ignore_target '0'
|
||||||
list webui_supported_protocol 'all'
|
list webui_supported_protocol 'all'
|
||||||
|
@ -24,6 +25,10 @@ config include
|
||||||
option path '/usr/share/pbr/pbr.user.netflix'
|
option path '/usr/share/pbr/pbr.user.netflix'
|
||||||
option enabled 0
|
option enabled 0
|
||||||
|
|
||||||
|
config include
|
||||||
|
option path '/usr/share/pbr/pbr.user.wg_server_and_client'
|
||||||
|
option enabled 0
|
||||||
|
|
||||||
config policy
|
config policy
|
||||||
option name 'Plex/Emby Local Server'
|
option name 'Plex/Emby Local Server'
|
||||||
option interface 'wan'
|
option interface 'wan'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
[ "$ACTION" = "reload" ] || [ "$ACTION" = "restart" ] || exit 0
|
[ "$ACTION" = "reload" ] || [ "$ACTION" = "restart" ] || exit 0
|
||||||
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
|
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
|
||||||
logger -t "pbr" "Reloading pbr due to firewall action: $ACTION"
|
logger -t "pbr" "Sending reload signal to pbr due to firewall action: $ACTION"
|
||||||
/etc/init.d/pbr reload
|
/etc/init.d/pbr reload
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC1091,SC3060
|
# shellcheck disable=SC1091,SC3060
|
||||||
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
|
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
|
||||||
logger -t pbr "Reloading pbr $INTERFACE interface routing due to $ACTION of $INTERFACE ($DEVICE)"
|
logger -t pbr "Sending reload signal to pbr for $INTERFACE due to $ACTION of $INTERFACE${DEVICE:+ ($DEVICE)}"
|
||||||
/etc/init.d/pbr on_interface_reload "$INTERFACE"
|
/etc/init.d/pbr on_interface_reload "$INTERFACE" "$ACTION"
|
||||||
fi
|
fi
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +1,33 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC1091,SC3037,SC3043
|
|
||||||
|
|
||||||
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
|
readonly pbrFunctionsFile='/etc/init.d/pbr'
|
||||||
|
if [ -s "$pbrFunctionsFile" ]; then
|
||||||
|
# shellcheck source=../../etc/init.d/pbr
|
||||||
|
. "$pbrFunctionsFile"
|
||||||
|
else
|
||||||
|
printf "%b: pbr init.d file (%s) not found! \n" '\033[0;31mERROR\033[0m' "$pbrFunctionsFile"
|
||||||
|
fi
|
||||||
|
|
||||||
# Transition from vpn-policy-routing
|
# Transition from vpn-policy-routing
|
||||||
if [ -s '/etc/config/vpn-policy-routing' ] && [ ! -s '/etc/config/pbr-opkg' ]; then
|
if [ -s '/etc/config/vpn-policy-routing' ] && [ ! -s '/etc/config/pbr-opkg' ] \
|
||||||
|
&& [ "$(uci_get pbr config enabled)" = '0' ]; then
|
||||||
if [ -x '/etc/init.d/vpn-policy-routing' ]; then
|
if [ -x '/etc/init.d/vpn-policy-routing' ]; then
|
||||||
echo "Stopping and disabling vpn-policy-routing."
|
output "Stopping and disabling vpn-policy-routing."
|
||||||
/etc/init.d/vpn-policy-routing stop
|
if /etc/init.d/vpn-policy-routing stop \
|
||||||
/etc/init.d/vpn-policy-routing disable
|
&& /etc/init.d/vpn-policy-routing disable; then
|
||||||
|
output_okn
|
||||||
|
else
|
||||||
|
output_failn
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
output "Migrating vpn-policy-routing config file."
|
||||||
|
if mv '/etc/config/pbr' '/etc/config/pbr-opkg' \
|
||||||
|
&& sed 's/vpn-policy-routing/pbr/g' /etc/config/vpn-policy-routing > /etc/config/pbr \
|
||||||
|
&& uci_set vpn-policy-routing config enabled 0 && uci_commit vpn-policy-routing; then
|
||||||
|
output_okn
|
||||||
|
else
|
||||||
|
output_failn
|
||||||
fi
|
fi
|
||||||
echo "Migrating vpn-policy-routing config file."
|
|
||||||
mv '/etc/config/pbr' '/etc/config/pbr-opkg'
|
|
||||||
sed 's/vpn-policy-routing/pbr/g' /etc/config/vpn-policy-routing > /etc/config/pbr
|
|
||||||
uci set vpn-policy-routing.config.enabled=0; uci commit vpn-policy-routing;
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Transition from older versions of pbr
|
# Transition from older versions of pbr
|
||||||
|
@ -26,14 +40,17 @@ sed -i "s/'PREROUTING'/'prerouting'/g" /etc/config/pbr
|
||||||
sed -i "s/'POSTROUTING'/'postrouting'/g" /etc/config/pbr
|
sed -i "s/'POSTROUTING'/'postrouting'/g" /etc/config/pbr
|
||||||
sed -i "s/option fw_mask '0x\(.*\)'/option fw_mask '\1'/g" /etc/config/pbr
|
sed -i "s/option fw_mask '0x\(.*\)'/option fw_mask '\1'/g" /etc/config/pbr
|
||||||
sed -i "s/option wan_mark '0x\(.*\)'/option wan_mark '\1'/g" /etc/config/pbr
|
sed -i "s/option wan_mark '0x\(.*\)'/option wan_mark '\1'/g" /etc/config/pbr
|
||||||
|
sed -i "s|option path '/etc/pbr/|option path '/usr/share/pbr/|g" /etc/config/pbr
|
||||||
|
|
||||||
if [ -s '/usr/share/pbr/pbr.firewall.include' ]; then
|
# add firewall include file to fw4 config
|
||||||
|
# shellcheck source=../../usr/share/pbr/firewall.include
|
||||||
|
if [ -s '/usr/share/pbr/firewall.include' ]; then
|
||||||
uci -q batch <<-EOT
|
uci -q batch <<-EOT
|
||||||
delete firewall.pbr
|
delete firewall.pbr
|
||||||
set firewall.pbr='include'
|
set firewall.pbr='include'
|
||||||
set firewall.pbr.fw4_compatible='1'
|
set firewall.pbr.fw4_compatible='1'
|
||||||
set firewall.pbr.type='script'
|
set firewall.pbr.type='script'
|
||||||
set firewall.pbr.path='/usr/share/pbr/pbr.firewall.include'
|
set firewall.pbr.path='/usr/share/pbr/firewall.include'
|
||||||
commit firewall
|
commit firewall
|
||||||
EOT
|
EOT
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC1091,SC3037,SC3043
|
# shellcheck disable=SC3037,SC3043
|
||||||
|
|
||||||
readonly packageName='pbr'
|
readonly pbrFunctionsFile='/etc/init.d/pbr'
|
||||||
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
|
if [ -s "$pbrFunctionsFile" ]; then
|
||||||
|
# shellcheck source=../../etc/init.d/pbr
|
||||||
|
. "$pbrFunctionsFile"
|
||||||
|
else
|
||||||
|
printf "%b: pbr init.d file (%s) not found! \n" '\033[0;31mERROR\033[0m' "$pbrFunctionsFile"
|
||||||
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2317
|
# shellcheck disable=SC2317
|
||||||
pbr_iface_setup() {
|
pbr_iface_setup() {
|
||||||
|
@ -15,17 +20,17 @@ pbr_iface_setup() {
|
||||||
case "${proto}" in
|
case "${proto}" in
|
||||||
(gre*|nebula|relay|vti*|vxlan|xfrm) return 0 ;;
|
(gre*|nebula|relay|vti*|vxlan|xfrm) return 0 ;;
|
||||||
(none)
|
(none)
|
||||||
uci -q set "network.${iface}_rt=route"
|
uci_add network route "${iface}_rt"
|
||||||
uci -q set "network.${iface}_rt.interface=${iface}"
|
uci_set network "${iface}_rt" interface "${iface}"
|
||||||
uci -q set "network.${iface}_rt.target=0.0.0.0/0"
|
uci_set network "${iface}_rt" target '0.0.0.0/0'
|
||||||
uci -q set "network.${iface}_rt6=route6"
|
uci_add route6 network "${iface}_rt6"
|
||||||
uci -q set "network.${iface}_rt6.interface=${iface}"
|
uci_set network "${iface}_rt6" interface "${iface}"
|
||||||
uci -q set "network.${iface}_rt6.target=::/0"
|
uci_set network "${iface}_rt6" target '::/0'
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo -en "Setting up ${packageName} routing tables for ${iface}... "
|
echo -en "Setting up ${packageName} routing tables for ${iface}... "
|
||||||
uci -q set "network.${iface}.ip4table=${packageName}_${iface%6}"
|
uci_set 'network' "${iface}" 'ip4table' "${packageName}_${iface%6}"
|
||||||
uci -q set "network.${iface}.ip6table=${packageName}_${iface%6}"
|
uci_set 'network' "${iface}" 'ip6table' "${packageName}_${iface%6}"
|
||||||
if ! grep -q -E -e "^[0-9]+\s+${packageName}_${iface%6}$" /etc/iproute2/rt_tables; then
|
if ! grep -q -E -e "^[0-9]+\s+${packageName}_${iface%6}$" /etc/iproute2/rt_tables; then
|
||||||
sed -i -e "\$a $(($(sort -r -n /etc/iproute2/rt_tables | grep -o -E -m 1 "^[0-9]+")+1))\t${packageName}_${iface%6}" \
|
sed -i -e "\$a $(($(sort -r -n /etc/iproute2/rt_tables | grep -o -E -m 1 "^[0-9]+")+1))\t${packageName}_${iface%6}" \
|
||||||
/etc/iproute2/rt_tables
|
/etc/iproute2/rt_tables
|
||||||
|
@ -33,8 +38,6 @@ pbr_iface_setup() {
|
||||||
echo -e "${__OK__}"
|
echo -e "${__OK__}"
|
||||||
}
|
}
|
||||||
|
|
||||||
. /lib/functions.sh
|
|
||||||
. /lib/functions/network.sh
|
|
||||||
config_load network
|
config_load network
|
||||||
config_foreach pbr_iface_setup interface
|
config_foreach pbr_iface_setup interface
|
||||||
network_flush_cache
|
network_flush_cache
|
||||||
|
@ -51,7 +54,7 @@ set network.default6='rule6'
|
||||||
set network.default6.lookup='${packageName}_${iface6%6}'
|
set network.default6.lookup='${packageName}_${iface6%6}'
|
||||||
set network.default6.priority='80000'
|
set network.default6.priority='80000'
|
||||||
EOF
|
EOF
|
||||||
uci commit network
|
uci_commit network
|
||||||
echo -en "Restarting network... "
|
echo -en "Restarting network... "
|
||||||
/etc/init.d/network restart
|
/etc/init.d/network restart
|
||||||
echo -e "${__OK__}"
|
echo -e "${__OK__}"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
|
||||||
|
logger -t "pbr" "Sending reload signal to pbr due to firewall action: $ACTION"
|
||||||
|
/etc/init.d/pbr on_firewall_reload "$ACTION"
|
||||||
|
fi
|
|
@ -1,31 +1,44 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh
|
# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh
|
||||||
|
|
||||||
TARGET_SET='pbr_wan_4_dst_ip_user'
|
TARGET_INTERFACE='wan'
|
||||||
TARGET_IPSET='pbr_wan_4_dst_net_user'
|
TARGET_NFTSET_4="pbr_${TARGET_INTERFACE}_4_dst_ip_user"
|
||||||
|
TARGET_NFTSET_6="pbr_${TARGET_INTERFACE}_6_dst_ip_user"
|
||||||
|
TARGET_IPSET_4="pbr_${TARGET_INTERFACE}_4_dst_net_user"
|
||||||
|
TARGET_IPSET_6="pbr_${TARGET_INTERFACE}_6_dst_net_user"
|
||||||
TARGET_TABLE='inet fw4'
|
TARGET_TABLE='inet fw4'
|
||||||
TARGET_URL="https://ip-ranges.amazonaws.com/ip-ranges.json"
|
TARGET_URL="https://ip-ranges.amazonaws.com/ip-ranges.json"
|
||||||
TARGET_DL_FILE="/var/pbr_tmp_aws_ip_ranges"
|
TARGET_DL_FILE_4="/var/pbr_tmp_aws_ip_ranges.ipv4"
|
||||||
TARGET_NFT_FILE="/var/pbr_tmp_aws_ip_ranges.nft"
|
# Uncomment the following line if you enabled ipv6 for pbr and want IPv6 entries added to the IPv6 set
|
||||||
[ -z "$nft" ] && nft="$(command -v nft)"
|
# TARGET_DL_FILE_6="/var/pbr_tmp_aws_ip_ranges.ipv6"
|
||||||
_ret=1
|
_ret=0
|
||||||
|
|
||||||
if [ ! -s "$TARGET_DL_FILE" ]; then
|
if [ ! -s "$TARGET_DL_FILE_4" ]; then
|
||||||
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep "ip_prefix" | sed 's/^.*\"ip_prefix\": \"//; s/\",//' > "$TARGET_DL_FILE"
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep "ip_prefix" | sed 's/^.*\"ip_prefix\": \"//; s/\",//' > "$TARGET_DL_FILE_4"
|
||||||
|
fi
|
||||||
|
if [ -s "$TARGET_DL_FILE_4" ]; then
|
||||||
|
if [ -n "$nft" ] && [ -x "$nft" ]; then
|
||||||
|
while read -r p; do "$nft" "add element $TARGET_TABLE $TARGET_NFTSET_4 { $p }" || _ret=1; done < "$TARGET_DL_FILE_4"
|
||||||
|
elif ipset -q list "$TARGET_IPSET_4" >/dev/null 2>&1; then
|
||||||
|
if awk -v ipset="$TARGET_IPSET_4" '{print "add " ipset " " $1}' "$TARGET_DL_FILE_4" | ipset restore -!; then
|
||||||
|
_ret=0
|
||||||
|
else
|
||||||
|
_ret=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -s "$TARGET_DL_FILE" ]; then
|
if [ -n "$TARGET_DL_FILE_6" ] && [ ! -s "$TARGET_DL_FILE_6" ]; then
|
||||||
if ipset -q list "$TARGET_IPSET" >/dev/null 2>&1; then
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep "ipv6_prefix" | sed 's/^.*\"ipv6_prefix\": \"//; s/\",//' > "$TARGET_DL_FILE_6"
|
||||||
if awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_DL_FILE" | ipset restore -!; then
|
fi
|
||||||
_ret=0
|
if [ -s "$TARGET_DL_FILE_6" ]; then
|
||||||
fi
|
if [ -n "$nft" ] && [ -x "$nft" ]; then
|
||||||
elif [ -n "$nft" ] && [ -x "$nft" ] && "$nft" list set "$TARGET_TABLE" "$TARGET_SET" >/dev/null 2>&1; then
|
while read -r p; do "$nft" "add element $TARGET_TABLE $TARGET_NFTSET_6 { $p }" || _ret=1; done < "$TARGET_DL_FILE_6"
|
||||||
printf "add element %s %s { " "$TARGET_TABLE" "$TARGET_SET" > "$TARGET_NFT_FILE"
|
elif ipset -q list "$TARGET_IPSET_6" >/dev/null 2>&1; then
|
||||||
awk '{printf $1 ", "}' "$TARGET_DL_FILE" >> "$TARGET_NFT_FILE"
|
if awk -v ipset="$TARGET_IPSET_6" '{print "add " ipset " " $1}' "$TARGET_DL_FILE_6" | ipset restore -!; then
|
||||||
printf " } " >> "$TARGET_NFT_FILE"
|
|
||||||
if "$nft" -f "$TARGET_NFT_FILE"; then
|
|
||||||
rm -f "$TARGET_NFT_FILE"
|
|
||||||
_ret=0
|
_ret=0
|
||||||
|
else
|
||||||
|
_ret=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -3,45 +3,63 @@
|
||||||
# Credits to https://forum.openwrt.org/u/dscpl for api.hackertarget.com code.
|
# Credits to https://forum.openwrt.org/u/dscpl for api.hackertarget.com code.
|
||||||
# Credits to https://github.com/kkeker and https://github.com/tophirsch for api.bgpview.io code.
|
# Credits to https://github.com/kkeker and https://github.com/tophirsch for api.bgpview.io code.
|
||||||
|
|
||||||
TARGET_SET='pbr_wan_4_dst_ip_user'
|
TARGET_INTERFACE='wan'
|
||||||
TARGET_IPSET='pbr_wan_4_dst_net_user'
|
TARGET_NFTSET_4="pbr_${TARGET_INTERFACE}_4_dst_ip_user"
|
||||||
|
TARGET_NFTSET_6="pbr_${TARGET_INTERFACE}_6_dst_ip_user"
|
||||||
|
TARGET_IPSET_4="pbr_${TARGET_INTERFACE}_4_dst_net_user"
|
||||||
|
TARGET_IPSET_6="pbr_${TARGET_INTERFACE}_6_dst_net_user"
|
||||||
TARGET_TABLE='inet fw4'
|
TARGET_TABLE='inet fw4'
|
||||||
TARGET_ASN='2906'
|
TARGET_ASN='2906'
|
||||||
TARGET_DL_FILE="/var/pbr_tmp_AS${TARGET_ASN}"
|
TARGET_DL_FILE_4="/var/pbr_tmp_AS${TARGET_ASN}.ipv4"
|
||||||
TARGET_NFT_FILE="/var/pbr_tmp_AS${TARGET_ASN}.nft"
|
# Uncomment the following line if you enabled ipv6 for pbr and want IPv6 entries added to the IPv6 set
|
||||||
#DB_SOURCE='ipinfo.io'
|
# TARGET_DL_FILE_6="/var/pbr_tmp_AS${TARGET_ASN}.ipv6"
|
||||||
|
DB_SOURCE='ipinfo.io'
|
||||||
#DB_SOURCE='api.hackertarget.com'
|
#DB_SOURCE='api.hackertarget.com'
|
||||||
DB_SOURCE='api.bgpview.io'
|
#DB_SOURCE='api.bgpview.io'
|
||||||
[ -z "$nft" ] && nft="$(command -v nft)"
|
REGEX_IPV4='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\/[0-9]\{1,\}'
|
||||||
_ret=1
|
REGEX_IPV6='.*::.*'
|
||||||
|
_ret=0
|
||||||
|
|
||||||
if [ ! -s "$TARGET_DL_FILE" ]; then
|
if [ ! -s "$TARGET_DL_FILE_4" ]; then
|
||||||
if [ "$DB_SOURCE" = "ipinfo.io" ]; then
|
if [ "$DB_SOURCE" = "ipinfo.io" ]; then
|
||||||
TARGET_URL="https://ipinfo.io/AS${TARGET_ASN}"
|
TARGET_URL="https://ipinfo.io/AS${TARGET_ASN}"
|
||||||
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep -E "a href.*${TARGET_ASN}\/" | grep -v ":" | sed "s/^.*<a href=\"\/AS${TARGET_ASN}\///; s/\" >//" > "$TARGET_DL_FILE"
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | sed -n "s|\(.*\)/AS${TARGET_ASN}/\($REGEX_IPV4\)\"|\2|p" > "$TARGET_DL_FILE_4"
|
||||||
fi
|
fi
|
||||||
if [ "$DB_SOURCE" = "api.hackertarget.com" ]; then
|
if [ "$DB_SOURCE" = "api.hackertarget.com" ]; then
|
||||||
TARGET_URL="https://api.hackertarget.com/aslookup/?q=AS${TARGET_ASN}"
|
TARGET_URL="https://api.hackertarget.com/aslookup/?q=AS${TARGET_ASN}"
|
||||||
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | sed '1d' > "$TARGET_DL_FILE"
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | sed '1d' > "$TARGET_DL_FILE_4"
|
||||||
fi
|
fi
|
||||||
if [ "$DB_SOURCE" = "api.bgpview.io" ]; then
|
if [ "$DB_SOURCE" = "api.bgpview.io" ]; then
|
||||||
TARGET_URL="https://api.bgpview.io/asn/${TARGET_ASN}/prefixes"
|
TARGET_URL="https://api.bgpview.io/asn/${TARGET_ASN}/prefixes"
|
||||||
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | jsonfilter -e '@.data.ipv4_prefixes[*].prefix' > "$TARGET_DL_FILE"
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | jsonfilter -e '@.data.ipv4_prefixes[*].prefix' > "$TARGET_DL_FILE_4"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -s "$TARGET_DL_FILE_4" ]; then
|
||||||
|
if [ -n "$nft" ] && [ -x "$nft" ]; then
|
||||||
|
while read -r p; do "$nft" "add element $TARGET_TABLE $TARGET_NFTSET_4 { $p }" || _ret=1; done < "$TARGET_DL_FILE_4"
|
||||||
|
elif ipset -q list "$TARGET_IPSET_4" >/dev/null 2>&1; then
|
||||||
|
if awk -v ipset="$TARGET_IPSET_4" '{print "add " ipset " " $1}' "$TARGET_DL_FILE_4" | ipset restore -!; then
|
||||||
|
_ret=0
|
||||||
|
else
|
||||||
|
_ret=1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -s "$TARGET_DL_FILE" ]; then
|
if [ -n "$TARGET_DL_FILE_6" ] && [ ! -s "$TARGET_DL_FILE_6" ]; then
|
||||||
if ipset -q list "$TARGET_IPSET" >/dev/null 2>&1; then
|
if [ "$DB_SOURCE" = "ipinfo.io" ]; then
|
||||||
if awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_DL_FILE" | ipset restore -!; then
|
TARGET_URL="https://ipinfo.io/AS${TARGET_ASN}"
|
||||||
_ret=0
|
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | sed -n "s|\(.*\)/AS${TARGET_ASN}/\($REGEX_IPV6\)\"|\2|p" > "$TARGET_DL_FILE_6"
|
||||||
fi
|
fi
|
||||||
elif [ -n "$nft" ] && [ -x "$nft" ] && "$nft" list set "$TARGET_TABLE" "$TARGET_SET" >/dev/null 2>&1; then
|
fi
|
||||||
printf "add element %s %s { " "$TARGET_TABLE" "$TARGET_SET" > "$TARGET_NFT_FILE"
|
if [ -s "$TARGET_DL_FILE_6" ]; then
|
||||||
awk '{printf $1 ", "}' "$TARGET_DL_FILE" >> "$TARGET_NFT_FILE"
|
if [ -n "$nft" ] && [ -x "$nft" ]; then
|
||||||
printf " } " >> "$TARGET_NFT_FILE"
|
while read -r p; do "$nft" "add element $TARGET_TABLE $TARGET_NFTSET_6 { $p }" || _ret=1; done < "$TARGET_DL_FILE_6"
|
||||||
if "$nft" -f "$TARGET_NFT_FILE"; then
|
elif ipset -q list "$TARGET_IPSET_6" >/dev/null 2>&1; then
|
||||||
rm -f "$TARGET_NFT_FILE"
|
if awk -v ipset="$TARGET_IPSET_6" '{print "add " ipset " " $1}' "$TARGET_DL_FILE_6" | ipset restore -!; then
|
||||||
_ret=0
|
_ret=0
|
||||||
|
else
|
||||||
|
_ret=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# shellcheck disable=SC1091,SC3043
|
||||||
|
# This code is based on idea of https://github.com/egc112
|
||||||
|
|
||||||
|
WAN_INTERFACE='wan'
|
||||||
|
_ret='1'
|
||||||
|
|
||||||
|
insert_ip_rule() {
|
||||||
|
local proto listen_port
|
||||||
|
config_get proto "$1" proto
|
||||||
|
config_get listen_port "$1" listen_port
|
||||||
|
if [ "$proto" = 'wireguard' ] && [ -n "$listen_port" ]; then
|
||||||
|
ip rule del sport "$listen_port" table "pbr_${WAN_INTERFACE}" >/dev/null 2>&1
|
||||||
|
ip rule add sport "$listen_port" table "pbr_${WAN_INTERFACE}" >/dev/null 2>&1 && _ret=0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
. /lib/functions.sh
|
||||||
|
config_load network
|
||||||
|
config_foreach insert_ip_rule 'interface'
|
||||||
|
|
||||||
|
return $_ret
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
/etc/init.d/"$1" version 2>&1 | grep "$2"
|
/etc/init.d/pbr version 2>&1 | grep "$2"
|
||||||
|
|
Loading…
Reference in New Issue