vpnbypass: better start/stop from Web UI and triggers

Signed-off-by: Stan Grishin <stangri@melmac.net>
This commit is contained in:
Stan Grishin 2018-01-25 19:16:35 -08:00
parent 74eecfebcc
commit d7b0dc611f
3 changed files with 93 additions and 46 deletions

View File

@ -4,8 +4,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=vpnbypass PKG_NAME:=vpnbypass
PKG_VERSION:=1.3.0 PKG_VERSION:=1.3.1
PKG_RELEASE:=6 PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0+ PKG_LICENSE:=GPL-3.0+
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net> PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
@ -15,15 +15,16 @@ define Package/vpnbypass
SECTION:=net SECTION:=net
CATEGORY:=Network CATEGORY:=Network
DEPENDS:=+ipset +iptables DEPENDS:=+ipset +iptables
CONFLICTS:=openvpn-policy-routing CONFLICTS:=vpn-policy-routing
TITLE:=Simple VPN Bypass Service TITLE:=VPN Bypass Service
PKGARCH:=all PKGARCH:=all
endef endef
define Package/vpnbypass/description define Package/vpnbypass/description
This service can be used to enable simple VPN split tunnelling. This service can be used to enable simple VPN split tunnelling.
Supports accessing domains, IP ranges outside of your VPN tunnel. Supports accessing domains, IP ranges outside of your VPN tunnel.
Also supports dedicating local ports/IP ranges for direct internet access (outside of your VPN tunnel). Also supports dedicating local ports/IP ranges for direct
internet access (outside of your VPN tunnel).
Please see the README for further information. Please see the README for further information.
endef endef
@ -52,4 +53,46 @@ define Package/vpnbypass/install
$(INSTALL_DATA) ./files/vpnbypass.hotplug $(1)/etc/hotplug.d/firewall/94-vpnbypass $(INSTALL_DATA) ./files/vpnbypass.hotplug $(1)/etc/hotplug.d/firewall/94-vpnbypass
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
while [ ! -z "$(uci -q get ucitrack.@vpnbypass[-1] 2>/dev/null)" ] ; do
uci -q delete ucitrack.@vpnbypass[-1]
done
while [ ! -z "$(uci -q get ucitrack.@firewall[-1].affects 2>/dev/null | awk '/vpnbypass/')" ] ; do
uci -q del_list ucitrack.@firewall[-1].affects='vpnbypass'
done
uci -q batch <<-EOF >/dev/null
add ucitrack vpnbypass
set ucitrack.@vpnbypass[-1].init='vpnbypass'
add_list ucitrack.@firewall[-1].affects='vpnbypass'
commit ucitrack
EOF
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo "Stopping service and removing rc.d symlink for vpnbypass"
/etc/init.d/vpnbypass stop || true
/etc/init.d/vpnbypass disable
while [ ! -z "$(uci -q get ucitrack.@vpnbypass[-1] 2>/dev/null)" ] ; do
uci -q delete ucitrack.@vpnbypass[-1]
done
while [ ! -z "$(uci -q get ucitrack.@firewall[-1].affects 2>/dev/null | awk '/vpnbypass/')" ] ; do
uci -q del_list ucitrack.@firewall[-1].affects='vpnbypass'
done
fi
exit 0
endef
$(eval $(call BuildPackage,vpnbypass)) $(eval $(call BuildPackage,vpnbypass))

View File

