shadowsocks-libev: rewrite ss-rules

- New UCI options ifnames, dst_default
 - UCI options src_ips_xxx now accept cidr as their values
 - Export ipset names as part of the interface so that it can be
   depended on and used by other programs
 - Bypass only remote servers used ss-redir instances, so that it's
   possible to let other servers to go through existing re-redir
   instances

Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
This commit is contained in:
Yousong Zhou 2017-08-13 16:00:19 +08:00
parent b1cd3a955a
commit df395767d3
4 changed files with 262 additions and 283 deletions

View File

@ -14,7 +14,7 @@ include $(TOPDIR)/rules.mk
#
PKG_NAME:=shadowsocks-libev
PKG_VERSION:=3.0.8
PKG_RELEASE:=6
PKG_RELEASE:=7
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION)

View File

@ -39,8 +39,9 @@ We can have multiple instances of component and `server` sections. The relation
redir_tcp name of ss_redir section with mode tcp_only or tcp_and_udp
redir_udp name of ss_redir section with mode udp_only or tcp_and_udp
ifnames only apply rules on packets from these ifnames
--- incoming packets having source address in
--- for incoming packets having source address in
src_ips_bypass will bypass the redir chain
src_ips_forward will always go through the redir chain
@ -50,10 +51,6 @@ We can have multiple instances of component and `server` sections. The relation
src_default bypass, forward, [checkdst]
--- for local out tcp packets, the default action can be specified with
local_default [bypass], forward, checkdst
--- if the previous check result is checkdst,
--- then packets having destination address in
@ -62,6 +59,18 @@ We can have multiple instances of component and `server` sections. The relation
dst_ips_forward_file
dst_ips_forward will go through the redir chain
--- otherwise, the default action can be specified with
dst_default [bypass], forward
--- for local out tcp packets, the default action can be specified with
local_default [bypass], forward, checkdst
ss-rules uses kernel ipset mechanism for storing addresses/networks. Those ipsets are also part of the API and can be populated by other programs, e.g. dnsmasq with builtin ipset support. For more details please read output of `ss-rules --help`
Note also that `src_ips_xx` and `dst_ips_xx` actually also accepts cidr network representation. Names are retained for backward compatibility coniderations
## notes and faq
Useful paths and commands for debugging

View File

