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 --local-default <bypass|forward|checkdst>
37 Default action for local out TCP traffic
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
73 o_local_default
=bypass
76 echo "ss-rules: $*" >&2
79 ss_rules_parse_args
() {
80 while [ "$#" -gt 0 ]; do
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;;
103 if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then
104 __errmsg
"Requires at least -l or -L option"
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
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)")
137 ss_rules_ipset_mkadd
() {
138 local setname
="$1"; shift
142 echo "add $setname $i"
146 ss_rules_iptchains_init
() {
147 ss_rules_iptchains_init_tcp
148 ss_rules_iptchains_init_udp
151 ss_rules_iptchains_init_tcp
() {
152 local ipt
="iptables -t nat"
157 [ -n "$o_redir_tcp_port" ] ||
return 0
159 ss_rules_iptchains_init_ nat tcp
161 case "$o_local_default" in
162 checkdst
) local_target
=ss_rules_dst
;;
163 forward
) local_target
=ss_rules_forward
;;
167 iptables-restore
--noflush <<-EOF
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"
177 ss_rules_iptchains_init_udp
() {
178 [ -n "$o_redir_udp_port" ] ||
return 0
179 ss_rules_iptchains_init_ mangle udp
182 ss_rules_iptchains_init_
() {
186 local src_default_target dst_default_target
190 forward_rules
="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
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"
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
;;
203 case "$o_dst_default" in
204 forward
) dst_default_target
=ss_rules_forward
;;
205 bypass|
*) dst_default_target
=RETURN
;;
207 iptables-restore
--noflush <<-EOF
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"
228 ss_rules_iptchains_mkprerules
() {
231 if [ -z "$o_ifnames" ]; then
232 echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
236 |
sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
240 ss_rules_parse_args
"$@"
243 ss_rules_iptchains_init