Plugin options are properties of shadowsocks deployment as a whole,
including both server and each client components. Multiple client
instances accessing the same server will need to share the same plugin
settings
With this change, plugin options will need to specified to "server" and
"ss-server" section, not to each component section.
Fixes: c19e949
("shadowsocks-libev: add plugin options support")
Reference: https://github.com/openwrt/packages/issues/8903#issuecomment-489674137
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
290 lines
7.6 KiB
Bash
290 lines
7.6 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
#
|
|
# Copyright (C) 2017-2019 Yousong Zhou <yszhou4tech@gmail.com>
|
|
#
|
|
# This is free software, licensed under the GNU General Public License v3.
|
|
# See /LICENSE for more information.
|
|
#
|
|
|
|
USE_PROCD=1
|
|
START=99
|
|
|
|
ss_confdir=/var/etc/shadowsocks-libev
|
|
ss_bindir=/usr/bin
|
|
|
|
ss_mkjson_server_conf() {
|
|
local cfgserver
|
|
|
|
config_get cfgserver "$cfg" server
|
|
[ -n "$cfgserver" ] || return 1
|
|
eval "$(validate_server_section "$cfg" ss_validate_mklocal)"
|
|
validate_server_section "$cfgserver" || return 1
|
|
[ "$disabled" = 0 ] || return 1
|
|
ss_mkjson_server_conf_ "$cfgserver"
|
|
}
|
|
|
|
ss_mkjson_server_conf_() {
|
|
[ -n "$server_port" ] || return 1
|
|
[ -z "$server" ] || json_add_string server "$server"
|
|
json_add_int server_port "$server_port"
|
|
[ -z "$method" ] || json_add_string method "$method"
|
|
[ -z "$key" ] || json_add_string key "$key"
|
|
[ -z "$password" ] || json_add_string password "$password"
|
|
[ -z "$plugin" ] || json_add_string plugin "$plugin"
|
|
[ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts"
|
|
}
|
|
|
|
ss_mkjson_ss_local_conf() {
|
|
ss_mkjson_server_conf
|
|
}
|
|
|
|
ss_mkjson_ss_redir_conf() {
|
|
ss_mkjson_server_conf
|
|
}
|
|
|
|
ss_mkjson_ss_server_conf() {
|
|
ss_mkjson_server_conf_
|
|
}
|
|
|
|
ss_mkjson_ss_tunnel_conf() {
|
|
ss_mkjson_server_conf || return 1
|
|
[ -n "$tunnel_address" ] || return 1
|
|
json_add_string tunnel_address "$tunnel_address"
|
|
}
|
|
|
|
ss_xxx() {
|
|
local cfg="$1"
|
|
local cfgtype="$2"
|
|
local bin="$ss_bindir/${cfgtype/_/-}"
|
|
local confjson="$ss_confdir/$cfgtype.$cfg.json"
|
|
|
|
[ -x "$bin" ] || return
|
|
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
|
|
"validate_${cfgtype}_section" "$cfg" || return
|
|
[ "$disabled" = 0 ] || return
|
|
|
|
json_init
|
|
ss_mkjson_${cfgtype}_conf || return
|
|
json_add_boolean use_syslog 1
|
|
json_add_boolean ipv6_first "$ipv6_first"
|
|
json_add_boolean fast_open "$fast_open"
|
|
json_add_boolean reuse_port "$reuse_port"
|
|
json_add_boolean no_delay "$no_delay"
|
|
[ -z "$local_address" ] || json_add_string local_address "$local_address"
|
|
[ -z "$local_port" ] || json_add_int local_port "$local_port"
|
|
[ -z "$mode" ] || json_add_string mode "$mode"
|
|
[ -z "$mtu" ] || json_add_int mtu "$mtu"
|
|
[ -z "$timeout" ] || json_add_int timeout "$timeout"
|
|
[ -z "$user" ] || json_add_string user "$user"
|
|
json_dump -i >"$confjson"
|
|
|
|
procd_open_instance "$cfgtype.$cfg"
|
|
procd_set_param command "$bin" -c "$confjson"
|
|
[ "$verbose" = 0 ] || procd_append_param command -v
|
|
[ -z "$bind_address" ] || procd_append_param command -b "$bind_address"
|
|
procd_set_param file "$confjson"
|
|
procd_set_param respawn
|
|
procd_close_instance
|
|
ss_rules_cb
|
|
}
|
|
|
|
ss_rules_cb() {
|
|
local cfgserver server
|
|
|
|
if [ "$cfgtype" = ss_redir ]; then
|
|
config_get cfgserver "$cfg" server
|
|
config_get server "$cfgserver" server
|
|
ss_redir_servers="$ss_redir_servers $server"
|
|
if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then
|
|
eval "ss_rules_redir_tcp_$cfg=$local_port"
|
|
fi
|
|
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
|
|
eval "ss_rules_redir_udp_$cfg=$local_port"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
ss_rules() {
|
|
local cfg="ss_rules"
|
|
local bin="$ss_bindir/ss-rules"
|
|
local cfgtype
|
|
local local_port_tcp local_port_udp
|
|
local args
|
|
|
|
[ -x "$bin" ] || return 1
|
|
"$bin" -f
|
|
"$bin" -6 -f
|
|
|
|
config_get cfgtype "$cfg" TYPE
|
|
[ "$cfgtype" = ss_rules ] || return 1
|
|
|
|
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)"
|
|
validate_ss_rules_section "$cfg" || return 1
|
|
[ "$disabled" = 0 ] || return 0
|
|
|
|
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
|
|
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
|
|
[ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
|
|
ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)"
|
|
[ "$dst_forward_recentrst" = 0 ] || args="$args --dst-forward-recentrst"
|
|
|
|
ss_rules_call
|
|
ss_rules_call -6
|
|
}
|
|
|
|
ss_rules_call() {
|
|
"$bin" "$@" \
|
|
-s "$ss_redir_servers" \
|
|
-l "$local_port_tcp" \
|
|
-L "$local_port_udp" \
|
|
--src-default "$src_default" \
|
|
--dst-default "$dst_default" \
|
|
--local-default "$local_default" \
|
|
--dst-bypass-file "$dst_ips_bypass_file" \
|
|
--dst-forward-file "$dst_ips_forward_file" \
|
|
--dst-bypass "$dst_ips_bypass" \
|
|
--dst-forward "$dst_ips_forward" \
|
|
--src-bypass "$src_ips_bypass" \
|
|
--src-forward "$src_ips_forward" \
|
|
--src-checkdst "$src_ips_checkdst" \
|
|
--ifnames "$ifnames" \
|
|
--ipt-extra "$ipt_args" \
|
|
$args \
|
|
|| "$bin" "$@" -f
|
|
}
|
|
|
|
start_service() {
|
|
local cfgtype
|
|
|
|
mkdir -p "$ss_confdir"
|
|
config_load shadowsocks-libev
|
|
for cfgtype in ss_local ss_redir ss_server ss_tunnel; do
|
|
config_foreach ss_xxx "$cfgtype" "$cfgtype"
|
|
done
|
|
ss_rules
|
|
}
|
|
|
|
stop_service() {
|
|
local bin="$ss_bindir/ss-rules"
|
|
|
|
[ -x "$bin" ] && {
|
|
"$bin" -f
|
|
"$bin" -6 -f
|
|
}
|
|
rm -rf "$ss_confdir"
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_interface_trigger wan
|
|
procd_add_reload_trigger shadowsocks-libev
|
|
procd_open_validate
|
|
validate_server_section
|
|
validate_ss_local_section
|
|
validate_ss_redir_section
|
|
validate_ss_rules_section
|
|
validate_ss_server_section
|
|
validate_ss_tunnel_section
|
|
procd_close_validate
|
|
}
|
|
|
|
ss_validate_mklocal() {
|
|
local tuple opts
|
|
|
|
shift 2
|
|
for tuple in "$@"; do
|
|
opts="${tuple%%:*} $opts"
|
|
done
|
|
[ -z "$opts" ] || echo "local $opts"
|
|
}
|
|
|
|
ss_validate() {
|
|
uci_validate_section shadowsocks-libev "$@"
|
|
}
|
|
|
|
validate_common_server_options_() {
|
|
local cfgtype="$1"; shift
|
|
local cfg="$1"; shift
|
|
local func="$1"; shift
|
|
local stream_methods='"table", "rc4", "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", "chacha20-ietf"'
|
|
local aead_methods='"aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305"'
|
|
|
|
"${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \
|
|
'disabled:bool:0' \
|
|
'server:host' \
|
|
'server_port:port' \
|
|
'password:string' \
|
|
'key:string' \
|
|
"method:or($stream_methods, $aead_methods)" \
|
|
'plugin:string' \
|
|
'plugin_opts:string'
|
|
}
|
|
|
|
validate_common_client_options_() {
|
|
validate_common_options_ "$@" \
|
|
'server:uci("shadowsocks-libev", "@server")' \
|
|
'local_address:host:0.0.0.0' \
|
|
'local_port:port'
|
|
}
|
|
|
|
validate_common_options_() {
|
|
local cfgtype="$1"; shift
|
|
local cfg="$1"; shift
|
|
local func="$1"; shift
|
|
|
|
"${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \
|
|
'disabled:bool:0' \
|
|
'fast_open:bool:0' \
|
|
'ipv6_first:bool:0' \
|
|
'no_delay:bool:0' \
|
|
'reuse_port:bool:0' \
|
|
'verbose:bool:0' \
|
|
'mode:or("tcp_only", "udp_only", "tcp_and_udp"):tcp_only' \
|
|
'mtu:uinteger' \
|
|
'timeout:uinteger' \
|
|
'user:string'
|
|
}
|
|
|
|
validate_server_section() {
|
|
validate_common_server_options_ server "$1" "$2"
|
|
}
|
|
|
|
validate_ss_local_section() {
|
|
validate_common_client_options_ ss_local "$1" "$2"
|
|
}
|
|
|
|
validate_ss_redir_section() {
|
|
validate_common_client_options_ ss_redir "$1" "$2"
|
|
}
|
|
|
|
validate_ss_rules_section() {
|
|
"${2:-ss_validate}" ss_rules "$1" \
|
|
'disabled:bool:0' \
|
|
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
|
|
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
|
|
'src_ips_bypass:or(ipaddr,cidr)' \
|
|
'src_ips_forward:or(ipaddr,cidr)' \
|
|
'src_ips_checkdst:or(ipaddr,cidr)' \
|
|
'dst_ips_bypass_file:file' \
|
|
'dst_ips_bypass:or(ipaddr,cidr)' \
|
|
'dst_ips_forward_file:file' \
|
|
'dst_ips_forward:or(ipaddr,cidr)' \
|
|
'src_default:or("bypass", "forward", "checkdst"):checkdst' \
|
|
'dst_default:or("bypass", "forward"):bypass' \
|
|
'local_default:or("bypass", "forward", "checkdst"):bypass' \
|
|
'dst_forward_recentrst:bool:0' \
|
|
'ifnames:maxlength(15)' \
|
|
'ipt_args:string'
|
|
}
|
|
|
|
validate_ss_server_section() {
|
|
validate_common_server_options_ ss_server "$1" \
|
|
validate_common_options_ \
|
|
"$2" \
|
|
'bind_address:ipaddr'
|
|
}
|
|
|
|
validate_ss_tunnel_section() {
|
|
validate_common_client_options_ ss_tunnel "$1" \
|
|
"$2" \
|
|
'tunnel_address:regex(".+\:[0-9]+")'
|
|
}
|