Merge pull request #4674 from diizzyy/patch-80
[feed/packages.git] / net / shadowsocks-libev / files / ss-rules
1 #!/bin/sh
2 #
3 # Copyright (C) 2014-2017 Jian Chang <aa65535@live.com>
4 #
5 # This is free software, licensed under the GNU General Public License v3.
6 # See /LICENSE for more information.
7 #
8
9 usage() {
10 cat <<-EOF
11 Usage: ss-rules [options]
12
13 Valid options are:
14
15 -s <server_ips> ip address of shadowsocks remote server
16 -l <local_port> port number of shadowsocks local server
17 -S <server_ips> ip address of shadowsocks remote UDP server
18 -L <local_port> port number of shadowsocks local UDP server
19 -B <ip_list_file> a file whose content is bypassed ip list
20 -b <wan_ips> wan ip of will be bypassed
21 -W <ip_list_file> a file whose content is forwarded ip list
22 -w <wan_ips> wan ip of will be forwarded
23 -I <interface> proxy only for the given interface
24 -d <target> the default target of lan access control
25 -a <lan_hosts> lan ip of access control, need a prefix to
26 define proxy type
27 -e <extra_args> extra arguments for iptables
28 -o apply the rules to the OUTPUT chain
29 -O apply the global rules to the OUTPUT chain
30 -u enable udprelay mode, TPROXY is required
31 -U enable udprelay mode, using different IP
32 and ports for TCP and UDP
33 -f flush the rules
34 -h show this help message and exit
35 EOF
36 exit $1
37 }
38
39 loger() {
40 # 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
41 logger -st ss-rules[$$] -p$1 $2
42 }
43
44 flush_rules() {
45 iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
46 if command -v ip >/dev/null 2>&1; then
47 ip rule del fwmark 1 lookup 100 2>/dev/null
48 ip route del local default dev lo table 100 2>/dev/null
49 fi
50 for setname in $(ipset -n list | grep "ss_spec"); do
51 ipset destroy $setname 2>/dev/null
52 done
53 FWI=$(uci get firewall.shadowsocks.path 2>/dev/null)
54 [ -n "$FWI" ] && echo '# firewall include file' >$FWI
55 return 0
56 }
57
58 ipset_init() {
59 ipset -! restore <<-EOF || return 1
60 create ss_spec_src_ac hash:ip hashsize 64
61 create ss_spec_src_bp hash:ip hashsize 64
62 create ss_spec_src_fw hash:ip hashsize 64
63 create ss_spec_dst_sp hash:net hashsize 64
64 create ss_spec_dst_bp hash:net hashsize 64
65 create ss_spec_dst_fw hash:net hashsize 64
66 $(gen_lan_host_ipset_entry)
67 $(gen_special_purpose_ip | sed -e "s/^/add ss_spec_dst_sp /")
68 $(sed -e "s/^/add ss_spec_dst_bp /" ${WAN_BP_LIST:=/dev/null} 2>/dev/null)
69 $(for ip in $WAN_BP_IP; do echo "add ss_spec_dst_bp $ip"; done)
70 $(sed -e "s/^/add ss_spec_dst_fw /" ${WAN_FW_LIST:=/dev/null} 2>/dev/null)
71 $(for ip in $WAN_FW_IP; do echo "add ss_spec_dst_fw $ip"; done)
72 EOF
73 return 0
74 }
75
76 ipt_nat() {
77 include_ac_rules nat
78 ipt="iptables -t nat"
79 $ipt -A SS_SPEC_WAN_FW -p tcp \
80 -j REDIRECT --to-ports $local_port || return 1
81 if [ -n "$OUTPUT" ]; then
82 $ipt -N SS_SPEC_WAN_DG
83 $ipt -A SS_SPEC_WAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
84 $ipt -A SS_SPEC_WAN_DG -p tcp $EXT_ARGS -j $OUTPUT
85 $ipt -I OUTPUT 1 -p tcp -j SS_SPEC_WAN_DG
86 fi
87 return $?
88 }
89
90 ipt_mangle() {
91 [ -n "$TPROXY" ] || return 0
92 if !(lsmod | grep -q TPROXY && command -v ip >/dev/null); then
93 loger 4 "TPROXY or ip not found."
94 return 0
95 fi
96 ip rule add fwmark 1 lookup 100
97 ip route add local default dev lo table 100
98 include_ac_rules mangle
99 iptables -t mangle -A SS_SPEC_WAN_FW -p udp \
100 -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01
101 return $?
102 }
103
104 export_ipt_rules() {
105 [ -n "$FWI" ] || return 0
106 cat <<-CAT >>$FWI
107 iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
108 iptables-restore -n <<-EOF
109 $(iptables-save | grep -E "SS_SPEC|^\*|^COMMIT" |\
110 sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/")
111 EOF
112 CAT
113 return $?
114 }
115
116 gen_lan_host_ipset_entry() {
117 for host in $LAN_HOSTS; do
118 case "${host:0:1}" in
119 n|N)
120 echo add ss_spec_src_ac ${host:2}
121 ;;
122 b|B)
123 echo add ss_spec_src_bp ${host:2}
124 ;;
125 g|G)
126 echo add ss_spec_src_fw ${host:2}
127 ;;
128 esac
129 done
130 }
131
132 gen_special_purpose_ip() {
133 cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
134 0.0.0.0/8
135 10.0.0.0/8
136 100.64.0.0/10
137 127.0.0.0/8
138 169.254.0.0/16
139 172.16.0.0/12
140 192.0.0.0/24
141 192.0.2.0/24
142 192.31.196.0/24
143 192.52.193.0/24
144 192.88.99.0/24
145 192.168.0.0/16
146 192.175.48.0/24
147 198.18.0.0/15
148 198.51.100.0/24
149 203.0.113.0/24
150 224.0.0.0/4
151 240.0.0.0/4
152 255.255.255.255
153 $server
154 $SERVER
155 EOF
156 }
157
158 include_ac_rules() {
159 local protocol=$([ "$1" = "mangle" ] && echo udp || echo tcp)
160 iptables-restore -n <<-EOF
161 *$1
162 :SS_SPEC_LAN_DG - [0:0]
163 :SS_SPEC_LAN_AC - [0:0]
164 :SS_SPEC_WAN_AC - [0:0]
165 :SS_SPEC_WAN_FW - [0:0]
166 -A SS_SPEC_LAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
167 -A SS_SPEC_LAN_DG -p $protocol $EXT_ARGS -j SS_SPEC_LAN_AC
168 -A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_bp src -j RETURN
169 -A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_fw src -j SS_SPEC_WAN_FW
170 -A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_ac src -j SS_SPEC_WAN_AC
171 -A SS_SPEC_LAN_AC -j ${LAN_TARGET:=SS_SPEC_WAN_AC}
172 -A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_fw dst -j SS_SPEC_WAN_FW
173 -A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_bp dst -j RETURN
174 -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
175 $(gen_prerouting_rules $protocol)
176 COMMIT
177 EOF
178 }
179
180 gen_prerouting_rules() {
181 [ -z "$IFNAMES" ] && echo -I PREROUTING 1 -p $1 -j SS_SPEC_LAN_DG
182 for ifname in $IFNAMES; do
183 echo -I PREROUTING 1 -i $ifname -p $1 -j SS_SPEC_LAN_DG
184 done
185 }
186
187 while getopts ":s:l:S:L:B:b:W:w:I:d:a:e:oOuUfh" arg; do
188 case "$arg" in
189 s)
190 server=$(for ip in $OPTARG; do echo $ip; done)
191 ;;
192 l)
193 local_port=$OPTARG
194 ;;
195 S)
196 SERVER=$(for ip in $OPTARG; do echo $ip; done)
197 ;;
198 L)
199 LOCAL_PORT=$OPTARG
200 ;;
201 B)
202 WAN_BP_LIST=$OPTARG
203 ;;
204 b)
205 WAN_BP_IP=$OPTARG
206 ;;
207 W)
208 WAN_FW_LIST=$OPTARG
209 ;;
210 w)
211 WAN_FW_IP=$OPTARG
212 ;;
213 I)
214 IFNAMES=$OPTARG
215 ;;
216 d)
217 LAN_TARGET=$OPTARG
218 ;;
219 a)
220 LAN_HOSTS=$OPTARG
221 ;;
222 e)
223 EXT_ARGS=$OPTARG
224 ;;
225 o)
226 OUTPUT=SS_SPEC_WAN_AC
227 ;;
228 O)
229 OUTPUT=SS_SPEC_WAN_FW
230 ;;
231 u)
232 TPROXY=1
233 ;;
234 U)
235 TPROXY=2
236 ;;
237 f)
238 flush_rules
239 exit 0
240 ;;
241 h)
242 usage 0
243 ;;
244 esac
245 done
246
247 [ -z "$server" -o -z "$local_port" ] && usage 2
248
249 if [ "$TPROXY" = 1 ]; then
250 unset SERVER
251 LOCAL_PORT=$local_port
252 elif [ "$TPROXY" = 2 ]; then
253 : ${SERVER:?"You must assign an ip for the udp relay server."}
254 : ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
255 fi
256
257 flush_rules && ipset_init && ipt_nat && ipt_mangle && export_ipt_rules
258 RET=$?
259 [ "$RET" = 0 ] || loger 3 "Start failed!"
260 exit $RET