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