3 # Copyright (C) 2017 Yousong Zhou <yszhou4tech@gmail.com>
5 # The design idea was derived from ss-rules by Jian Chang <aa65535@live.com>
7 # This is free software, licensed under the GNU General Public License v3.
8 # See /LICENSE for more information.
13 Usage: ss-rules [options]
15 -h, --help Show this help message then exit
16 -f, --flush Flush rules, ipset then exit
17 -l <port> Local port number of ss-redir with TCP mode
18 -L <port> Local port number of ss-redir with UDP mode
19 -s <ips> List of ip addresses of remote shadowsocks server
20 --ifnames Only apply rules on packets from these ifnames
21 --src-bypass <ips|cidr>
22 --src-forward <ips|cidr>
23 --src-checkdst <ips|cidr>
24 --src-default <bypass|forward|checkdst>
25 Packets will have their src ip checked in order against
26 bypass, forward, checkdst list and will bypass, forward
27 through, or continue to have their dst ip checked
28 respectively on the first match. Otherwise, --src-default
29 decide the default action
30 --dst-bypass <ips|cidr>
31 --dst-forward <ips|cidr>
32 --dst-bypass-file <file>
33 --dst-forward-file <file>
34 --dst-default <bypass|forward>
35 Same as with their --src-xx equivalent
36 --dst-forward-recentrst
37 Forward those packets whose destinations have recently
38 sent to us multiple tcp-rst packets
39 --local-default <bypass|forward|checkdst>
40 Default action for local out TCP traffic
42 The following ipsets will be created by ss-rules. They are also intended to be
43 populated by other programs like dnsmasq with ipset support
76 o_local_default
=bypass
79 echo "ss-rules: $*" >&2
82 ss_rules_parse_args
() {
83 while [ "$#" -gt 0 ]; do
85 -h|
--help) ss_rules_usage
; exit 0;;
86 -f|
--flush) ss_rules_flush
; exit 0;;
87 -l) o_redir_tcp_port
="$2"; shift 2;;
88 -L) o_redir_udp_port
="$2"; shift 2;;
89 -s) o_remote_servers
="$2"; shift 2;;
90 --ifnames) o_ifnames
="$2"; shift 2;;
91 --ipt-extra) o_ipt_extra
="$2"; shift 2;;
92 --src-default) o_src_default
="$2"; shift 2;;
93 --dst-default) o_dst_default
="$2"; shift 2;;
94 --local-default) o_local_default
="$2"; shift 2;;
95 --src-bypass) o_src_bypass
="$2"; shift 2;;
96 --src-forward) o_src_forward
="$2"; shift 2;;
97 --src-checkdst) o_src_checkdst
="$2"; shift 2;;
98 --dst-bypass) o_dst_bypass
="$2"; shift 2;;
99 --dst-forward) o_dst_forward
="$2"; shift 2;;
100 --dst-forward-recentrst) o_dst_forward_recentrst
=1; shift 1;;
101 --dst-bypass-file) o_dst_bypass_file
="$2"; shift 2;;
102 --dst-forward-file) o_dst_forward_file
="$2"; shift 2;;
103 *) __errmsg
"unknown option $1"; return 1;;
107 if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then
108 __errmsg
"Requires at least -l or -L option"
111 if [ -n "$o_dst_forward_recentrst" ] && ! iptables
-m recent
-h >/dev
/null
; then
112 __errmsg
"Please install iptables-mod-conntrack-extra with opkg"
115 o_remote_servers
="$(for s in $o_remote_servers; do resolveip -4 "$s"; done)"
121 iptables-save
--counters |
grep -v ss_rules_ | iptables-restore
--counters
122 while ip rule del fwmark
1 lookup
100 2>/dev
/null
; do true
; done
123 ip route flush table
100
124 for setname
in $
(ipset
-n list |
grep "ss_rules_"); do
125 ipset destroy
"$setname" 2>/dev
/null || true
129 ss_rules_ipset_init
() {
130 ipset
--exist restore
<<-EOF
131 create ss_rules_src_bypass hash:net hashsize 64
132 create ss_rules_src_forward hash:net hashsize 64
133 create ss_rules_src_checkdst hash:net hashsize 64
134 create ss_rules_dst_bypass hash:net hashsize 64
135 create ss_rules_dst_bypass_ hash:net hashsize 64
136 create ss_rules_dst_forward hash:net hashsize 64
137 create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600
138 $(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers")
139 $(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass")
140 $(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward")
141 $(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst")
142 $(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)")
143 $(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null)")
147 ss_rules_ipset_mkadd
() {
148 local setname
="$1"; shift
152 echo "add $setname $i"
156 ss_rules_iptchains_init
() {
157 ss_rules_iptchains_init_tcp
158 ss_rules_iptchains_init_udp
161 ss_rules_iptchains_init_tcp
() {
162 local ipt
="iptables -t nat"
165 [ -n "$o_redir_tcp_port" ] ||
return 0
167 ss_rules_iptchains_init_ nat tcp
169 case "$o_local_default" in
170 checkdst
) local_target
=ss_rules_dst
;;
171 forward
) local_target
=ss_rules_forward
;;
175 iptables-restore
--noflush <<-EOF
177 :ss_rules_local_out -
178 -I OUTPUT 1 -p tcp -j ss_rules_local_out
179 -A ss_rules_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
180 -A ss_rules_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default"
185 ss_rules_iptchains_init_udp
() {
186 [ -n "$o_redir_udp_port" ] ||
return 0
187 ss_rules_iptchains_init_ mangle udp
190 ss_rules_iptchains_init_
() {
194 local src_default_target dst_default_target
195 local recentrst_mangle_rules recentrst_addset_rules
199 forward_rules
="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
200 if [ -n "$o_dst_forward_recentrst" ]; then
201 recentrst_mangle_rules
="
203 -I PREROUTING 1 -p tcp -m tcp --tcp-flags RST RST -m recent --name ss_rules_recentrst --set --rsource
206 recentrst_addset_rules
="
207 -A ss_rules_dst -m recent --name ss_rules_recentrst --rcheck --rdest --seconds 3 --hitcount 3 -j SET --add-set ss_rules_dst_forward_recentrst_ dst --exist
208 -A ss_rules_dst -m set --match-set ss_rules_dst_forward_recentrst_ dst -j ss_rules_forward
213 ip rule add fwmark
1 lookup
100
214 ip route add
local default dev lo table
100
215 forward_rules
="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
218 case "$o_src_default" in
219 forward
) src_default_target
=ss_rules_forward
;;
220 checkdst
) src_default_target
=ss_rules_dst
;;
221 bypass|
*) src_default_target
=RETURN
;;
223 case "$o_dst_default" in
224 forward
) dst_default_target
=ss_rules_forward
;;
225 bypass|
*) dst_default_target
=RETURN
;;
227 sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore --noflush
233 $(ss_rules_iptchains_mkprerules "$proto")
234 -A ss_rules_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
235 -A ss_rules_pre_src -p $proto $o_ipt_extra -j ss_rules_src
236 -A ss_rules_src -m set --match-set ss_rules_src_bypass src -j RETURN
237 -A ss_rules_src -m set --match-set ss_rules_src_forward src -j ss_rules_forward
238 -A ss_rules_src -m set --match-set ss_rules_src_checkdst src -j ss_rules_dst
239 -A ss_rules_src -j $src_default_target -m comment --comment "src_default: $o_src_default"
240 -A ss_rules_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN
241 -A ss_rules_dst -m set --match-set ss_rules_dst_forward dst -j ss_rules_forward
242 $recentrst_addset_rules
243 -A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default"
246 $recentrst_mangle_rules
250 ss_rules_iptchains_mkprerules
() {
253 if [ -z "$o_ifnames" ]; then
254 echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
258 |
sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
262 ss_rules_parse_args
"$@"
265 ss_rules_iptchains_init