mir3c/squashfs-root/usr/sbin/smartvpn.sh

539 lines
13 KiB
Bash
Executable File

#!/bin/sh
####################################################################################
#/etc/config/smartvpn example
#
#config global "settings"
# option disabled "1"
# option status "off"
# option type vpn
# option domain_file /etc/smartvpn/proxy.txt
# option proxy_local_port 10080
# option proxy_remote_ip 54.85.90.122
#mac: devices which transfer through vpn
#notmac: devices which not transfer through vpn
#config device 'device'
# list mac '34:17:eb:d0:e6:f9'
# list mac '34:17:eb:d0:e6:a9'
#host: website which transfer through vpn
#nothost: website which not transfer through vpn
#config dest 'dest'
# list host '.google.com'
# list notnet '169.254.0.0/16'
# list notnet '0.0.0.0/8'
# list notnet '10.0.0.0/8'
# list notnet '127.0.0.0/8'
# list notnet '169.254.0.0/16'
# list notnet '172.16.0.0/12'
# list notnet '192.168.0.0/16'
# list notnet '224.0.0.0/4'
# list notnet '240.0.0.0/4'
####################################################################################
#model=`nvram get model`
#if [ -z "$model" ]; then
# model=`cat /proc/xiaoqiang/model`
#fi
#if [ "$model" != "R1D" ]; then
# return 1
#fi
. /lib/functions.sh
. /lib/functions/network.sh
ipset_name="smartvpn"
ipset_ip_name="smartvpn_ip"
ipset_mark="0x10"
vpn_status="down"
smartvpn_cfg_domain_disabled=1
smartvpn_cfg_status="off"
smartvpn_cfg_type="vpn"
smartvpn_cfg_domainfile=""
dnsmasq_conf_path="/etc/dnsmasq.d/"
smartdns_conf_path="/etc/smartvpn/"
smartdns_conf_name="smartdns.conf"
smartdns_conf="$smartdns_conf_path/$smartdns_conf_name"
rule_file_ip="/etc/smartvpn/smartvpn_ip.txt"
set_smartvpn_cfg_status_on="uci set smartvpn.settings.status=on; uci commit smartvpn;"
set_smartvpn_cfg_status_off="uci set smartvpn.settings.status=off; uci commit smartvpn;"
hostlist_not_null=0
smartvpn_logger()
{
echo "smartvpn: $1"
logger -t smartvpn "$1"
}
smartvpn_usage()
{
echo "usage: ./smartvpn.sh on|off"
echo "value: on -- enable smartvpn"
echo "value: off -- disable smartvpn"
echo "note: smartvpn only used when vpn is UP!"
echo ""
}
dnsmasq_restart()
{
dnamasq_lock="/var/run/samartvpn.dnsmasq.lock"
trap "lock -u $dnamasq_lock; exit 1" SIGHUP SIGINT SIGTERM
lock $dnamasq_lock
$set_smartvpn_switch_off >/dev/null 2>&1
$set_switch_commit >/dev/null 2>&1
process_pid=$(ps | grep "/usr/sbin/dnsmasq" |grep -v "grep /usr/sbin/dnsmasq" | awk '{print $1}' 2>/dev/null)
process_num=$( echo $process_pid |awk '{print NF}' 2>/dev/null)
process_pid1=$( echo $process_pid |awk '{ print $1; exit;}' 2>/dev/null)
process_pid2=$( echo $process_pid |awk '{ print $2; exit;}' 2>/dev/null)
[ "$process_num" != "2" ] && /etc/init.d/dnsmasq restart
retry_times=0
while [ $retry_times -le 2 ]
do
let retry_times+=1
rm /var/etc/dnsmasq.conf
/etc/init.d/dnsmasq restart
sleep 1
process_newpid=$(ps | grep "/usr/sbin/dnsmasq" |grep -v "grep /usr/sbin/dnsmasq" | awk '{print $1}' 2>/dev/null)
process_newnum=$( echo $process_newpid |awk '{print NF}' 2>/dev/null)
process_newpid1=$( echo $process_newpid |awk '{ print $1; exit;}' 2>/dev/null)
process_newpid2=$( echo $process_newpid |awk '{ print $2; exit;}' 2>/dev/null)
echo "old: $process_pid1/$process_pid2 new: $process_newpid1/$process_newpid2"
[ "$process_pid1" == "$process_newpid1" ] && continue;
[ "$process_pid1" == "$process_newpid2" ] && continue;
[ "$process_pid2" == "$process_newpid1" ] && continue;
[ "$process_pid2" == "$process_newpid2" ] && continue;
break
done
lock -u $dnamasq_lock
}
smartvpn_dns_start()
{
# move dnsmasq conf
if [ -f $smartdns_conf ]; then
mv $smartdns_conf $dnsmasq_conf_path
fi
# flush dnsmasq
dnsmasq_restart
return
}
smartvpn_dns_stop()
{
# del smartvpn dnsmasq conf
rm "$dnsmasq_conf_path/$smartdns_conf_name"
rm "/var/etc/dnsmasq.d/$smartdns_conf_name"
rm "/tmp/etc/dnsmasq.d/$smartdns_conf_name"
# flush dnsmasq
dnsmasq_restart
return
}
smartvpn_ipset_create()
{
ipset list | grep $ipset_name > /dev/null 2>&1
if [ $? -ne 0 ]; then
ipset create $ipset_name hash:ip > /dev/null 2>&1
ipset create $ipset_ip_name hash:net > /dev/null 2>&1
fi
}
smartvpn_ipset_add_by_file()
{
local _ipfile=$1
[ -f $_ipfile ] || return
ipset create $ipset_ip_name hash:net > /dev/null 2>&1
smartvpn_logger "add ip to ipset $ipset_ip_name."
cat $_ipfile | while read line
do
ipset add $ipset_ip_name $line
done
}
smartvpn_ipset_delete()
{
ipset flush $ipset_name
ipset flush $ipset_ip_name
ipset destroy $ipset_name # maybe failed, but doesn't matter
ipset destroy $ipset_ip_name # maybe failed, but doesn't matter
return
}
smartvpn_vpn_route_delete()
{
# del subnet default routing
network_get_subnet subnet lan
ip rule del from $(fix_subnet $subnet) table vpn
smartvpn_logger "delete $subnet to vpn."
return 0
}
smartvpn_vpn_route_add()
{
# after smartvpn is off, add wan route if vpn is still up
if [ $vpn_status == "up" ]; then
network_get_subnet subnet lan
smartvpn_logger "add $subnet to vpn."
ip rule del from $(fix_subnet $subnet) table vpn
ip rule add from $(fix_subnet $subnet) table vpn
fi
return 0
}
smartvpn_wandns2vpn_remove()
{
network_get_dnsserver dnsservers wan
for dnsserver in $dnsservers; do
smartvpn_logger "wan dns del $dnsserver to vpn"
ip rule del to $dnsserver table vpn
done
}
smartvpn_firewall_reload_add()
{
uci -q batch <<-EOF >/dev/null
set firewall.smartvpn=include
set firewall.smartvpn.path="/lib/firewall.sysapi.loader smartvpn"
set firewall.smartvpn.reload=1
commit firewall
EOF
return 0
}
smartvpn_firewall_reload_delete()
{
uci -q batch <<-EOF >/dev/null
delete firewall.smartvpn
commit firewall
EOF
return 0
}
smartvpn_device_table="smartvpn_device"
smartvpn_mark_table="smartvpn_mark"
smartvpn_vpn_mark_redirect_open()
{
ip rule add fwmark $ipset_mark table vpn
#allowmacs="$(uci get smartvpn.device.mac 2>/dev/null)"
#notnets="$(uci get smartvpn.dest.notnet 2>/dev/null)"
iptables -t mangle -F $smartvpn_device_table 2>/dev/null
iptables -t mangle -X $smartvpn_device_table 2>/dev/null
iptables -t mangle -N $smartvpn_device_table 2>/dev/null
iptables -t mangle -F $smartvpn_mark_table 2>/dev/null
iptables -t mangle -X $smartvpn_mark_table 2>/dev/null
iptables -t mangle -N $smartvpn_mark_table 2>/dev/null
#which dest not transfer through VPN
#if [ "$smartvpn_cfg_hostnotnet" != "" ]
#then
# for notnet in $smartvpn_cfg_hostnotnet
# do
# smartvpn_logger "locat net add $notnet."
# iptables -t nat -A $smartvpn_mark_table -d $notnet -j ACCEPT
# done
#fi
#allowmacs not NULL
if [ "$smartvpn_cfg_devicemac" != "" ]
then
for mac in $smartvpn_cfg_devicemac
do
smartvpn_logger "device mac add $mac."
iptables -t mangle -A $smartvpn_device_table -m mac --mac-source $mac -j RETURN
done
iptables -t mangle -A $smartvpn_device_table -j ACCEPT
else
smartvpn_logger "all devices traffic to vpn."
iptables -t mangle -A $smartvpn_device_table -j RETURN
fi
smartvpn_logger "$dnsmasq_conf_path/$smartdns_conf_name hostlist_not_null $hostlist_not_null."
#dns mark not NULL
[ -s $dnsmasq_conf_path/$smartdns_conf_name ] && {
hostlist_not_null=1
}
smartvpn_logger "hostlist_not_null $hostlist_not_null."
if [ "$hostlist_not_null" != "1" ]
then
smartvpn_logger "add all host mark $ipset_mark to vpn."
iptables -t mangle -A $smartvpn_mark_table -j MARK --set-mark $ipset_mark
else
smartvpn_wandns2vpn_remove
smartvpn_logger "add ipset $ipset_name + $ipset_ip_name to vpn."
iptables -t mangle -A $smartvpn_mark_table -m set --match-set $ipset_name dst -j MARK --set-mark $ipset_mark
iptables -t mangle -A $smartvpn_mark_table -m set --match-set $ipset_ip_name dst -j MARK --set-mark $ipset_mark
fi
iptables -t mangle -A PREROUTING -j smartvpn_device
iptables -t mangle -A PREROUTING -j smartvpn_mark
return
}
smartvpn_vpn_mark_redirect_close()
{
iptables -t mangle -D PREROUTING -j smartvpn_device
iptables -t mangle -D PREROUTING -j smartvpn_mark
iptables -t mangle -F $smartvpn_device_table
iptables -t mangle -X $smartvpn_device_table
iptables -t mangle -F $smartvpn_mark_table
iptables -t mangle -X $smartvpn_mark_table
#iptables -t mangle -D $smartvpn_mark_table -m set --match-set $ipset_name dst -j MARK --set-mark $ipset_mark
ip rule del fwmark $ipset_mark table vpn > /dev/null 2>&1
return
}
vpn_status_get()
{
network_is_up vpn
if [ $? -eq 0 ]; then
vpn_status="up"
else
vpn_status="down"
fi
return
}
#config remote "vpn"
# option disabled "1"
# option status "off"
# option domain_file /etc/smartvpn/vpn.txt
# option type vpn
smartvpn_config_get()
{
config_load "smartvpn"
config_get smartvpn_cfg_domain_switch vpn switch &>/dev/null;
config_get smartvpn_cfg_domain_disabled vpn disabled &>/dev/null;
config_get smartvpn_cfg_status vpn status &>/dev/null;
config_get smartvpn_cfg_type vpn type &>/dev/null;
config_get smartvpn_cfg_domainfile vpn domain_file &>/dev/null;
config_get smartvpn_cfg_devicemac device mac &>/dev/null
config_get smartvpn_cfg_devicedisabled device disabled &>/dev/null
config_get smartvpn_cfg_hostnotnet dest notnet &>/dev/null
if [ -z $smartvpn_cfg_domain_disabled ];
then
smartvpn_cfg_domain_disabled="0"
fi
if [ -z $smartvpn_cfg_status ];
then
smartvpn_cfg_status="off"
fi
if [ $smartvpn_cfg_type != "vpn" ]
then
return 1
fi
return 0
}
smartvpn_flush()
{
if [ $smartvpn_cfg_domain_disabled -ne 0 ]
then
smartvpn_logger "smartvpn not enabled."
return 1
fi
if [ $smartvpn_cfg_type != "vpn" ]
then
smartvpn_logger "smartvpn not in vpn."
return 1
fi
if [ $smartvpn_cfg_status != "on" ];
then
smartvpn_logger "smartvpn not run."
return 1
fi
smartvpn_vpn_mark_redirect_close
smartvpn_vpn_mark_redirect_open
return 0;
}
smartvpn_set_off()
{
uci set smartvpn.vpn.status=off
uci commit smartvpn
}
smartvpn_set_on()
{
uci set smartvpn.vpn.status=on
uci commit smartvpn
}
smartvpn_open()
{
if [ $smartvpn_cfg_status == "on" ];
then
smartvpn_logger "already enabled."
return 1
fi
if [ $vpn_status != "up" ];
then
smartvpn_logger "vpn_status($vpn_status) is down, return."
return 1
fi
[ $smartvpn_cfg_domain_disabled == "1" ] && smartvpn_cfg_domainfile=""
if [ -s $smartvpn_cfg_domainfile -a $smartvpn_cfg_type == "vpn" ]
then
smartvpn_logger "translet domain to ipset."
gensmartdns.sh "$smartvpn_cfg_domainfile" "$smartdns_conf" "$rule_file_ip" "$ipset_name"
fi
[ $smartvpn_cfg_devicedisabled == "1" ] && smartvpn_cfg_devicemac=""
### enable smartvpn
smartvpn_ipset_create
[ -f $rule_file_ip ] && {
smartvpn_logger "add ips to ipset."
smartvpn_ipset_add_by_file $rule_file_ip
hostlist_not_null=1
rm $rule_file_ip
}
smartvpn_dns_start
smartvpn_vpn_route_delete
smartvpn_vpn_mark_redirect_open
smartvpn_firewall_reload_add
ip route flush table cache
smartvpn_logger "status set on."
smartvpn_set_on
smartvpn_logger "smartvpn open!"
return
}
smartvpn_close()
{
if [ $smartvpn_cfg_status == "off" ];
then
smartvpn_logger "status already off!"
return 0
fi
smartvpn_vpn_mark_redirect_close
smartvpn_vpn_route_add
smartvpn_firewall_reload_delete
smartvpn_dns_stop
smartvpn_ipset_delete
ip route flush table cache
smartvpn_set_off
smartvpn_logger "status set off."
smartvpn_logger "smartvpn close!"
return
}
vpn_status_get
smartvpn_config_get || return 1
OPT=$1
[ "$smartvpn_cfg_domain_switch" != "1" ] && return 1;
smartvpn_lock="/var/run/samartvpn.lock"
trap "lock -u $smartvpn_lock; exit 1" SIGHUP SIGINT SIGTERM
lock $smartvpn_lock
#main
case $OPT in
on)
smartvpn_close
smartvpn_cfg_status=off
smartvpn_open
lock -u $smartvpn_lock
return $?
;;
flush)
smartvpn_close
smartvpn_cfg_status=off
smartvpn_open
lock -u $smartvpn_lock
return $?
;;
off)
smartvpn_close
lock -u $smartvpn_lock
return $?
;;
*)
smartvpn_usage
lock -u $smartvpn_lock
return 1
;;
esac