vpnbypass: initial commit 3903/head
authorStan Grishin <stangri@melmac.net>
Mon, 23 Jan 2017 16:02:44 +0000 (08:02 -0800)
committerStan Grishin <stangri@melmac.net>
Fri, 27 Jan 2017 12:24:39 +0000 (04:24 -0800)
Signed-off-by: Stan Grishin <stangri@melmac.net>
vpnbypass: fixed renamed option in stop_service

Signed-off-by: Stan Grishin <stangri@melmac.net>
vpnbypass: fixed typo in makefile, switch FW_MARK to 0x010000 to play nice with SQM/mwan (thanks Hannu)

Signed-off-by: Stan Grishin <stangri@melmac.net>
vpnbypass: proper masking in setting mark

Signed-off-by: Stan Grishin <stangri@melmac.net>
vpnbypass: separating luci-app-vpnbypass into different tree

Signed-off-by: Stan Grishin <stangri@melmac.net>
vpnbypass: fixed incorrect use of procd_add_reload_interface_trigger according to http://wiki.prplfoundation.org/wiki/Procd_reference

Signed-off-by: Stan Grishin <stangri@melmac.net>
net/vpnbypass/Makefile [new file with mode: 0644]
net/vpnbypass/files/README.md [new file with mode: 0644]
net/vpnbypass/files/vpnbypass.conf [new file with mode: 0644]
net/vpnbypass/files/vpnbypass.hotplug [new file with mode: 0644]
net/vpnbypass/files/vpnbypass.init [new file with mode: 0644]

