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
() {
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