X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=net%2Fshadowsocks-libev%2Ffiles%2Fss-rules;h=b0a30606e1300d57f357d61e44d6e2c9da6c44c2;hb=0931d35319940474ae4796c069b8bc44c57fc6d2;hp=8ce1000cbcadad262d454a24ec4cef3fee21f728;hpb=4d23d296ac50654b66c5203e5328432d7557d549;p=feed%2Fpackages.git diff --git a/net/shadowsocks-libev/files/ss-rules b/net/shadowsocks-libev/files/ss-rules old mode 100644 new mode 100755 index 8ce1000cbc..b0a30606e1 --- a/net/shadowsocks-libev/files/ss-rules +++ b/net/shadowsocks-libev/files/ss-rules @@ -1,219 +1,264 @@ -#!/bin/sh - -usage() { - cat <<-EOF - Usage: ss-rules [options] - - Valid options are: - - -s hostname or ip of shadowsocks remote server - -l port number of shadowsocks local server - -i a file content is bypassed ip list - -a lan ip of access control, need a prefix to - define access control mode - -b wan ip of will be bypassed - -w wan ip of will be forwarded - -e extra options for iptables - -o apply the rules to the OUTPUT chain - -u enable udprelay mode, TPROXY is required - -U enable udprelay mode, using different IP - and ports for TCP and UDP - -f flush the rules -EOF -} +#!/bin/sh -e +# +# Copyright (C) 2017 Yousong Zhou +# +# The design idea was derived from ss-rules by Jian Chang +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# -loger() { - # 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug - logger -st ss-rules[$$] -p$1 $2 -} +ss_rules_usage() { + cat >&2 < Local port number of ss-redir with TCP mode + -L Local port number of ss-redir with UDP mode + -s List of ip addresses of remote shadowsocks server + --ifnames Only apply rules on packets from these ifnames + --src-bypass + --src-forward + --src-checkdst + --src-default + Packets will have their src ip checked in order against + bypass, forward, checkdst list and will bypass, forward + through, or continue to have their dst ip checked + respectively on the first match. Otherwise, --src-default + decide the default action + --dst-bypass + --dst-forward + --dst-bypass-file + --dst-forward-file + --dst-default + Same as with their --src-xx equivalent + --dst-forward-recentrst + Forward those packets whose destinations have recently + sent to us multiple tcp-rst packets + --local-default + Default action for local out TCP traffic + +The following ipsets will be created by ss-rules. They are also intended to be +populated by other programs like dnsmasq with ipset support -ipt_n="iptables -t nat" -ipt_m="iptables -t mangle" + ss_rules_src_bypass + ss_rules_src_forward + ss_rules_src_checkdst + ss_rules_dst_bypass + ss_rules_dst_forward +EOF +} -flush_r() { - local IPT +o_dst_bypass_=" + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.31.196.0/24 + 192.52.193.0/24 + 192.88.99.0/24 + 192.168.0.0/16 + 192.175.48.0/24 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 + 255.255.255.255 +" +o_src_default=bypass +o_dst_default=bypass +o_local_default=bypass - IPT=$(iptables-save -t nat) - eval $(echo "$IPT" | grep "_SS_SPEC_RULE_" | \ - sed -e 's/^-A/$ipt_n -D/' -e 's/$/;/') +__errmsg() { + echo "ss-rules: $*" >&2 +} - for chain in $(echo "$IPT" | awk '/^:SS_SPEC/{print $1}'); do - $ipt_n -F ${chain:1} 2>/dev/null && $ipt_n -X ${chain:1} +ss_rules_parse_args() { + while [ "$#" -gt 0 ]; do + case "$1" in + -h|--help) ss_rules_usage; exit 0;; + -f|--flush) ss_rules_flush; exit 0;; + -l) o_redir_tcp_port="$2"; shift 2;; + -L) o_redir_udp_port="$2"; shift 2;; + -s) o_remote_servers="$2"; shift 2;; + --ifnames) o_ifnames="$2"; shift 2;; + --ipt-extra) o_ipt_extra="$2"; shift 2;; + --src-default) o_src_default="$2"; shift 2;; + --dst-default) o_dst_default="$2"; shift 2;; + --local-default) o_local_default="$2"; shift 2;; + --src-bypass) o_src_bypass="$2"; shift 2;; + --src-forward) o_src_forward="$2"; shift 2;; + --src-checkdst) o_src_checkdst="$2"; shift 2;; + --dst-bypass) o_dst_bypass="$2"; shift 2;; + --dst-forward) o_dst_forward="$2"; shift 2;; + --dst-forward-recentrst) o_dst_forward_recentrst=1; shift 1;; + --dst-bypass-file) o_dst_bypass_file="$2"; shift 2;; + --dst-forward-file) o_dst_forward_file="$2"; shift 2;; + *) __errmsg "unknown option $1"; return 1;; + esac done - IPT=$(iptables-save -t mangle) - eval $(echo "$IPT" | grep "_SS_SPEC_RULE_" | \ - sed -e 's/^-A/$ipt_m -D/' -e 's/$/;/') + if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then + __errmsg "Requires at least -l or -L option" + return 1 + fi + if [ -n "$o_dst_forward_recentrst" ] && ! iptables -m recent -h >/dev/null; then + __errmsg "Please install iptables-mod-conntrack-extra with opkg" + return 1 + fi + o_remote_servers="$(for s in $o_remote_servers; do resolveip -4 "$s"; done)" +} - for chain in $(echo "$IPT" | awk '/^:SS_SPEC/{print $1}'); do - $ipt_m -F ${chain:1} 2>/dev/null && $ipt_m -X ${chain:1} +ss_rules_flush() { + local setname + + iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters + while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip route flush table 100 + for setname in $(ipset -n list | grep "ss_rules_"); do + ipset destroy "$setname" 2>/dev/null || true done +} - ip rule del fwmark 0x01/0x01 table 100 2>/dev/null - ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null - ipset -X ss_spec_lan_ac 2>/dev/null - ipset -X ss_spec_wan_ac 2>/dev/null - return 0 +ss_rules_ipset_init() { + ipset --exist restore <<-EOF + create ss_rules_src_bypass hash:net hashsize 64 + create ss_rules_src_forward hash:net hashsize 64 + create ss_rules_src_checkdst hash:net hashsize 64 + create ss_rules_dst_bypass hash:net hashsize 64 + create ss_rules_dst_bypass_ hash:net hashsize 64 + create ss_rules_dst_forward hash:net hashsize 64 + create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600 + $(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass") + $(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward") + $(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst") + $(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)") + $(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null)") + EOF } -ipset_r() { - ipset -! -R <<-EOF || return 1 - create ss_spec_wan_ac hash:net - $(echo -e "$IPLIST" | sed -e "s/^/add ss_spec_wan_ac /") - $(for ip in $WAN_FW_IP; do echo "add ss_spec_wan_ac $ip nomatch"; done) -EOF - $ipt_n -N SS_SPEC_WAN_AC && \ - $ipt_n -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN && \ - $ipt_n -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW - return $? +ss_rules_ipset_mkadd() { + local setname="$1"; shift + local i + + for i in $*; do + echo "add $setname $i" + done } -fw_rule() { - $ipt_n -N SS_SPEC_WAN_FW && \ - $ipt_n -A SS_SPEC_WAN_FW -p tcp \ - -j REDIRECT --to-ports $local_port 2>/dev/null || { - loger 3 "Can't redirect, please check the iptables." - exit 1 - } - return $? +ss_rules_iptchains_init() { + ss_rules_iptchains_init_tcp + ss_rules_iptchains_init_udp } -ac_rule() { - local TAG ROUTECHAIN +ss_rules_iptchains_init_tcp() { + local local_target - if [ -n "$LAN_AC_IP" ]; then - if [ "${LAN_AC_IP:0:1}" = "w" ]; then - TAG="nomatch" - else - if [ "${LAN_AC_IP:0:1}" != "b" ]; then - loger 3 "Bad argument \`-a $LAN_AC_IP\`." - return 2 - fi - fi - fi + [ -n "$o_redir_tcp_port" ] || return 0 - ROUTECHAIN=PREROUTING - if iptables-save -t nat | grep -q "^:zone_lan_prerouting"; then - ROUTECHAIN=zone_lan_prerouting - fi + ss_rules_iptchains_init_ nat tcp - ipset -! -R <<-EOF || return 1 - create ss_spec_lan_ac hash:net - $(for ip in ${LAN_AC_IP:1}; do echo "add ss_spec_lan_ac $ip $TAG"; done) -EOF - $ipt_n -A $ROUTECHAIN -p tcp $EXT_ARGS \ - -m set ! --match-set ss_spec_lan_ac src \ - -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_WAN_AC + case "$o_local_default" in + checkdst) local_target=ss_rules_dst ;; + forward) local_target=ss_rules_forward ;; + bypass|*) return 0;; + esac - if [ "$OUTPUT" = 1 ]; then - $ipt_n -A OUTPUT -p tcp $EXT_ARGS \ - -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_WAN_AC - fi - return $? + iptables-restore --noflush <<-EOF + *nat + :ss_rules_local_out - + -I OUTPUT 1 -p tcp -j ss_rules_local_out + -A ss_rules_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A ss_rules_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" + COMMIT + EOF } -tp_rule() { - [ -n "$TPROXY" ] || return 0 - ip rule add fwmark 0x01/0x01 table 100 - ip route add local 0.0.0.0/0 dev lo table 100 - $ipt_m -N SS_SPEC_TPROXY - $ipt_m -A SS_SPEC_TPROXY -p udp -m set ! --match-set ss_spec_wan_ac dst \ - -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01 - $ipt_m -A PREROUTING -p udp $EXT_ARGS \ - -m set ! --match-set ss_spec_lan_ac src \ - -m comment --comment "_SS_SPEC_RULE_" -j SS_SPEC_TPROXY - return $? +ss_rules_iptchains_init_udp() { + [ -n "$o_redir_udp_port" ] || return 0 + ss_rules_iptchains_init_ mangle udp } -while getopts ":s:l:S:L:i:e:a:b:w:ouUf" arg; do - case $arg in - s) - server=$OPTARG - ;; - l) - local_port=$OPTARG - ;; - S) - SERVER=$OPTARG - ;; - L) - LOCAL_PORT=$OPTARG - ;; - i) - IGNORE=$OPTARG - ;; - e) - EXT_ARGS=$OPTARG - ;; - a) - LAN_AC_IP=$OPTARG - ;; - b) - WAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done) - ;; - w) - WAN_FW_IP=$OPTARG - ;; - o) - OUTPUT=1 - ;; - u) - TPROXY=1 - ;; - U) - TPROXY=2 +ss_rules_iptchains_init_() { + local table="$1" + local proto="$2" + local forward_rules + local src_default_target dst_default_target + local recentrst_mangle_rules recentrst_addset_rules + + case "$proto" in + tcp) + forward_rules="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port" + if [ -n "$o_dst_forward_recentrst" ]; then + recentrst_mangle_rules=" + *mangle + -I PREROUTING 1 -p tcp -m tcp --tcp-flags RST RST -m recent --name ss_rules_recentrst --set --rsource + COMMIT + " + recentrst_addset_rules=" + -A ss_rules_dst -m recent --name ss_rules_recentrst --rcheck --rdest --seconds 3 --hitcount 3 -j SET --add-set ss_rules_dst_forward_recentrst_ dst --exist + -A ss_rules_dst -m set --match-set ss_rules_dst_forward_recentrst_ dst -j ss_rules_forward + " + fi ;; - f) - flush_r - exit 0 + udp) + ip rule add fwmark 1 lookup 100 + ip route add local default dev lo table 100 + forward_rules="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01" ;; esac -done - -if [ -z "$server" -o -z "$local_port" ]; then - usage - exit 2 -fi + case "$o_src_default" in + forward) src_default_target=ss_rules_forward ;; + checkdst) src_default_target=ss_rules_dst ;; + bypass|*) src_default_target=RETURN ;; + esac + case "$o_dst_default" in + forward) dst_default_target=ss_rules_forward ;; + bypass|*) dst_default_target=RETURN ;; + esac + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore --noflush + *$table + :ss_rules_pre_src - + :ss_rules_src - + :ss_rules_dst - + :ss_rules_forward - + $(ss_rules_iptchains_mkprerules "$proto") + -A ss_rules_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A ss_rules_pre_src -p $proto $o_ipt_extra -j ss_rules_src + -A ss_rules_src -m set --match-set ss_rules_src_bypass src -j RETURN + -A ss_rules_src -m set --match-set ss_rules_src_forward src -j ss_rules_forward + -A ss_rules_src -m set --match-set ss_rules_src_checkdst src -j ss_rules_dst + -A ss_rules_src -j $src_default_target -m comment --comment "src_default: $o_src_default" + -A ss_rules_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A ss_rules_dst -m set --match-set ss_rules_dst_forward dst -j ss_rules_forward + $recentrst_addset_rules + -A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" + $forward_rules + COMMIT + $recentrst_mangle_rules + EOF +} -if [ "$TPROXY" = 1 ]; then - SERVER=$server - LOCAL_PORT=$local_port -fi +ss_rules_iptchains_mkprerules() { + local proto="$1" -if [ "$TPROXY" = 2 ]; then - if [ -z "$SERVER" -o -z "$LOCAL_PORT" ]; then - loger 3 "Please use -S and -L specifies IP and port for UDP." + if [ -z "$o_ifnames" ]; then + echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src" + else + echo $o_ifnames \ + | tr ' ' '\n' \ + | sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/" fi -fi - -if [ -f "$IGNORE" ]; then - IGNORE_IP=$(cat $IGNORE 2>/dev/null) -fi - -IPLIST=$(cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" - $server - $SERVER - 0.0.0.0/8 - 10.0.0.0/8 - 100.64.0.0/10 - 127.0.0.0/8 - 169.254.0.0/16 - 172.16.0.0/12 - 192.0.0.0/24 - 192.0.2.0/24 - 192.88.99.0/24 - 192.168.0.0/16 - 198.18.0.0/15 - 198.51.100.0/24 - 203.0.113.0/24 - 224.0.0.0/4 - 240.0.0.0/4 - 255.255.255.255 - $WAN_BP_IP - $IGNORE_IP -EOF -) - -flush_r && fw_rule && ipset_r && ac_rule && tp_rule +} -exit $? +ss_rules_parse_args "$@" +ss_rules_flush +ss_rules_ipset_init +ss_rules_iptchains_init