@ -107,7 +107,7 @@ ss_xxx() {
[ -x "$bin" ] || return
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
"validate_${cfgtype}_section" "$cfg"
"validate_${cfgtype}_section" "$cfg" || return 1
[ "$disabled" = 0 ] || return
if ss_mkjson \
@ -127,21 +127,17 @@ ss_xxx() {
}
ss_rules_cb() {
local cfgserver
local server
local cfgserver server
[ "$cfgtype" != ss_server ] || return
config_get cfgserver "$cfg" server
config_get server "$cfgserver" server
ss_rules_servers="$ss_rules_servers $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"
eval "ss_rules_redir_server_udp_$cfg=$server"
fi
fi
}
@ -150,48 +146,37 @@ ss_rules() {
local cfg="ss_rules"
local bin="$ss_bindir/ss-rules"
local cfgtype
local args local_port_tcp local_port_udp server_udp
local i a_args d_args
local local_port_tcp local_port_udp
[ -x "$bin" ] || return 1
config_get cfgtype "$cfg" TYPE
[ "$cfgtype" = ss_rules ] || return 1
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)"
validate_ss_rules_section "$cfg"
validate_ss_rules_section "$cfg" || return 1
[ "$disabled" = 0 ] || return 1
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
eval server_udp="\$ss_rules_redir_server_udp_$redir_udp"
[ -z "$local_port_udp" ] || args="$args -U"
case "$local_default" in
forward) args="$args -O" ;;
checkdst) args="$args -o" ;;
esac
case "$src_default" in
bypass) d_args=RETURN ;;
forward) d_args=SS_SPEC_WAN_FW ;;
checkdst) d_args=SS_SPEC_WAN_AC ;;
esac
ss_rules_servers="$(echo "$ss_rules_servers" | tr ' ' '\n' | sort -u)"
for i in $src_ips_bypass; do a_args="b,$i $a_args"; done
for i in $src_ips_forward; do a_args="g,$i $a_args"; done
for i in $src_ips_checkdst; do a_args="n,$i $a_args"; done
[ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)"
"$bin" \
-s "$ss_rules_servers" \
-s "$ss_redir_servers" \
-l "$local_port_tcp" \
-S "$server_udp" \
-L "$local_port_udp" \
-B "$dst_ips_bypass_file" \
-W "$dst_ips_forward_file" \
-b "$dst_ips_bypass" \
-w "$dst_ips_forward" \
-e "$ipt_args" \
-a "$a_args" \
-d "$d_args" \
$args \
--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" \
|| "$bin" -f
}
@ -299,15 +284,17 @@ validate_ss_rules_section() {
'disabled:bool:0' \
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
'src_ips_bypass:list(ipaddr)' \
'src_ips_forward:list(ipaddr)' \
'src_ips_checkdst:list(ipaddr)' \
'src_ips_bypass:list(or(ip4addr,cidr4))' \
'src_ips_forward:list(or(ip4addr,cidr4))' \
'src_ips_checkdst:list(or(ip4addr,cidr4))' \
'dst_ips_bypass_file:file' \
'dst_ips_bypass:list(ipaddr)' \
'dst_ips_bypass:list(or(ip4addr,cidr4))' \
'dst_ips_forward_file:file' \
'dst_ips_forward:list(ipaddr)' \
'src_default:or("bypass", "forward", "checkdst")' \
'local_default:or("bypass", "forward", "checkdst")' \
'dst_ips_forward:list(or(ip4addr,cidr4))' \
'src_default:or("bypass", "forward", "checkdst"):checkdst' \
'dst_default:or("bypass", "forward"):bypass' \
'local_default:or("bypass", "forward", "checkdst"):bypass' \
'ifnames:list(maxlength(15))' \
'ipt_args:string'
}

View File

