Merge pull request #1534 from aTanW/master
[feed/packages.git] / net / shadowsocks-libev / files / ss-rules
1 #!/bin/sh
2
3 usage() {
4 cat <<-EOF
5 Usage: ss-rules [options]
6
7 Valid options are:
8
9 -s <server_host> hostname or ip of shadowsocks remote server
10 -l <local_port> port number of shadowsocks local server
11 -i <ip_list_file> a file content is bypassed ip list
12 -a <lan_ips> lan ip of access control, need a prefix to
13 define access control mode
14 -b <wan_ips> wan ip of will be bypassed
15 -w <wan_ips> wan ip of will be forwarded
16 -e <extra_options> extra options for iptables
17 -o apply the rules to the OUTPUT chain
18 -u enable udprelay mode, TPROXY is required
19 -f flush the rules
20 EOF
21 }
22
23 loger() {
24 # 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
25 logger -st ss-rules[$$] -p$1 $2
26 }
27
28 ipt_n="iptables -t nat"
29 ipt_m="iptables -t mangle"
30
31 flush_r() {
32 local IPT
33
34 IPT=$(iptables-save -t nat)
35 eval $(echo "$IPT" | grep "_SS_SPEC_RULE_" | \
36 sed -e 's/^-A/$ipt_n -D/' -e 's/$/;/')
37
38 for chain in $(echo "$IPT" | awk '/^:SS_SPEC/{print $1}'); do
39 $ipt_n -F ${chain:1} 2>/dev/null && $ipt_n -X ${chain:1}
40 done
41
42 IPT=$(iptables-save -t mangle)
43 eval $(echo "$IPT" | grep "_SS_SPEC_RULE_" | \
44 sed -e 's/^-A/$ipt_m -D/' -e 's/$/;/')
45
46 for chain in $(echo "$IPT" | awk '/^:SS_SPEC/{print $1}'); do
47 $ipt_m -F ${chain:1} 2>/dev/null && $ipt_m -X ${chain:1}
48 done
49
50 ip rule del fwmark 0x01/0x01 table 100 2>/dev/null
51 ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
52 ipset -X ss_spec_lan_ac 2>/dev/null
53 ipset -X ss_spec_wan_ac 2>/dev/null
54 return 0
55 }
56
57 ipset_r() {
58 ipset -! -R <<-EOF || return 1
59 create ss_spec_wan_ac hash:net
60 $(echo -e "$IPLIST" | sed -e "s/^/add ss_spec_wan_ac /")
61 $(for ip in $WAN_FW_IP; do echo "add ss_spec_wan_ac $ip nomatch"; done)
62 EOF
63 $ipt_n -N SS_SPEC_WAN_AC && \
64 $ipt_n -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN && \
65 $ipt_n -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
66 return $?
67 }
68
69 fw_rule() {
70 $ipt_n -N SS_SPEC_WAN_FW && \
71 $ipt_n -A SS_SPEC_WAN_FW -p tcp \
72 -j REDIRECT --to-ports $LOCAL_PORT 2>/dev/null || {
73 loger 3 "Can't redirect, please check the iptables."
74 exit 1
75 }
76 return $?
77 }
78
79 ac_rule() {
80 local TAG ROUTECHAIN
81
82 if [ -n "$LAN_AC_IP" ]; then
83 if [ "${LAN_AC_IP:0:1}" = "w" ]; then
84 TAG="nomatch"
85 else
86 if [ "${LAN_AC_IP:0:1}" != "b" ]; then
87 loger 3 "Bad argument \`-a $LAN_AC_IP\`."
88 return 2
89 fi
90 fi
91 fi
92
93 ROUTECHAIN=PREROUTING
94 if iptables-save -t nat | grep -q "^:zone_lan_prerouting"; then
95 ROUTECHAIN=zone_lan_prerouting
96 fi
97
98 ipset -! -R <<-EOF || return 1
99 create ss_spec_lan_ac hash:net
100 $(for ip in ${LAN_AC_IP:1}; do echo "add ss_spec_lan_ac $ip $TAG"; done)
101 EOF
102 $ipt_n -A $ROUTECHAIN -p tcp $EXT_ARGS \
103 -m set ! --match-set ss_spec_lan_ac src \
104 -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_WAN_AC
105
106 if [ "$OUTPUT" = 1 ]; then
107 $ipt_n -A OUTPUT -p tcp $EXT_ARGS \
108 -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_WAN_AC
109 fi
110 return $?
111 }
112
113 tp_rule() {
114 [ "$TPROXY" = 1 ] || return 0
115 ip rule add fwmark 0x01/0x01 table 100
116 ip route add local 0.0.0.0/0 dev lo table 100
117 $ipt_m -N SS_SPEC_TPROXY
118 $ipt_m -A SS_SPEC_TPROXY -p udp -m set ! --match-set ss_spec_wan_ac dst \
119 -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01
120 $ipt_m -A PREROUTING -p udp $EXT_ARGS \
121 -m set ! --match-set ss_spec_lan_ac src \
122 -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_TPROXY
123 return $?
124 }
125
126 while getopts ":s:l:c:i:e:a:b:w:ouf" arg; do
127 case $arg in
128 s)
129 SERVER=$OPTARG
130 ;;
131 l)
132 LOCAL_PORT=$OPTARG
133 ;;
134 i)
135 IGNORE=$OPTARG
136 ;;
137 e)
138 EXT_ARGS=$OPTARG
139 ;;
140 a)
141 LAN_AC_IP=$OPTARG
142 ;;
143 b)
144 WAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done)
145 ;;
146 w)
147 WAN_FW_IP=$OPTARG
148 ;;
149 o)
150 OUTPUT=1
151 ;;
152 u)
153 TPROXY=1
154 ;;
155 f)
156 flush_r
157 exit 0
158 ;;
159 esac
160 done
161
162 if [ -z "$SERVER" -o -z "$LOCAL_PORT" ]; then
163 usage
164 exit 2
165 fi
166
167 SERVER=$(resolveip -t60 $SERVER)
168
169 if [ -z "$SERVER" ]; then
170 loger 3 "Can't resolve the server hostname."
171 exit 1
172 fi
173
174 if [ -f "$IGNORE" ]; then
175 IGNORE_IP=$(cat $IGNORE 2>/dev/null)
176 fi
177
178 IPLIST=$(cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
179 $SERVER
180 0.0.0.0/8
181 10.0.0.0/8
182 100.64.0.0/10
183 127.0.0.0/8
184 169.254.0.0/16
185 172.16.0.0/12
186 192.0.0.0/24
187 192.0.2.0/24
188 192.88.99.0/24
189 192.168.0.0/16
190 198.18.0.0/15
191 198.51.100.0/24
192 203.0.113.0/24
193 224.0.0.0/4
194 240.0.0.0/4
195 255.255.255.255
196 $WAN_BP_IP
197 $IGNORE_IP
198 EOF
199 )
200
201 flush_r && fw_rule && ipset_r && ac_rule && tp_rule
202
203 exit $?