@ -1,5 +1,5 @@
# VPN Bypass # VPN Bypass
A simple PROCD-based vpnbypass service for OpenWrt/LEDE Project. Useful if your router accesses internet thru VPN client/tunnel, but you want specific traffic (ports, IP ranges, domains or local IP ranges) to be routed outside of this tunnel. A simple PROCD-based ```vpnbypass``` service for OpenWrt/LEDE Project. Useful if your router accesses internet thru VPN client/tunnel, but you want specific traffic (ports, IP ranges, domains or local IP ranges) to be routed outside of this tunnel.
## Features ## Features
- Allows to define local ports so that traffic to them is routed outside of the VPN tunnel (by default routes Plex Media Server traffic (port 32400) outside of the VPN tunnel). - Allows to define local ports so that traffic to them is routed outside of the VPN tunnel (by default routes Plex Media Server traffic (port 32400) outside of the VPN tunnel).
@ -52,15 +52,15 @@ If these packages are not found in the official feed/repo for your version of Op
#### Add custom repo to your router #### Add custom repo to your router
If your router is not set up with the access to repository containing these packages you will need to add custom repository to your router by connecting to your router via ssh and running the following commands: If your router is not set up with the access to repository containing these packages you will need to add custom repository to your router by connecting to your router via ssh and running the following commands:
###### OpenWrt CC 15.05.1 ###### OpenWrt 15.05.1
```sh ```sh
opkg update; opkg install wget libopenssl opkg update; opkg install ca-certificates wget libopenssl
echo -e -n 'untrusted comment: public key 7ffc7517c4cc0c56\nRWR//HUXxMwMVnx7fESOKO7x8XoW4/dRidJPjt91hAAU2L59mYvHy0Fa\n' > /tmp/stangri-repo.pub && opkg-key add /tmp/stangri-repo.pub echo -e -n 'untrusted comment: public key 7ffc7517c4cc0c56\nRWR//HUXxMwMVnx7fESOKO7x8XoW4/dRidJPjt91hAAU2L59mYvHy0Fa\n' > /tmp/stangri-repo.pub && opkg-key add /tmp/stangri-repo.pub
! grep -q 'stangri_repo' /etc/opkg/customfeeds.conf && echo 'src/gz stangri_repo https://raw.githubusercontent.com/stangri/openwrt-repo/master' >> /etc/opkg/customfeeds.conf ! grep -q 'stangri_repo' /etc/opkg/customfeeds.conf && echo 'src/gz stangri_repo https://raw.githubusercontent.com/stangri/openwrt-repo/master' >> /etc/opkg/customfeeds.conf
opkg update opkg update
``` ```
###### LEDE Project and OpenWrt DD trunk ###### LEDE Project 17.01.x and OpenWrt 18.xx or later
```sh ```sh
opkg update; opkg install uclient-fetch libustream-mbedtls opkg update; opkg install uclient-fetch libustream-mbedtls
echo -e -n 'untrusted comment: public key 7ffc7517c4cc0c56\nRWR//HUXxMwMVnx7fESOKO7x8XoW4/dRidJPjt91hAAU2L59mYvHy0Fa\n' > /tmp/stangri-repo.pub && opkg-key add /tmp/stangri-repo.pub echo -e -n 'untrusted comment: public key 7ffc7517c4cc0c56\nRWR//HUXxMwMVnx7fESOKO7x8XoW4/dRidJPjt91hAAU2L59mYvHy0Fa\n' > /tmp/stangri-repo.pub && opkg-key add /tmp/stangri-repo.pub

View File

