You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
5.2 KiB
Bash
226 lines
5.2 KiB
Bash
#!/bin/sh
|
|
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/home/root
|
|
#
|
|
# VPN Client selective routing up down script
|
|
#
|
|
# Copyright by pedro 2019 - 2024
|
|
#
|
|
|
|
|
|
. nvram_ops
|
|
|
|
PID=$$
|
|
IFACE=$dev
|
|
SERVICE=$(echo $dev | sed 's/\(tun\|tap\)1/client/;s/\(tun\|tap\)2/server/')
|
|
FIREWALL_ROUTING="/etc/openvpn/fw/$SERVICE-fw-routing.sh"
|
|
DNSMASQ_IPSET="/etc/dnsmasq.ipset"
|
|
RESTART_DNSMASQ=0
|
|
RESTART_FW=0
|
|
ID="0"
|
|
LOGS="logger -t openvpn-vpnrouting.sh[$PID][$IFACE]"
|
|
[ -d /etc/openvpn/fw ] || mkdir -m 0700 "/etc/openvpn/fw"
|
|
|
|
|
|
find_iface() {
|
|
# These IDs were intentionally picked to avoid overwriting
|
|
# marks set by QoS. See qos.c
|
|
if [ "$SERVICE" == "client1" ]; then
|
|
ID="2304" # 0x900
|
|
elif [ "$SERVICE" == "client2" ]; then
|
|
ID="2560" # 0xA00
|
|
# BCMARM-BEGIN
|
|
elif [ "$SERVICE" == "client3" ]; then
|
|
ID="2816" # 0xB00
|
|
# BCMARM-END
|
|
else
|
|
$LOGS "Interface not found!"
|
|
exit 0
|
|
fi
|
|
|
|
PIDFILE="/var/run/vpnrouting$ID.pid"
|
|
}
|
|
|
|
initTable() {
|
|
local ROUTE
|
|
$LOGS "Creating VPN routing table (mode $VPN_REDIR)"
|
|
|
|
[ "$VPN_REDIR" -eq 3 ] && {
|
|
ip route show table main dev $IFACE | while read ROUTE; do
|
|
ip route add table $ID $ROUTE dev $IFACE
|
|
done
|
|
}
|
|
# copy routes from main routing table (exclude vpns and default gateway)
|
|
[ "$VPN_REDIR" -eq 2 ] && {
|
|
ip route show table main | grep -Ev 'tun11|tun12|tun13|^default ' | while read ROUTE; do
|
|
ip route add table $ID $ROUTE
|
|
done
|
|
}
|
|
}
|
|
|
|
stopRouting() {
|
|
$LOGS "Clean-up routing"
|
|
|
|
ip route flush table $ID
|
|
ip route flush cache
|
|
|
|
[ -f "$FIREWALL_ROUTING" ] && {
|
|
sed -i "s/-A/-D/g" $FIREWALL_ROUTING
|
|
$FIREWALL_ROUTING
|
|
rm -f $FIREWALL_ROUTING &>/dev/null
|
|
}
|
|
# BCMARM-BEGIN
|
|
ipset destroy vpnrouting$ID
|
|
# BCMARM-END
|
|
# BCMARMNO-BEGIN
|
|
ipset --destroy vpnrouting$ID
|
|
# BCMARMNO-END
|
|
ip rule | grep "lookup $ID" && ip rule del fwmark $ID/0xf00 table $ID
|
|
|
|
sed -i $DNSMASQ_IPSET -e "/vpnrouting$ID/d"
|
|
}
|
|
|
|
startRouting() {
|
|
local DNSMASQ=0 i VAL1 VAL2 VAL3
|
|
|
|
stopRouting
|
|
NS vpn_client"${ID#??}"_rdnsmasq=0
|
|
|
|
$LOGS "Starting routing policy for openvpn-$SERVICE - Interface $IFACE - Table $ID"
|
|
|
|
[ -n "$route_vpn_gateway" ] && {
|
|
ip route add table $ID default via $route_vpn_gateway dev $IFACE
|
|
} || {
|
|
ip route add table $ID default dev $IFACE
|
|
}
|
|
ip rule add fwmark $ID/0xf00 table $ID priority 90
|
|
|
|
initTable
|
|
# BCMARM-BEGIN
|
|
ipset create vpnrouting$ID hash:ip
|
|
# BCMARM-END
|
|
# BCMARMNO-BEGIN
|
|
ipset --create vpnrouting$ID iphash
|
|
# BCMARMNO-END
|
|
|
|
echo "#!/bin/sh" > $FIREWALL_ROUTING # new routing file
|
|
# BCMARM-BEGIN
|
|
echo "iptables -t mangle -A PREROUTING -m set --match-set vpnrouting$ID dst,src -j MARK --set-mark $ID/0xf00" >> $FIREWALL_ROUTING
|
|
# BCMARM-END
|
|
# BCMARMNO-BEGIN
|
|
echo "iptables -t mangle -A PREROUTING -m set --set vpnrouting$ID dst,src -j MARK --set-mark $ID/0xf00" >> $FIREWALL_ROUTING
|
|
# BCMARMNO-END
|
|
|
|
# example of routing_val: 1<2<8.8.8.8<1>1<1<1.2.3.4<0>1<3<domain.com<0> (enabled<type<domain_or_IP<kill_switch>)
|
|
for i in $(echo "$(NG vpn_"$SERVICE"_routing_val)" | tr ">" "\n"); do
|
|
VAL1=$(echo $i | cut -d "<" -f1)
|
|
VAL2=$(echo $i | cut -d "<" -f2)
|
|
VAL3=$(echo $i | cut -d "<" -f3)
|
|
|
|
# only if rule is enabled
|
|
[ "$VAL1" -eq 1 ] && {
|
|
case "$VAL2" in
|
|
1) # from source
|
|
$LOGS "Type: $VAL2 - add $VAL3"
|
|
[ "$(echo $VAL3 | grep -)" ] && { # range
|
|
echo "iptables -t mangle -A PREROUTING -m iprange --src-range $VAL3 -j MARK --set-mark $ID/0xf00" >> $FIREWALL_ROUTING
|
|
} || {
|
|
echo "iptables -t mangle -A PREROUTING -s $VAL3 -j MARK --set-mark $ID/0xf00" >> $FIREWALL_ROUTING
|
|
}
|
|
;;
|
|
2) # to destination
|
|
$LOGS "Type: $VAL2 - add $VAL3"
|
|
echo "iptables -t mangle -A PREROUTING -d $VAL3 -j MARK --set-mark $ID/0xf00" >> $FIREWALL_ROUTING
|
|
;;
|
|
3) # to domain
|
|
$LOGS "Type: $VAL2 - add $VAL3"
|
|
echo "ipset=/$VAL3/vpnrouting$ID" >> $DNSMASQ_IPSET
|
|
# try to add ipset rule using forced query to DNS server
|
|
#nslookup $VAL3 2>/dev/null
|
|
|
|
DNSMASQ=1
|
|
;;
|
|
*) continue ;;
|
|
esac
|
|
}
|
|
done
|
|
|
|
chmod 700 $FIREWALL_ROUTING
|
|
RESTART_FW=1
|
|
|
|
[ "$DNSMASQ" -eq 1 ] && {
|
|
NS vpn_client"${ID#??}"_rdnsmasq=1
|
|
RESTART_DNSMASQ=1
|
|
}
|
|
|
|
$LOGS "Completed routing policy configuration for openvpn-$SERVICE"
|
|
}
|
|
|
|
checkRestart() {
|
|
[ "$RESTART_DNSMASQ" -eq 1 -o "$(NG "vpn_client"${ID#??}"_rdnsmasq")" -eq 1 ] && service dnsmasq restart
|
|
[ "$RESTART_FW" -eq 1 ] && service firewall restart
|
|
}
|
|
|
|
checkPid() {
|
|
local PIDNO
|
|
|
|
[ -f $PIDFILE ] && {
|
|
PIDNO=$(cat $PIDFILE)
|
|
cat "/proc/$PIDNO/cmdline" &>/dev/null
|
|
|
|
[ $? -eq 0 ] && {
|
|
# priority has the last process
|
|
$LOGS "Killing previous process ..."
|
|
kill -9 $PIDNO
|
|
echo $PID > $PIDFILE
|
|
|
|
[ $? -ne 0 ] && {
|
|
$LOGS "Could not create PID file"
|
|
exit 0
|
|
}
|
|
} || {
|
|
# process not found assume not running
|
|
echo $PID > $PIDFILE
|
|
[ $? -ne 0 ] && {
|
|
$LOGS "Could not create PID file"
|
|
exit 0
|
|
}
|
|
}
|
|
} || {
|
|
echo $PID > $PIDFILE
|
|
[ $? -ne 0 ] && {
|
|
$LOGS "Could not create PID file"
|
|
exit 0
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
###################################################
|
|
|
|
|
|
find_iface
|
|
checkPid
|
|
VPN_REDIR=$(NG vpn_"$SERVICE"_rgw)
|
|
|
|
[ "$script_type" == "route-up" -a "$VPN_REDIR" -lt 2 ] && {
|
|
$LOGS "Skipping, $SERVICE not in routing policy mode"
|
|
checkRestart
|
|
exit 0
|
|
}
|
|
|
|
[ "$script_type" == "route-pre-down" ] && {
|
|
stopRouting
|
|
}
|
|
|
|
[ "$script_type" == "route-up" ] && {
|
|
startRouting
|
|
}
|
|
|
|
checkRestart
|
|
|
|
ip route flush cache
|
|
|
|
rm -f $PIDFILE &>/dev/null
|
|
|
|
exit 0
|