diff --git a/net/vpnbypass/Makefile b/net/vpnbypass/Makefile
new file mode 100644 (file)
index 0000000..a65e1a3
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (c) 2017 Stan Grishin (stangri@melmac.net)
+# This is free software, licensed under the GNU General Public License v3.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=vpnbypass
+PKG_VERSION:=1.0.0
+PKG_RELEASE:=4
+PKG_LICENSE:=GPL-3.0+
+PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/$(PKG_NAME)
+       SECTION:=net
+       CATEGORY:=Network
+       DEPENDS:=+ip-full +ipset +iptables +ubox +dnsmasq-full
+       CONFLICTS:=ip dnsmasq
+       TITLE:=Simple VPN Bypass Service
+       PKGARCH:=all
+endef
+
+define Package/$(PKG_NAME)/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).
+Please see the README for further information.
+
+endef
+
+define Package/$(PKG_NAME)/conffiles
+/etc/config/vpnbypass
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/$(PKG_NAME)/install
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/vpnbypass.init $(1)/etc/init.d/vpnbypass
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_CONF) ./files/vpnbypass.conf $(1)/etc/config/vpnbypass
+       $(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
+       $(INSTALL_DATA) ./files/vpnbypass.hotplug $(1)/etc/hotplug.d/firewall/90-vpnbypass
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
\ No newline at end of file
diff --git a/net/vpnbypass/files/README.md b/net/vpnbypass/files/README.md
new file mode 100644 (file)
index 0000000..9dd2cc2
--- /dev/null
@@ -0,0 +1,47 @@
+# OpenWrt Simple VPNBypass
+A simple PROCD-based vpnbypass init script 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
+- Routes Plex Media Server traffic outside of the VPN tunnel.
+- Allows you to define IPs/ranges in local network so that their traffic is routed outside of the VPN tunnel.
+- Allows you to define list of domain names which are accessed outside of the VPN tunnel (useful for Netflix, Hulu, etc).
+- Doesn't stay in memory -- creates the iptables rules which are automatically updated on WAN up/down.
+
+# Requirements
+This service requires following packages to be installed on your router: ip-full ipset iptables dnsmasq-full (dnsmasq-full requires you uninstall dnsmasq first). Run the following commands to satisfy the requirements:
+```sh
+opkg update
+opkg remove dnsmasq ip; opkg install ip-full ipset iptables dnsmasq-full
+```
+
+# How to install
+```sh
+opkg update
+opkg install vpnbypass luci-app-vpnbypass
+```
+Default install routes Plex Media Server traffic (port 32400) outside of the VPN tunnel, routes LogmeIn Hamachi traffic (25.0.0.0/8) outside of the VPN tunnel and also routes internet traffic from local IPs 192.168.1.80-192.168.1.88 outside of the VPN tunnel.
+
+# Documentation / Discussion
+Please head to OpenWrt/LEDE Project Forums for discussion of this script.
+
+# What's New
+1.0.0:
+- Hotplug script created during install.
+
+0.1.0:
+- Package built.
+- Support for user-defined ports implemented.
+- Support for user-defined routes implemented.
+- Support for user-defined local ranges implemented.
+
+0.0.1:
+- Initial release.
+
+# Known Issues
+Until user-defined domains are supported within vpnbypass config, you can set domains to be accessed outside of VPN tunnel like so:
+```sh
+uci add_list dhcp.@dnsmasq[-1].ipset='/github.com/plex.tv/google.com/vpnbypass'
+uci add_list dhcp.@dnsmasq[-1].ipset='/hulu.com/netflix.com/nhl.com/vpnbypass'
+uci commit dhcp
+/etc/init.d/dnsmasq restart
+```
\ No newline at end of file
diff --git a/net/vpnbypass/files/vpnbypass.conf b/net/vpnbypass/files/vpnbypass.conf
new file mode 100644 (file)
index 0000000..8c200e9
--- /dev/null
@@ -0,0 +1,5 @@
+config vpnbypass 'config'
+       option enabled '1'
+       list localport '32400'
+       list remotesubnet '25.0.0.0/8'
+       list localsubnet '192.168.1.80/28'
diff --git a/net/vpnbypass/files/vpnbypass.hotplug b/net/vpnbypass/files/vpnbypass.hotplug
new file mode 100644 (file)
index 0000000..a2874f9
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ "$ACTION" = "reload" ] && /etc/init.d/vpnbypass reload
diff --git a/net/vpnbypass/files/vpnbypass.init b/net/vpnbypass/files/vpnbypass.init
new file mode 100644 (file)
index 0000000..2bf5aa6
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh /etc/rc.common
+
+START=90
+USE_PROCD=1
+
+TID="200"; FW_MARK="0x010000"; IPSET="vpnbypass"; 
+
+output() {
+       [ -z "$verbosity" ] && config_get verbosity  'config' 'verbosity' '2'
+       [ -n "$2" -a $((verbosity)) -ne $(($2)) ] && return 0;
+       [ -t 1 ] && echo -e -n "$1"
+       [ $(echo -e -n "$1" | wc -l) -gt 0 ] && logger -t "vpnbypass[$$]" "$(echo -e -n ${logmsg}${1})" && logmsg='' || logmsg=${logmsg}${1}
+}
+
+vpnbypass_enabled() {
+    config_get_bool enabled 'config' 'enabled' 0
+    [ $((enabled)) -gt 0 ] && return 0 || { output "VPNBypass is not enabled in the config file!\nTo enable, run 'uci set vpnbypass.config.enabled=1; uci commit vpnbypass'\n"; return 1; }
+}
+
+boot() { ubus -t 30 wait_for network.interface && rc_procd start_service || output 'ERROR: Failed to settle network interface!\n'; }
+
+start_service() {
+       local ll
+    config_load vpnbypass
+    vpnbypass_enabled || return 1
+       [ -d /etc/openvpn ] || return 1
+    config_get lports   'config' 'localport'
+    config_get rports   'config' 'remoteport'
+    config_get routes   'config' 'remotesubnet'
+    config_get ranges   'config' 'localsubnet'
+    config_get domains  'config' 'domain'
+
+       procd_open_instance
+       procd_set_param stdout 1
+       procd_set_param stderr 1
+       procd_close_instance
+
+       . /lib/functions/network.sh; network_get_ipaddr wanip wan; network_get_gateway gwip wan; network_get_ipaddr lanip lan
+       [ ! "$wanip" ] && output 'ERROR: Could not get wan ip\n' && exit 0
+       [ ! "$gwip" ] && output 'ERROR: Could not get wan gateway\n' && exit 0
+       for ll in ${routes}; do (ip route del $ll; ip route add $ll via $gwip) >/dev/null 2>&1; done
+       (ip rule del fwmark $FW_MARK table $TID; iptables -t mangle -F; ipset -F $IPSET; ipset -X $IPSET) >/dev/null 2>&1
+       (ip route flush table $TID; ip route flush cache) >/dev/null 2>&1
+       (ip route add default via $gwip table $TID; ip route flush cache) >/dev/null 2>&1
+       (modprobe xt_set || modprobe ip_set; insmod ip_set_hash_ip) >/dev/null 2>&1
+       (ipset -N $IPSET iphash -q; ipset -F $IPSET) >/dev/null 2>&1
+       for ll in ${lports}; do iptables -t mangle -A PREROUTING -p tcp -m multiport --sport $ll -j MARK --set-mark $FW_MARK/$FW_MARK -m comment --comment "vpnbypass"; done
+       for ll in ${rports}; do iptables -t mangle -A PREROUTING -p tcp -m multiport --dport $ll -j MARK --set-mark $FW_MARK/$FW_MARK -m comment --comment "vpnbypass"; done
+       for ll in ${ranges}; do iptables -t mangle -I PREROUTING -s $ll -j MARK --set-mark $FW_MARK/$FW_MARK -m comment --comment "vpnbypass"; done
+       iptables -t mangle -A PREROUTING -m set --match-set $IPSET dst -j MARK --set-mark $FW_MARK/$FW_MARK -m comment --comment "vpnbypass"
+       ip rule add fwmark $FW_MARK table $TID
+       output "vpnbypass started with TID: $TID FW_MARK: $FW_MARK\n"
+}
+
+stop_service() {
+       local ll
+    config_load vpnbypass
+    vpnbypass_enabled || return 1
+    config_get routes   'config' 'remotesubnet'
+
+       [ -d /etc/openvpn ] || return 1
+       rm -f /etc/hotplug.d/firewall/${START}-${IPSET}
+       . /lib/functions/network.sh; network_get_ipaddr wanip wan; network_get_gateway gwip wan; network_get_ipaddr lanip lan
+       [ ! "$wanip" ] && output 'ERROR: Could not get wan ip\n' && exit 0
+       [ ! "$gwip" ] && output 'ERROR: Could not get wan gateway\n' && exit 0
+       for ll in ${routes}; do ip route del $ll >/dev/null 2>&1; done
+#      iptables-save | grep -Fv -- "vpnbypass" | iptables-restore
+       (ip rule del fwmark $FW_MARK table $TID; iptables -t mangle -F; ipset -F $IPSET; ipset -X $IPSET) >/dev/null 2>&1
+       (ip route flush table $TID; ip route flush cache) >/dev/null 2>&1
+       output "vpnbypass stopped\n"
+}
+
+service_triggers() {
+    procd_add_reload_trigger 'vpnbypass'
+    procd_add_reload_interface_trigger 'wan'
+}