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
PKG_NAME:=vpnbypass
PKG_VERSION:=1.3.0
PKG_RELEASE:=6
PKG_VERSION:=1.3.1
PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0+
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
@ -15,15 +15,16 @@ define Package/vpnbypass
SECTION:=net
CATEGORY:=Network
DEPENDS:=+ipset +iptables
CONFLICTS:=openvpn-policy-routing
TITLE:=Simple VPN Bypass Service
CONFLICTS:=vpn-policy-routing
TITLE:=VPN Bypass Service
PKGARCH:=all
endef
define Package/vpnbypass/description
This service can be used to enable simple VPN split tunnelling.
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.
endef
@ -52,4 +53,46 @@ define Package/vpnbypass/install
$(INSTALL_DATA) ./files/vpnbypass.hotplug $(1)/etc/hotplug.d/firewall/94-vpnbypass
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))

View File

@ -1,5 +1,5 @@
# 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
- 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
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
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
! 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
```
###### LEDE Project and OpenWrt DD trunk
###### LEDE Project 17.01.x and OpenWrt 18.xx or later
```sh
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

View File

@ -4,38 +4,45 @@ PKG_VERSION=
export START=94
export USE_PROCD=1
readonly __ok__='\033[0;32m[\xe2\x9c\x93]\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'
readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\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}; }
PKG_NAME="${PKG_NAME:-vpnbypass}"; p_name="${PKG_NAME} ${PKG_VERSION}"
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}; }
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() {
local c=1 enabled
config_load $PKG_NAME
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
local sleepCount=1
load_package_config
while : ; do
network_find_wan wan_if4
[ $serviceEnabled -gt 0 ] || return 1
[ -n "$wan_if4" ] && network_get_gateway wan_gw $wan_if4
[[ $c -ge 25 || -n "$wan_gw" ]] && break
output "$p_name waiting for wan gateway...\n"
sleep 2; network_flush_cache; let "c+=1";
[[ $sleepCount -ge 25 || -n "$wan_gw" ]] && break
output "$serviceName waiting for wan gateway...\n"
sleep 2; network_flush_cache; let "sleepCount+=1";
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() {
local d; d=$(echo "$*" | sed s/-A/-D/g);
[ "$d" != "$*" ] && iptables $d >/dev/null 2>&1
@ -46,7 +53,7 @@ ipt() {
d=$(echo "$*" | sed s/-N/-X/g)
[ "$d" != "$*" ] && iptables $d >/dev/null 2>&1
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() {
@ -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 ${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
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() {
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 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
iptables -t mangle -F VPNBYPASS >/dev/null 2>&1; iptables -t mangle -X VPNBYPASS >/dev/null 2>&1;
output "$p_name stopped\n"
ipt -t mangle -D PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS
ipt -t mangle -F VPNBYPASS; ipt -t mangle -X VPNBYPASS;
output "$serviceName stopped\n"
}
reload_service(){
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_load_interface() { is_supported_interface "$1" && ifaces="${ifaces}${1} "; }
service_triggers() {
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_add_config_trigger "config.change" "vpnbypass" /etc/init.d/vpnbypass reload
for n in $ifaces; do procd_add_interface_trigger "interface.*" "$n" /etc/init.d/openvpn-policy-routing reload; done;
for n in $ifaces; do procd_add_reload_interface_trigger "$n"; procd_add_interface_trigger "interface.*" "$n" /etc/init.d/${packageName} reload; done;
output 2 "$serviceName monitoring interfaces: $ifaces $_OK_\n"
procd_close_trigger
}