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_NAME:=shadowsocks-libev
PKG_VERSION:=3.0.8 PKG_VERSION:=3.0.8
PKG_RELEASE:=6 PKG_RELEASE:=7
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION) 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_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 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_bypass will bypass the redir chain
src_ips_forward will always go through 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] 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, --- if the previous check result is checkdst,
--- then packets having destination address in --- 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_file
dst_ips_forward will go through the redir chain 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 ## notes and faq
Useful paths and commands for debugging Useful paths and commands for debugging

View File

@ -107,7 +107,7 @@ ss_xxx() {
[ -x "$bin" ] || return [ -x "$bin" ] || return
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)" eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
"validate_${cfgtype}_section" "$cfg" "validate_${cfgtype}_section" "$cfg" || return 1
[ "$disabled" = 0 ] || return [ "$disabled" = 0 ] || return
if ss_mkjson \ if ss_mkjson \
@ -127,21 +127,17 @@ ss_xxx() {
} }
ss_rules_cb() { ss_rules_cb() {
local cfgserver local cfgserver server
local 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 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 if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then
eval "ss_rules_redir_tcp_$cfg=$local_port" eval "ss_rules_redir_tcp_$cfg=$local_port"
fi fi
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
eval "ss_rules_redir_udp_$cfg=$local_port" eval "ss_rules_redir_udp_$cfg=$local_port"
eval "ss_rules_redir_server_udp_$cfg=$server"
fi fi
fi fi
} }
@ -150,48 +146,37 @@ ss_rules() {
local cfg="ss_rules" local cfg="ss_rules"
local bin="$ss_bindir/ss-rules" local bin="$ss_bindir/ss-rules"
local cfgtype local cfgtype
local args local_port_tcp local_port_udp server_udp local local_port_tcp local_port_udp
local i a_args d_args
[ -x "$bin" ] || return 1 [ -x "$bin" ] || return 1
config_get cfgtype "$cfg" TYPE config_get cfgtype "$cfg" TYPE
[ "$cfgtype" = ss_rules ] || return 1 [ "$cfgtype" = ss_rules ] || return 1
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" 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 [ "$disabled" = 0 ] || return 1
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
eval server_udp="\$ss_rules_redir_server_udp_$redir_udp" [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
[ -z "$local_port_udp" ] || args="$args -U" ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -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
"$bin" \ "$bin" \
-s "$ss_rules_servers" \ -s "$ss_redir_servers" \
-l "$local_port_tcp" \ -l "$local_port_tcp" \
-S "$server_udp" \
-L "$local_port_udp" \ -L "$local_port_udp" \
-B "$dst_ips_bypass_file" \ --src-default "$src_default" \
-W "$dst_ips_forward_file" \ --dst-default "$dst_default" \
-b "$dst_ips_bypass" \ --local-default "$local_default" \
-w "$dst_ips_forward" \ --dst-bypass-file "$dst_ips_bypass_file" \
-e "$ipt_args" \ --dst-forward-file "$dst_ips_forward_file" \
-a "$a_args" \ --dst-bypass "$dst_ips_bypass" \
-d "$d_args" \ --dst-forward "$dst_ips_forward" \
$args \ --src-bypass "$src_ips_bypass" \
--src-forward "$src_ips_forward" \
--src-checkdst "$src_ips_checkdst" \
--ifnames "$ifnames" \
--ipt-extra "$ipt_args" \
|| "$bin" -f || "$bin" -f
} }
@ -299,15 +284,17 @@ validate_ss_rules_section() {
'disabled:bool:0' \ 'disabled:bool:0' \
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \ 'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \ 'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
'src_ips_bypass:list(ipaddr)' \ 'src_ips_bypass:list(or(ip4addr,cidr4))' \
'src_ips_forward:list(ipaddr)' \ 'src_ips_forward:list(or(ip4addr,cidr4))' \
'src_ips_checkdst:list(ipaddr)' \ 'src_ips_checkdst:list(or(ip4addr,cidr4))' \
'dst_ips_bypass_file:file' \ '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_file:file' \
'dst_ips_forward:list(ipaddr)' \ 'dst_ips_forward:list(or(ip4addr,cidr4))' \
'src_default:or("bypass", "forward", "checkdst")' \ 'src_default:or("bypass", "forward", "checkdst"):checkdst' \
'local_default:or("bypass", "forward", "checkdst")' \ 'dst_default:or("bypass", "forward"):bypass' \
'local_default:or("bypass", "forward", "checkdst"):bypass' \
'ifnames:list(maxlength(15))' \
'ipt_args:string' '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. # This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information. # See /LICENSE for more information.
# #
usage() { ss_usage() {
cat <<-EOF cat >&2 <<EOF
Usage: ss-rules [options] 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 The following ipsets will be created by ss-rules. They are also intended to be
-l <local_port> port number of shadowsocks local server populated by other programs like dnsmasq with ipset support
-S <server_ips> ip address of shadowsocks remote UDP server
-L <local_port> port number of shadowsocks local UDP server ss_rules_src_bypass
-B <ip_list_file> a file whose content is bypassed ip list ss_rules_src_forward
-b <wan_ips> wan ip of will be bypassed ss_rules_src_checkdst
-W <ip_list_file> a file whose content is forwarded ip list ss_rules_dst_bypass
-w <wan_ips> wan ip of will be forwarded ss_rules_dst_forward
-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
EOF EOF
exit $1
} }
loger() { o_dst_bypass_="
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug 0.0.0.0/8
logger -st ss-rules[$$] -p$1 $2 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() { ss_rules_parse_args() {
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c while [ "$#" -gt 0 ]; do
if command -v ip >/dev/null 2>&1; then case "$1" in
ip rule del fwmark 1 lookup 100 2>/dev/null -h|--help) ss_usage; exit 0;;
ip route del local default dev lo table 100 2>/dev/null -f|--flush) ss_rules_flush; exit 0;;
fi -l) o_redir_tcp_port="$2"; shift 2;;
for setname in $(ipset -n list | grep "ss_spec"); do -L) o_redir_udp_port="$2"; shift 2;;
ipset destroy $setname 2>/dev/null -s) o_remote_servers="$2"; shift 2;;
done --ifnames) o_ifnames="$2"; shift 2;;
FWI=$(uci get firewall.shadowsocks.path 2>/dev/null) --ipt-extra) o_ipt_extra="$2"; shift 2;;
[ -n "$FWI" ] && echo '# firewall include file' >$FWI --src-default) o_src_default="$2"; shift 2;;
return 0 --dst-default) o_dst_default="$2"; shift 2;;
} --local-default) o_local_default="$2"; shift 2;;
--src-bypass) o_src_bypass="$2"; shift 2;;
ipset_init() { --src-forward) o_src_forward="$2"; shift 2;;
ipset -! restore <<-EOF || return 1 --src-checkdst) o_src_checkdst="$2"; shift 2;;
create ss_spec_src_ac hash:ip hashsize 64 --dst-bypass) o_dst_bypass="$2"; shift 2;;
create ss_spec_src_bp hash:ip hashsize 64 --dst-forward) o_dst_forward="$2"; shift 2;;
create ss_spec_src_fw hash:ip hashsize 64 --dst-bypass-file) o_dst_bypass_file="$2"; shift 2;;
create ss_spec_dst_sp hash:net hashsize 64 --dst-forward-file) o_dst_forward_file="$2"; shift 2;;
create ss_spec_dst_bp hash:net hashsize 64 *) __errmsg "unknown option $1"; return 1;;
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}
;;
esac esac
done 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() { ss_rules_flush() {
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" local setname
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
}
include_ac_rules() { iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters
local protocol=$([ "$1" = "mangle" ] && echo udp || echo tcp) while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done
iptables-restore -n <<-EOF ip route flush table 100
*$1 for setname in $(ipset -n list | grep "ss_rules_"); do
:SS_SPEC_LAN_DG - [0:0] ipset destroy "$setname" 2>/dev/null || true
: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
done done
} }
while getopts ":s:l:S:L:B:b:W:w:I:d:a:e:oOuUfh" arg; do ss_rules_ipset_init() {
case "$arg" in ipset --exist restore <<-EOF
s) create ss_rules_src_bypass hash:net hashsize 64
server=$(for ip in $OPTARG; do echo $ip; done) 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) udp)
local_port=$OPTARG ip rule add fwmark 1 lookup 100
;; ip route add local default dev lo table 100
S) forward_rules="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
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
;; ;;
esac 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 if [ -z "$o_ifnames" ]; then
unset SERVER echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
LOCAL_PORT=$local_port else
elif [ "$TPROXY" = 2 ]; then echo "$o_ifnames" \
: ${SERVER:?"You must assign an ip for the udp relay server."} | tr ' ' '\n' \
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."} | sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
fi fi
}
flush_rules && ipset_init && ipt_nat && ipt_mangle && export_ipt_rules ss_rules_parse_args "$@"
RET=$? ss_rules_flush
[ "$RET" = 0 ] || loger 3 "Start failed!" ss_rules_ipset_init
exit $RET ss_rules_iptchains_init