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"
120 iptables-save
--counters |
grep -v ss_rules_ | iptables-restore
--counters
121 while ip rule del fwmark
1 lookup
100 2>/dev
/null
; do true
; done
122 ip route flush table
100
123 for setname
in $
(ipset
-n list |
grep "ss_rules_"); do
124 ipset destroy
"$setname" 2>/dev
/null || true
128 ss_rules_ipset_init
() {
129 ipset
--exist restore
<<-EOF
130 create ss_rules_src_bypass hash:net hashsize 64
131 create ss_rules_src_forward hash:net hashsize 64
132 create ss_rules_src_checkdst hash:net hashsize 64
133 create ss_rules_dst_bypass hash:net hashsize 64
134 create ss_rules_dst_bypass_ hash:net hashsize 64
135 create ss_rules_dst_forward hash:net hashsize 64
136 create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600
137 $(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers")
138 $(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass")
139 $(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward")
140 $(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst")
141 $(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)")
142 $(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null)")
146 ss_rules_ipset_mkadd
() {
147 local setname
="$1"; shift
151 echo "add $setname $i"
155 ss_rules_iptchains_init
() {
156 ss_rules_iptchains_init_tcp
157 ss_rules_iptchains_init_udp
160 ss_rules_iptchains_init_tcp
() {
161 local ipt
="iptables -t nat"
164 [ -n "$o_redir_tcp_port" ] ||
return 0
166 ss_rules_iptchains_init_ nat tcp
168 case "$o_local_default" in
169 checkdst
) local_target
=ss_rules_dst
;;
170 forward
) local_target
=ss_rules_forward
;;
174 iptables-restore
--noflush <<-EOF
176 :ss_rules_local_out -
177 -I OUTPUT 1 -p tcp -j ss_rules_local_out
178 -A ss_rules_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
179 -A ss_rules_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default"
184 ss_rules_iptchains_init_udp
() {
185 [ -n "$o_redir_udp_port" ] ||
return 0
186 ss_rules_iptchains_init_ mangle udp
189 ss_rules_iptchains_init_
() {
193 local src_default_target dst_default_target
194 local recentrst_mangle_rules recentrst_addset_rules
198 forward_rules
="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
199 if [ -n "$o_dst_forward_recentrst" ]; then
200 recentrst_mangle_rules
="
202 -I PREROUTING 1 -p tcp -m tcp --tcp-flags RST RST -m recent --name ss_rules_recentrst --set --rsource
205 recentrst_addset_rules
="
206 -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
207 -A ss_rules_dst -m set --match-set ss_rules_dst_forward_recentrst_ dst -j ss_rules_forward
212 ip rule add fwmark
1 lookup
100
213 ip route add
local default dev lo table
100
214 forward_rules
="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
217 case "$o_src_default" in
218 forward
) src_default_target
=ss_rules_forward
;;
219 checkdst
) src_default_target
=ss_rules_dst
;;
220 bypass|
*) src_default_target
=RETURN
;;
222 case "$o_dst_default" in
223 forward
) dst_default_target
=ss_rules_forward
;;
224 bypass|
*) dst_default_target
=RETURN
;;
226 sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore --noflush
232 $(ss_rules_iptchains_mkprerules "$proto")
233 -A ss_rules_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
234 -A ss_rules_pre_src -p $proto $o_ipt_extra -j ss_rules_src
235 -A ss_rules_src -m set --match-set ss_rules_src_bypass src -j RETURN
236 -A ss_rules_src -m set --match-set ss_rules_src_forward src -j ss_rules_forward
237 -A ss_rules_src -m set --match-set ss_rules_src_checkdst src -j ss_rules_dst
238 -A ss_rules_src -j $src_default_target -m comment --comment "src_default: $o_src_default"
239 -A ss_rules_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN
240 -A ss_rules_dst -m set --match-set ss_rules_dst_forward dst -j ss_rules_forward
241 $recentrst_addset_rules
242 -A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default"
245 $recentrst_mangle_rules
249 ss_rules_iptchains_mkprerules
() {
252 if [ -z "$o_ifnames" ]; then
253 echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
257 |
sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
261 ss_rules_parse_args
"$@"
264 ss_rules_iptchains_init