@ -4,38 +4,45 @@ PKG_VERSION=
export START=94 export START=94
export USE_PROCD=1 export USE_PROCD=1
readonly __ok__='\033[0;32m[\xe2\x9c\x93]\033[0m' readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
readonly __fail__='\033[0;31m[\xe2\x9c\x97]\033[0m' readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
readonly __pass__='\033[0;33m[-]\033[0m' readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
readonly __error__='\033[0;31mERROR\033[0m' readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
readonly __PASS__='\033[0;33m[-]\033[0m'
readonly _ERROR_='\033[0;31mERROR\033[0m'
export verbosity=2 TID='200' IPSET='vpnbypass' FW_MARK='0x010000' FW_MASK='0xff0000' wan_if4 wan_gw export serviceEnabled verbosity=2 TID='200' IPSET='vpnbypass' FW_MARK='0x010000' FW_MASK='0xff0000' wan_if4 wan_gw
output() { [[ $# -ne 1 ]] && { [[ ! $((verbosity & $1)) -gt 0 ]] && return 0 || shift; }; local msg; msg=$(echo -n "${1/$p_name /service }" | sed 's|\\033\[[0-9]\?;\?[0-9]\?[0-9]\?m||g'); [[ -t 1 ]] && echo -e -n "$1"; [[ $(echo -e -n "$msg" | wc -l) -gt 0 ]] && logger -t "${PKG_NAME:-service} [$$]" "$(echo -e -n ${logmsg}${msg})" && logmsg='' || logmsg=${logmsg}${msg}; } output() { [[ $# -ne 1 ]] && { [[ ! $((verbosity & $1)) -gt 0 ]] && return 0 || shift; }; local msg; msg=$(echo -n "${1/$serviceName /service }" | sed 's|\\033\[[0-9]\?;\?[0-9]\?[0-9]\?m||g'); [[ -t 1 ]] && echo -e -n "$1"; [[ $(echo -e -n "$msg" | wc -l) -gt 0 ]] && logger -t "${packageName:-service} [$$]" "$(echo -e -n ${logmsg}${msg})" && logmsg='' || logmsg=${logmsg}${msg}; }
PKG_NAME="${PKG_NAME:-vpnbypass}"; p_name="${PKG_NAME} ${PKG_VERSION}" readonly packageName='vpnbypass'
readonly serviceName="$packageName $PKG_VERSION"
load_package_config() {
config_load "$packageName"
config_get_bool serviceEnabled 'config' 'enabled' 1
config_get verbosity 'config' 'verbosity' '2'
source /lib/functions/network.sh
}
is_enabled() { is_enabled() {
local c=1 enabled local sleepCount=1
config_load $PKG_NAME load_package_config
config_get_bool enabled 'config' 'enabled' 1
config_get verbosity 'config' 'verbosity' '2'
config_get TID 'config' 'table_number' '200'
config_get IPSET 'config' 'ipset' 'vpnbypass'
config_get FW_MARK 'config' 'fw_mark' '0x010000'
config_get FW_MASK 'config' 'fw_mask' '0xff0000'
source /lib/functions/network.sh
[[ $enabled -gt 0 ]] || { output "$__error__: $p_name is not enabled.\n"; return 1; }
source /lib/functions/network.sh
while : ; do while : ; do
network_find_wan wan_if4 network_find_wan wan_if4
[ $serviceEnabled -gt 0 ] || return 1
[ -n "$wan_if4" ] && network_get_gateway wan_gw $wan_if4 [ -n "$wan_if4" ] && network_get_gateway wan_gw $wan_if4
[[ $c -ge 25 || -n "$wan_gw" ]] && break [[ $sleepCount -ge 25 || -n "$wan_gw" ]] && break
output "$p_name waiting for wan gateway...\n" output "$serviceName waiting for wan gateway...\n"
sleep 2; network_flush_cache; let "c+=1"; sleep 2; network_flush_cache; let "sleepCount+=1";
done done
[ -n "$wan_gw" ] && return 0 || { output "$__error__: $p_name failed to discover WAN gateway.\n"; return 1; } [ -n "$wan_gw" ] && return 0
output "$__ERROR__: $serviceName failed to discover WAN gateway.\n"; return 1;
} }
is_ovpn() { local dev; dev=$(uci -q get network.$1.ifname); if [[ "${dev:0:3}" == "tun" || "${dev:0:3}" == "tap" || -f "/sys/devices/virtual/net/${dev}/tun_flags" ]]; then return 0; else return 1; fi; }
is_wan() { if [ -n "$wan_if4" ] && [ "$1" == "$wan_if4" ]; then return 0; else return 1; fi; }
is_supported_interface() { if is_wan "$1" || is_ovpn "$1"; then return 0; else return 1; fi; }
ipt() { ipt() {
local d; d=$(echo "$*" | sed s/-A/-D/g); local d; d=$(echo "$*" | sed s/-A/-D/g);
[ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1
@ -46,7 +53,7 @@ ipt() {
d=$(echo "$*" | sed s/-N/-X/g) d=$(echo "$*" | sed s/-N/-X/g)
[ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1
d="$*" d="$*"
iptables $d >/dev/null 2>&1 || output "\n$__error__: iptables $d\n" iptables $d >/dev/null 2>&1 || output "\n$__ERROR__: iptables $d\n"
} }
start_service() { start_service() {
@ -70,29 +77,26 @@ start_service() {
for ll in ${lports}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --sport "${ll//-/:}"; done for ll in ${lports}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --sport "${ll//-/:}"; done
for ll in ${routes}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -d "$ll"; done for ll in ${routes}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -d "$ll"; done
for ll in ${rports}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --dport "${ll//-/:}"; done for ll in ${rports}; do ipt -t mangle -I VPNBYPASS 1 -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --dport "${ll//-/:}"; done
output "$p_name started with TID: $TID; FW_MARK: $FW_MARK\n" output "$serviceName started with TID: $TID; FW_MARK: $FW_MARK\n"
} }
stop_service() { stop_service() {
is_enabled || return 1 load_package_config
ip rule del fwmark "$FW_MARK" table "$TID" >/dev/null 2>&1; ipset -q flush "$IPSET"; ipset -q destroy "$IPSET"; ip rule del fwmark "$FW_MARK" table "$TID" >/dev/null 2>&1; ipset -q flush "$IPSET"; ipset -q destroy "$IPSET";
ip route flush table "$TID"; ip route flush cache; ip route flush table "$TID"; ip route flush cache;
iptables -t mangle -D PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS >/dev/null 2>&1 ipt -t mangle -D PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS
iptables -t mangle -F VPNBYPASS >/dev/null 2>&1; iptables -t mangle -X VPNBYPASS >/dev/null 2>&1; ipt -t mangle -F VPNBYPASS; ipt -t mangle -X VPNBYPASS;
output "$p_name stopped\n" output "$serviceName stopped\n"
} }
reload_service(){ service_triggers_load_interface() { is_supported_interface "$1" && ifaces="${ifaces}${1} "; }
start_service
}
st_load_interfaces(){ local d; config_get d $1 ifname; [[ "$1" == "$wan_if4" || "$d" != "${d/tun}" || "$d" != "${d/tap}" ]] && ifaces=" ${1} ${ifaces}"; }
service_triggers() { service_triggers() {
local ifaces n local ifaces n
procd_add_reload_trigger 'vpnbypass' config_load network; config_foreach service_triggers_load_interface 'interface';
procd_add_reload_trigger 'firewall'
procd_add_reload_trigger 'openvpn'
procd_open_trigger procd_open_trigger
procd_add_config_trigger "config.change" "vpnbypass" /etc/init.d/vpnbypass reload for n in $ifaces; do procd_add_reload_interface_trigger "$n"; procd_add_interface_trigger "interface.*" "$n" /etc/init.d/${packageName} reload; done;
for n in $ifaces; do procd_add_interface_trigger "interface.*" "$n" /etc/init.d/openvpn-policy-routing reload; done; output 2 "$serviceName monitoring interfaces: $ifaces $_OK_\n"
procd_close_trigger procd_close_trigger
} }