shadowsocks-libev: ss-rules: rename usage func
[feed/packages.git] / net / shadowsocks-libev / files / ss-rules
1 #!/bin/sh -e
2 #
3 # Copyright (C) 2017 Yousong Zhou <yszhou4tech@gmail.com>
4 #
5 # The design idea was derived from ss-rules by Jian Chang <aa65535@live.com>
6 #
7 # This is free software, licensed under the GNU General Public License v3.
8 # See /LICENSE for more information.
9 #
10
11 ss_rules_usage() {
12 cat >&2 <<EOF
13 Usage: ss-rules [options]
14
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 --local-default <bypass|forward|checkdst>
37 Default action for local out TCP traffic
38
39 The following ipsets will be created by ss-rules. They are also intended to be
40 populated by other programs like dnsmasq with ipset support
41
42 ss_rules_src_bypass
43 ss_rules_src_forward
44 ss_rules_src_checkdst
45 ss_rules_dst_bypass
46 ss_rules_dst_forward
47 EOF
48 }
49
50 o_dst_bypass_="
51 0.0.0.0/8
52 10.0.0.0/8
53 100.64.0.0/10
54 127.0.0.0/8
55 169.254.0.0/16
56 172.16.0.0/12
57 192.0.0.0/24
58 192.0.2.0/24
59 192.31.196.0/24
60 192.52.193.0/24
61 192.88.99.0/24
62 192.168.0.0/16
63 192.175.48.0/24
64 198.18.0.0/15
65 198.51.100.0/24
66 203.0.113.0/24
67 224.0.0.0/4
68 240.0.0.0/4
69 255.255.255.255
70 "
71 o_src_default=bypass
72 o_dst_default=bypass
73 o_local_default=bypass
74
75 __errmsg() {
76 echo "ss-rules: $*" >&2
77 }
78
79 ss_rules_parse_args() {
80 while [ "$#" -gt 0 ]; do
81 case "$1" in
82 -h|--help) ss_rules_usage; exit 0;;
83 -f|--flush) ss_rules_flush; exit 0;;
84 -l) o_redir_tcp_port="$2"; shift 2;;
85 -L) o_redir_udp_port="$2"; shift 2;;
86 -s) o_remote_servers="$2"; shift 2;;
87 --ifnames) o_ifnames="$2"; shift 2;;
88 --ipt-extra) o_ipt_extra="$2"; shift 2;;
89 --src-default) o_src_default="$2"; shift 2;;
90 --dst-default) o_dst_default="$2"; shift 2;;
91 --local-default) o_local_default="$2"; shift 2;;
92 --src-bypass) o_src_bypass="$2"; shift 2;;
93 --src-forward) o_src_forward="$2"; shift 2;;
94 --src-checkdst) o_src_checkdst="$2"; shift 2;;
95 --dst-bypass) o_dst_bypass="$2"; shift 2;;
96 --dst-forward) o_dst_forward="$2"; shift 2;;
97 --dst-bypass-file) o_dst_bypass_file="$2"; shift 2;;
98 --dst-forward-file) o_dst_forward_file="$2"; shift 2;;
99 *) __errmsg "unknown option $1"; return 1;;
100 esac
101 done
102
103 if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then
104 __errmsg "Requires at least -l or -L option"
105 return 1
106 fi
107 }
108
109 ss_rules_flush() {
110 local setname
111
112 iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters
113 while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done
114 ip route flush table 100
115 for setname in $(ipset -n list | grep "ss_rules_"); do
116 ipset destroy "$setname" 2>/dev/null || true
117 done
118 }
119
120 ss_rules_ipset_init() {
121 ipset --exist restore <<-EOF
122 create ss_rules_src_bypass hash:net hashsize 64
123 create ss_rules_src_forward hash:net hashsize 64
124 create ss_rules_src_checkdst hash:net hashsize 64
125 create ss_rules_dst_bypass hash:net hashsize 64
126 create ss_rules_dst_bypass_ hash:net hashsize 64
127 create ss_rules_dst_forward hash:net hashsize 64
128 $(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers")
129 $(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass")
130 $(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward")
131 $(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst")
132 $(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)")
133 $(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null)")
134 EOF
135 }
136
137 ss_rules_ipset_mkadd() {
138 local setname="$1"; shift
139 local i
140
141 for i in $*; do
142 echo "add $setname $i"
143 done
144 }
145
146 ss_rules_iptchains_init() {
147 ss_rules_iptchains_init_tcp
148 ss_rules_iptchains_init_udp
149 }
150
151 ss_rules_iptchains_init_tcp() {
152 local ipt="iptables -t nat"
153 local local_target
154 local forward_rules
155 local r
156
157 [ -n "$o_redir_tcp_port" ] || return 0
158
159 ss_rules_iptchains_init_ nat tcp
160
161 case "$o_local_default" in
162 checkdst) local_target=ss_rules_dst ;;
163 forward) local_target=ss_rules_forward ;;
164 bypass|*) return 0;;
165 esac
166
167 iptables-restore --noflush <<-EOF
168 *nat
169 :ss_rules_local_out -
170 -I OUTPUT 1 -p tcp -j ss_rules_local_out
171 -A ss_rules_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
172 -A ss_rules_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default"
173 COMMIT
174 EOF
175 }
176
177 ss_rules_iptchains_init_udp() {
178 [ -n "$o_redir_udp_port" ] || return 0
179 ss_rules_iptchains_init_ mangle udp
180 }
181
182 ss_rules_iptchains_init_() {
183 local table="$1"
184 local proto="$2"
185 local forward_rules
186 local src_default_target dst_default_target
187
188 case "$proto" in
189 tcp)
190 forward_rules="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
191 ;;
192 udp)
193 ip rule add fwmark 1 lookup 100
194 ip route add local default dev lo table 100
195 forward_rules="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
196 ;;
197 esac
198 case "$o_src_default" in
199 forward) src_default_target=ss_rules_forward ;;
200 checkdst) src_default_target=ss_rules_dst ;;
201 bypass|*) src_default_target=RETURN ;;
202 esac
203 case "$o_dst_default" in
204 forward) dst_default_target=ss_rules_forward ;;
205 bypass|*) dst_default_target=RETURN ;;
206 esac
207 iptables-restore --noflush <<-EOF
208 *$table
209 :ss_rules_pre_src -
210 :ss_rules_src -
211 :ss_rules_dst -
212 :ss_rules_forward -
213 $(ss_rules_iptchains_mkprerules "$proto")
214 -A ss_rules_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN
215 -A ss_rules_pre_src -p $proto $o_ipt_extra -j ss_rules_src
216 -A ss_rules_src -m set --match-set ss_rules_src_bypass src -j RETURN
217 -A ss_rules_src -m set --match-set ss_rules_src_forward src -j ss_rules_forward
218 -A ss_rules_src -m set --match-set ss_rules_src_checkdst src -j ss_rules_dst
219 -A ss_rules_src -j $src_default_target -m comment --comment "src_default: $o_src_default"
220 -A ss_rules_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN
221 -A ss_rules_dst -m set --match-set ss_rules_dst_forward dst -j ss_rules_forward
222 -A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default"
223 $forward_rules
224 COMMIT
225 EOF
226 }
227
228 ss_rules_iptchains_mkprerules() {
229 local proto="$1"
230
231 if [ -z "$o_ifnames" ]; then
232 echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
233 else
234 echo "$o_ifnames" \
235 | tr ' ' '\n' \
236 | sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
237 fi
238 }
239
240 ss_rules_parse_args "$@"
241 ss_rules_flush
242 ss_rules_ipset_init
243 ss_rules_iptchains_init