@ -1,260 +1,243 @@
#!/bin/sh
#!/bin/sh -e
#
# Copyright (C) 2014-2017 Jian Chang <aa65535@live.com>
# Copyright (C) 2017 Yousong Zhou <yszhou4tech@gmail.com>
#
# The design idea was derived from ss-rules by Jian Chang <aa65535@live.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
usage() {
cat <<-EOF
Usage: ss-rules [options]
ss_usage() {
cat >&2 <<EOF
Usage: ss-rules [options]
Valid options are:
-h, --help Show this help message then exit
-f, --flush Flush rules, ipset then exit
-l <port> Local port number of ss-redir with TCP mode
-L <port> Local port number of ss-redir with UDP mode
-s <ips> List of ip addresses of remote shadowsocks server
--ifnames Only apply rules on packets from these ifnames
--src-bypass <ips|cidr>
--src-forward <ips|cidr>
--src-checkdst <ips|cidr>
--src-default <bypass|forward|checkdst>
Packets will have their src ip checked in order against
bypass, forward, checkdst list and will bypass, forward
through, or continue to have their dst ip checked
respectively on the first match. Otherwise, --src-default
decide the default action
--dst-bypass <ips|cidr>
--dst-forward <ips|cidr>
--dst-bypass-file <file>
--dst-forward-file <file>
--dst-default <bypass|forward>
Same as with their --src-xx equivalent
--local-default <bypass|forward|checkdst>
Default action for local out TCP traffic
-s <server_ips> ip address of shadowsocks remote server
-l <local_port> port number of shadowsocks local server
-S <server_ips> ip address of shadowsocks remote UDP server
-L <local_port> port number of shadowsocks local UDP server
-B <ip_list_file> a file whose content is bypassed ip list
-b <wan_ips> wan ip of will be bypassed
-W <ip_list_file> a file whose content is forwarded ip list
-w <wan_ips> wan ip of will be forwarded
-I <interface> proxy only for the given interface
-d <target> the default target of lan access control
-a <lan_hosts> lan ip of access control, need a prefix to
define proxy type
-e <extra_args> extra arguments for iptables
-o apply the rules to the OUTPUT chain
-O apply the global rules to the OUTPUT chain
-u enable udprelay mode, TPROXY is required
-U enable udprelay mode, using different IP
and ports for TCP and UDP
-f flush the rules
-h show this help message and exit
The following ipsets will be created by ss-rules. They are also intended to be
populated by other programs like dnsmasq with ipset support
ss_rules_src_bypass
ss_rules_src_forward
ss_rules_src_checkdst
ss_rules_dst_bypass
ss_rules_dst_forward
EOF
exit $1
}
loger() {
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
logger -st ss-rules[$$] -p$1 $2
o_dst_bypass_="
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.31.196.0/24
192.52.193.0/24
192.88.99.0/24
192.168.0.0/16
192.175.48.0/24
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255
"
o_src_default=bypass
o_dst_default=bypass
o_local_default=bypass
__errmsg() {
echo "ss-rules: $*" >&2
}
flush_rules() {
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
if command -v ip >/dev/null 2>&1; then
ip rule del fwmark 1 lookup 100 2>/dev/null
ip route del local default dev lo table 100 2>/dev/null
fi
for setname in $(ipset -n list | grep "ss_spec"); do
ipset destroy $setname 2>/dev/null
done
FWI=$(uci get firewall.shadowsocks.path 2>/dev/null)
[ -n "$FWI" ] && echo '# firewall include file' >$FWI
return 0
}
ipset_init() {
ipset -! restore <<-EOF || return 1
create ss_spec_src_ac hash:ip hashsize 64
create ss_spec_src_bp hash:ip hashsize 64
create ss_spec_src_fw hash:ip hashsize 64
create ss_spec_dst_sp hash:net hashsize 64
create ss_spec_dst_bp hash:net hashsize 64
create ss_spec_dst_fw hash:net hashsize 64
$(gen_lan_host_ipset_entry)
$(gen_special_purpose_ip | sed -e "s/^/add ss_spec_dst_sp /")
$(sed -e "s/^/add ss_spec_dst_bp /" ${WAN_BP_LIST:=/dev/null} 2>/dev/null)
$(for ip in $WAN_BP_IP; do echo "add ss_spec_dst_bp $ip"; done)
$(sed -e "s/^/add ss_spec_dst_fw /" ${WAN_FW_LIST:=/dev/null} 2>/dev/null)
$(for ip in $WAN_FW_IP; do echo "add ss_spec_dst_fw $ip"; done)
EOF
return 0
}
ipt_nat() {
include_ac_rules nat
ipt="iptables -t nat"
$ipt -A SS_SPEC_WAN_FW -p tcp \
-j REDIRECT --to-ports $local_port || return 1
if [ -n "$OUTPUT" ]; then
$ipt -N SS_SPEC_WAN_DG
$ipt -A SS_SPEC_WAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
$ipt -A SS_SPEC_WAN_DG -p tcp $EXT_ARGS -j $OUTPUT
$ipt -I OUTPUT 1 -p tcp -j SS_SPEC_WAN_DG
fi
return $?
}
ipt_mangle() {
[ -n "$TPROXY" ] || return 0
if !(lsmod | grep -q TPROXY && command -v ip >/dev/null); then
loger 4 "TPROXY or ip not found."
return 0
fi
ip rule add fwmark 1 lookup 100
ip route add local default dev lo table 100
include_ac_rules mangle
iptables -t mangle -A SS_SPEC_WAN_FW -p udp \
-j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01
return $?
}
export_ipt_rules() {
[ -n "$FWI" ] || return 0
cat <<-CAT >>$FWI
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
iptables-restore -n <<-EOF
$(iptables-save | grep -E "SS_SPEC|^\*|^COMMIT" |\
sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/")
EOF
CAT
return $?
}
gen_lan_host_ipset_entry() {
for host in $LAN_HOSTS; do
case "${host:0:1}" in
n|N)
echo add ss_spec_src_ac ${host:2}
;;
b|B)
echo add ss_spec_src_bp ${host:2}
;;
g|G)
echo add ss_spec_src_fw ${host:2}
;;
ss_rules_parse_args() {
while [ "$#" -gt 0 ]; do
case "$1" in
-h|--help) ss_usage; exit 0;;
-f|--flush) ss_rules_flush; exit 0;;
-l) o_redir_tcp_port="$2"; shift 2;;
-L) o_redir_udp_port="$2"; shift 2;;
-s) o_remote_servers="$2"; shift 2;;
--ifnames) o_ifnames="$2"; shift 2;;
--ipt-extra) o_ipt_extra="$2"; shift 2;;
--src-default) o_src_default="$2"; shift 2;;
--dst-default) o_dst_default="$2"; shift 2;;
--local-default) o_local_default="$2"; shift 2;;
--src-bypass) o_src_bypass="$2"; shift 2;;
--src-forward) o_src_forward="$2"; shift 2;;
--src-checkdst) o_src_checkdst="$2"; shift 2;;
--dst-bypass) o_dst_bypass="$2"; shift 2;;
--dst-forward) o_dst_forward="$2"; shift 2;;
--dst-bypass-file) o_dst_bypass_file="$2"; shift 2;;
--dst-forward-file) o_dst_forward_file="$2"; shift 2;;
*) __errmsg "unknown option $1"; return 1;;
esac
done
if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then
__errmsg "Requires at least -l or -L option"
return 1
fi
}
gen_special_purpose_ip() {
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.31.196.0/24
192.52.193.0/24
192.88.99.0/24
192.168.0.0/16
192.175.48.0/24
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255
$server
$SERVER
EOF
}
ss_rules_flush() {
local setname
include_ac_rules() {
local protocol=$([ "$1" = "mangle" ] && echo udp || echo tcp)
iptables-restore -n <<-EOF
*$1
:SS_SPEC_LAN_DG - [0:0]
:SS_SPEC_LAN_AC - [0:0]
:SS_SPEC_WAN_AC - [0:0]
:SS_SPEC_WAN_FW - [0:0]
-A SS_SPEC_LAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
-A SS_SPEC_LAN_DG -p $protocol $EXT_ARGS -j SS_SPEC_LAN_AC
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_bp src -j RETURN
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_fw src -j SS_SPEC_WAN_FW
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_ac src -j SS_SPEC_WAN_AC
-A SS_SPEC_LAN_AC -j ${LAN_TARGET:=SS_SPEC_WAN_AC}
-A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_fw dst -j SS_SPEC_WAN_FW
-A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_bp dst -j RETURN
-A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
$(gen_prerouting_rules $protocol)
COMMIT
EOF
}
gen_prerouting_rules() {
[ -z "$IFNAMES" ] && echo -I PREROUTING 1 -p $1 -j SS_SPEC_LAN_DG
for ifname in $IFNAMES; do
echo -I PREROUTING 1 -i $ifname -p $1 -j SS_SPEC_LAN_DG
iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters
while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done
ip route flush table 100
for setname in $(ipset -n list | grep "ss_rules_"); do
ipset destroy "$setname" 2>/dev/null || true
done
}
while getopts ":s:l:S:L:B:b:W:w:I:d:a:e:oOuUfh" arg; do
case "$arg" in
s)
server=$(for ip in $OPTARG; do echo $ip; done)
ss_rules_ipset_init() {
ipset --exist restore <<-EOF
create ss_rules_src_bypass hash:net hashsize 64
create ss_rules_src_forward hash:net hashsize 64
create ss_rules_src_checkdst hash:net hashsize 64
create ss_rules_dst_bypass hash:net hashsize 64
create ss_rules_dst_bypass_ hash:net hashsize 64
create ss_rules_dst_forward hash:net hashsize 64
$(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers")
$(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass")
$(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward")
$(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst")
$(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)")
$(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null)")
EOF
}
ss_rules_ipset_mkadd() {
local setname="$1"; shift
local i
for i in $*; do
echo "add $setname $i"
done
}
ss_rules_iptchains_init() {
ss_rules_iptchains_init_tcp
ss_rules_iptchains_init_udp
}
ss_rules_iptchains_init_tcp() {
local ipt="iptables -t nat"
local local_target
local forward_rules
local r
[ -n "$o_redir_tcp_port" ] || return 0
ss_rules_iptchains_init_ nat tcp
case "$o_local_default" in
checkdst) local_target=ss_rules_dst ;;
forward) local_target=ss_rules_forward ;;
bypass|*) return 0;;
esac
iptables-restore --noflush <<-EOF
*nat
:ss_rules_local_out -
-I OUTPUT 1 -p tcp -j ss_rules_local_out
-A ss_rules_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
-A ss_rules_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default"
COMMIT
EOF
}
ss_rules_iptchains_init_udp() {
[ -n "$o_redir_udp_port" ] || return 0
ss_rules_iptchains_init_ mangle udp
}
ss_rules_iptchains_init_() {
local table="$1"
local proto="$2"
local forward_rules
local src_default_target dst_default_target
case "$proto" in
tcp)
forward_rules="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
;;
l)
local_port=$OPTARG
;;
S)
SERVER=$(for ip in $OPTARG; do echo $ip; done)
;;
L)
LOCAL_PORT=$OPTARG
;;
B)
WAN_BP_LIST=$OPTARG
;;
b)
WAN_BP_IP=$OPTARG
;;
W)
WAN_FW_LIST=$OPTARG
;;
w)
WAN_FW_IP=$OPTARG
;;
I)
IFNAMES=$OPTARG
;;
d)
LAN_TARGET=$OPTARG
;;
a)
LAN_HOSTS=$OPTARG
;;
e)
EXT_ARGS=$OPTARG
;;
o)
OUTPUT=SS_SPEC_WAN_AC
;;
O)
OUTPUT=SS_SPEC_WAN_FW
;;
u)
TPROXY=1
;;
U)
TPROXY=2
;;
f)
flush_rules
exit 0
;;
h)
usage 0
udp)
ip rule add fwmark 1 lookup 100
ip route add local default dev lo table 100
forward_rules="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
;;
esac
done
case "$o_src_default" in
forward) src_default_target=ss_rules_forward ;;
checkdst) src_default_target=ss_rules_dst ;;
bypass|*) src_default_target=RETURN ;;
esac
case "$o_dst_default" in
forward) dst_default_target=ss_rules_forward ;;
bypass|*) dst_default_target=RETURN ;;
esac
iptables-restore --noflush <<-EOF
*$table
:ss_rules_pre_src -
:ss_rules_src -
:ss_rules_dst -
:ss_rules_forward -
$(ss_rules_iptchains_mkprerules "$proto")
-A ss_rules_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
-A ss_rules_pre_src -p $proto $o_ipt_extra -j ss_rules_src
-A ss_rules_src -m set --match-set ss_rules_src_bypass src -j RETURN
-A ss_rules_src -m set --match-set ss_rules_src_forward src -j ss_rules_forward
-A ss_rules_src -m set --match-set ss_rules_src_checkdst src -j ss_rules_dst
-A ss_rules_src -j $src_default_target -m comment --comment "src_default: $o_src_default"
-A ss_rules_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN
-A ss_rules_dst -m set --match-set ss_rules_dst_forward dst -j ss_rules_forward
-A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default"
$forward_rules
COMMIT
EOF
}
[ -z "$server" -o -z "$local_port" ] && usage 2
ss_rules_iptchains_mkprerules() {
local proto="$1"
if [ "$TPROXY" = 1 ]; then
unset SERVER
LOCAL_PORT=$local_port
elif [ "$TPROXY" = 2 ]; then
: ${SERVER:?"You must assign an ip for the udp relay server."}
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
fi
if [ -z "$o_ifnames" ]; then
echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
else
echo "$o_ifnames" \
| tr ' ' '\n' \
| sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
fi
}
flush_rules && ipset_init && ipt_nat && ipt_mangle && export_ipt_rules
RET=$?
[ "$RET" = 0 ] || loger 3 "Start failed!"
exit $RET
ss_rules_parse_args "$@"
ss_rules_flush
ss_rules_ipset_init
ss_rules_iptchains_init