lede/package/lean/luci-app-shadowsocksr-pro/root/etc/init.d/ssrpro
2017-09-09 03:31:59 +08:00

379 lines
12 KiB
Bash
Executable File

#!/bin/sh /etc/rc.common
#
#
START=99
SS_REDIR_PORT=7070
SS_REDIR_PIDFILE=/var/run/ssr-redir-go.pid
PDNSD_LOCAL_PORT=7453
SSRCONF=/etc/shadowsocksr.json
CRON_FILE=/etc/crontabs/root
CONFIG=shadowsocksr
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# $covered_subnets, $local_addresses are not required
covered_subnets=`uci get shadowsocksr.@shadowsocksr[0].covered_subnets 2>/dev/null`
local_addresses=`uci get shadowsocksr.@shadowsocksr[0].local_addresses 2>/dev/null`
# Get LAN settings as default parameters
[ -f /lib/functions/network.sh ] && . /lib/functions/network.sh
[ -z "$covered_subnets" ] && network_get_subnet covered_subnets lan
[ -z "$local_addresses" ] && network_get_ipaddr local_addresses lan
vt_np_ipset="china" # Must be global variable
__gfwlist_by_mode()
{
case "$1" in
V) echo unblock-youku;;
*) echo china-banned;;
esac
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
start()
{
local vt_enabled=`uci get shadowsocksr.@shadowsocksr[0].enabled 2>/dev/null`
local vt_server_addr=`uci get shadowsocksr.@shadowsocksr[0].server`
local vt_server_port=`uci get shadowsocksr.@shadowsocksr[0].server_port`
local vt_password=`uci get shadowsocksr.@shadowsocksr[0].password 2>/dev/null`
local vt_method=`uci get shadowsocksr.@shadowsocksr[0].method`
local vt_protocol=`uci get shadowsocksr.@shadowsocksr[0].protocol`
local vt_obfs=`uci get shadowsocksr.@shadowsocksr[0].obfs`
local vt_timeout=`uci get shadowsocksr.@shadowsocksr[0].timeout 2>/dev/null`
local vt_safe_dns=`uci get shadowsocksr.@shadowsocksr[0].safe_dns 2>/dev/null`
local vt_safe_dns_port=`uci get shadowsocksr.@shadowsocksr[0].safe_dns_port 2>/dev/null`
local vt_safe_dns_tcp=`uci get shadowsocksr.@shadowsocksr[0].safe_dns_tcp 2>/dev/null`
local vt_proxy_mode=`uci get shadowsocksr.@shadowsocksr[0].proxy_mode`
local obfs_param=`uci get shadowsocksr.@shadowsocksr[0].obfs_param 2>/dev/null`
local cron_mode=`uci get shadowsocksr.@shadowsocksr[0].cron_mode 2>/dev/null`
local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode`
[ -f /etc/init.d/pdnsd ] && /etc/init.d/pdnsd disable 2>/dev/null
# -----------------------------------------------------------------
if [ "$vt_enabled" = 0 ]; then
echo "WARNING: Shadowsocksr is disabled."
return 1
fi
if [ -z "$vt_server_addr" -o -z "$vt_server_port" ]; then
echo "WARNING: Shadowsocksr not fully configured, not starting."
return 1
fi
[ -z "$vt_proxy_mode" ] && vt_proxy_mode=M
[ -z "$vt_method" ] && vt_method=table
[ -z "$vt_timeout" ] && vt_timeout=60
case "$vt_proxy_mode" in
M|S|G)
[ -z "$vt_safe_dns" ] && vt_safe_dns="8.8.8.8"
[ -z "$vt_safe_dns_tcp" ] && vt_safe_dns_tcp=1
;;
esac
[ -z "$vt_safe_dns_port" ] && vt_safe_dns_port=53
# -----------------------------------------------------------------
###### shadowsocksr ######
cat > $SSRCONF <<EOF
{
"server": "$vt_server_addr",
"server_port": $vt_server_port,
"password": "$vt_password",
"method": "$vt_method",
"local_address": "0.0.0.0",
"local_port": $SS_REDIR_PORT,
"timeout": $vt_timeout,
"protocol": "$vt_protocol",
"protocol_param": "",
"obfs": "$vt_obfs",
"obfs_param": "$obfs_param",
"fast_open": false
}
EOF
/usr/bin/ssr-redir -u -c $SSRCONF -f $SS_REDIR_PIDFILE || return 1
# IPv4 firewall rules
add_rule
# -----------------------------------------------------------------
mkdir -p /var/etc/dnsmasq-go.d
###### Anti-pollution configuration ######
if [ -n "$vt_safe_dns" ]; then
if [ "$vt_safe_dns_tcp" = 1 ]; then
start_pdnsd "$vt_safe_dns"
awk -vs="127.0.0.1#$PDNSD_LOCAL_PORT" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf
else
awk -vs="$vt_safe_dns#$vt_safe_dns_port" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf
fi
else
echo "WARNING: Not using secure DNS, DNS resolution might be polluted if you are in China."
fi
###### dnsmasq-to-ipset configuration ######
case "$vt_proxy_mode" in
M|V)
awk '!/^$/&&!/^#/{printf("ipset=/%s/'"$vt_gfwlist"'\n",$0)}' \
/etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/02-ipset.conf
;;
esac
# -----------------------------------------------------------------
###### Restart main 'dnsmasq' service if needed ######
if ls /var/etc/dnsmasq-go.d/* >/dev/null 2>&1; then
mkdir -p /tmp/dnsmasq.d
cat > /tmp/dnsmasq.d/dnsmasq-go.conf <<EOF
conf-dir=/var/etc/dnsmasq-go.d
EOF
/etc/init.d/dnsmasq restart
fi
add_cron
}
stop()
{
# -----------------------------------------------------------------
rm -rf /var/etc/dnsmasq-go.d
if [ -f /tmp/dnsmasq.d/dnsmasq-go.conf ]; then
rm -f /tmp/dnsmasq.d/dnsmasq-go.conf
/etc/init.d/dnsmasq restart
fi
stop_pdnsd
# --STOP IPv4 firewall---------------------------------------------------------------
del_rule
# -----------------------------------------------------------------
if [ -f $SS_REDIR_PIDFILE ]; then
kill -9 `cat $SS_REDIR_PIDFILE`
rm -f $SS_REDIR_PIDFILE
fi
killall -9 ssr-redir 2>/dev/null
del_cron
}
restart()
{
KEEP_GFWLIST=Y
stop
start
}
reload()
{
local vt_enabled=`uci get shadowsocksr.@shadowsocksr[0].enabled 2>/dev/null`
local vt_server_addr=`uci get shadowsocksr.@shadowsocksr[0].server`
local vt_server_port=`uci get shadowsocksr.@shadowsocksr[0].server_port`
local vt_safe_dns=`uci get shadowsocksr.@shadowsocksr[0].safe_dns 2>/dev/null`
local vt_safe_dns_port=`uci get shadowsocksr.@shadowsocksr[0].safe_dns_port 2>/dev/null`
local vt_safe_dns_tcp=`uci get shadowsocksr.@shadowsocksr[0].safe_dns_tcp 2>/dev/null`
local vt_proxy_mode=`uci get shadowsocksr.@shadowsocksr[0].proxy_mode`
local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode`
KEEP_GFWLIST=Y
del_rule
add_rule
if [ "$vt_safe_dns_tcp" = 1 ]; then
stop_pdnsd
start_pdnsd
fi
}
# $1: upstream DNS server
start_pdnsd()
{
local safe_dns="$1"
local tcp_dns_list="208.67.222.222, 208.67.220.220"
[ -n "$safe_dns" ] && tcp_dns_list="$safe_dns,$tcp_dns_list"
#killall -9 pdnsd 2>/dev/null && sleep 1
kill -9 $(cat /var/run/pdnsd.pid) >/dev/null 2>&1 && mkdir -p /var/etc /var/pdnsd
cat > /var/etc/pdnsd.conf <<EOF
global {
perm_cache=off;
cache_dir="/var/pdnsd";
pid_file = /var/run/pdnsd.pid;
run_as="nobody";
server_ip = 127.0.0.1;
server_port = $PDNSD_LOCAL_PORT;
status_ctl = on;
query_method = tcp_only;
min_ttl=1h;
max_ttl=1w;
timeout=10;
neg_domain_pol=on;
proc_limit=2;
procq_limit=8;
}
server {
label= "fwxxx";
ip = $tcp_dns_list;
port = 53;
timeout=6;
uptest=none;
interval=10m;
purge_cache=off;
}
EOF
/usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d
# Access TCP DNS server through Shadowsocksr tunnel
if iptables -t nat -N pdnsd_output; then
iptables -t nat -A pdnsd_output -m set --match-set $vt_np_ipset dst -j RETURN
iptables -t nat -A pdnsd_output -p tcp -j REDIRECT --to $SS_REDIR_PORT
fi
iptables -t nat -I OUTPUT -p tcp --dport 53 -j pdnsd_output
}
stop_pdnsd()
{
if iptables -t nat -F pdnsd_output 2>/dev/null; then
while iptables -t nat -D OUTPUT -p tcp --dport 53 -j pdnsd_output 2>/dev/null; do :; done
iptables -t nat -X pdnsd_output
fi
killall -9 pdnsd 2>/dev/null
rm -rf /var/pdnsd
rm -f /var/etc/pdnsd.conf
}
add_cron()
{
sed -i '/up-gfwlist.sh/d' $CRON_FILE
sed -i '/shadowsocksr_watchdog.log/d' $CRON_FILE
if [ $cron_mode -eq 1 ]; then
echo '0 5 * * * /etc/shadowsocksr/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1' >> $CRON_FILE
fi
echo '0 */1 * * * /etc/shadowsocksr/ssr-watchdog >> /tmp/shadowsocksr_watchdog.log 2>&1' >> $CRON_FILE
echo '0 1 * * 0 echo "" > /tmp/shadowsocksr_watchdog.log' >> $CRON_FILE
crontab $CRON_FILE
}
del_cron()
{
sed -i '/up-gfwlist.sh/d' $CRON_FILE
sed -i '/shadowsocksr_watchdog.log/d' $CRON_FILE
/etc/init.d/cron restart
}
uci_get_by_name() {
local ret=$(uci get $CONFIG.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
uci_get_by_type() {
local index=0
if [ -n $4 ]; then
index=$4
fi
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
add_rule()
{
iptables -t nat -N shadowsocksr_pre
iptables -t nat -F shadowsocksr_pre
iptables -t nat -A shadowsocksr_pre -m set --match-set local dst -j RETURN || {
iptables -t nat -A shadowsocksr_pre -d 10.0.0.0/8 -j RETURN
iptables -t nat -A shadowsocksr_pre -d 127.0.0.0/8 -j RETURN
iptables -t nat -A shadowsocksr_pre -d 172.16.0.0/12 -j RETURN
iptables -t nat -A shadowsocksr_pre -d 192.168.0.0/16 -j RETURN
iptables -t nat -A shadowsocksr_pre -d 127.0.0.0/8 -j RETURN
iptables -t nat -A shadowsocksr_pre -d 224.0.0.0/3 -j RETURN
}
iptables -t nat -A shadowsocksr_pre -d $vt_server_addr -j RETURN
iptables -N gameboost -t mangle
ipset -! create gameuser hash:ip maxelem 65536 2>/dev/null
/usr/bin/ip rule add fwmark 0x01/0x01 table 100
/usr/bin/ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -A gameboost -p udp -m set --match-set local dst -j RETURN
iptables -t mangle -A gameboost -p udp -m set --match-set china dst -j RETURN
iptables -t mangle -A gameboost -p udp --dport 53 -j RETURN
iptables -t mangle -A gameboost -p udp -j TPROXY --on-port 7070 --tproxy-mark 0x01/0x01
iptables -t mangle -A PREROUTING -m set --match-set gameuser src -j gameboost
for i in $(seq 0 100)
do
local ip=$(uci_get_by_type acl_rule ipaddr '' $i)
local mode=$(uci_get_by_type acl_rule filter_mode '' $i)
case "$mode" in
disable)
iptables -t nat -A shadowsocksr_pre -s $ip -j RETURN
;;
global)
iptables -t nat -A shadowsocksr_pre -s $ip -p tcp -j REDIRECT --to $SS_REDIR_PORT
iptables -t nat -A shadowsocksr_pre -s $ip -j RETURN
;;
game)
iptables -t nat -A shadowsocksr_pre -p tcp -s $ip -m set ! --match-set china dst -j REDIRECT --to $SS_REDIR_PORT
ipset -! add gameuser $ip
;;
esac
done
case "$vt_proxy_mode" in
G) : ;;
S)
iptables -t nat -A shadowsocksr_pre -m set --match-set $vt_np_ipset dst -j RETURN
iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT
;;
M)
ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null
awk '!/^$/&&!/^#/{printf("add vt_gfwlist %s'" "'\n",$0)}' /etc/shadowsocksr/addinip.txt > /tmp/addinip.ipset
sed -i "s/vt_gfwlist/$vt_gfwlist/g" /tmp/addinip.ipset
ipset -! restore < /tmp/addinip.ipset
iptables -t nat -A shadowsocksr_pre -m set ! --match-set $vt_gfwlist dst -j RETURN
iptables -t nat -A shadowsocksr_pre -m set --match-set $vt_np_ipset dst -j RETURN
iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set $vt_gfwlist dst -j REDIRECT --to $SS_REDIR_PORT
;;
V)
vt_np_ipset=""
ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null
iptables -t nat -A shadowsocksr_pre -m set ! --match-set $vt_gfwlist dst -j RETURN
;;
esac
local subnet
for subnet in $covered_subnets; do
iptables -t nat -A shadowsocksr_pre -s $subnet -p tcp -j REDIRECT --to $SS_REDIR_PORT
done
iptables -t nat -I PREROUTING -p tcp -j shadowsocksr_pre
}
del_rule()
{
if iptables -t nat -F shadowsocksr_pre 2>/dev/null; then
while iptables -t nat -D PREROUTING -p tcp -j shadowsocksr_pre 2>/dev/null; do :; done
iptables -t nat -X shadowsocksr_pre 2>/dev/null
fi
iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set china-banned dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null
iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null
/usr/bin/ip rule del fwmark 0x01/0x01 table 100
/usr/bin/ip route del local 0.0.0.0/0 dev lo table 100
if iptables -t mangle -F gameboost 2>/dev/null; then
while iptables -t mangle -D PREROUTING -m set --match-set gameuser src -j gameboost 2>/dev/null; do :; done
iptables -t mangle -X gameboost 2>/dev/null
fi
ipset destroy gameuser 2>/dev/null
# -----------------------------------------------------------------
[ "$KEEP_GFWLIST" = Y ] || ipset destroy "$vt_gfwlist" 2>/dev/null
}