shadowsocks-libev: rewrite ss-rules
- New UCI options ifnames, dst_default - UCI options src_ips_xxx now accept cidr as their values - Export ipset names as part of the interface so that it can be depended on and used by other programs - Bypass only remote servers used ss-redir instances, so that it's possible to let other servers to go through existing re-redir instances Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
This commit is contained in:
parent
b1cd3a955a
commit
df395767d3
4 changed files with 262 additions and 283 deletions
|
@ -14,7 +14,7 @@ include $(TOPDIR)/rules.mk
|
||||||
#
|
#
|
||||||
PKG_NAME:=shadowsocks-libev
|
PKG_NAME:=shadowsocks-libev
|
||||||
PKG_VERSION:=3.0.8
|
PKG_VERSION:=3.0.8
|
||||||
PKG_RELEASE:=6
|
PKG_RELEASE:=7
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION)
|
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION)
|
||||||
|
|
|
@ -39,8 +39,9 @@ We can have multiple instances of component and `server` sections. The relation
|
||||||
|
|
||||||
redir_tcp name of ss_redir section with mode tcp_only or tcp_and_udp
|
redir_tcp name of ss_redir section with mode tcp_only or tcp_and_udp
|
||||||
redir_udp name of ss_redir section with mode udp_only or tcp_and_udp
|
redir_udp name of ss_redir section with mode udp_only or tcp_and_udp
|
||||||
|
ifnames only apply rules on packets from these ifnames
|
||||||
|
|
||||||
--- incoming packets having source address in
|
--- for incoming packets having source address in
|
||||||
|
|
||||||
src_ips_bypass will bypass the redir chain
|
src_ips_bypass will bypass the redir chain
|
||||||
src_ips_forward will always go through the redir chain
|
src_ips_forward will always go through the redir chain
|
||||||
|
@ -50,10 +51,6 @@ We can have multiple instances of component and `server` sections. The relation
|
||||||
|
|
||||||
src_default bypass, forward, [checkdst]
|
src_default bypass, forward, [checkdst]
|
||||||
|
|
||||||
--- for local out tcp packets, the default action can be specified with
|
|
||||||
|
|
||||||
local_default [bypass], forward, checkdst
|
|
||||||
|
|
||||||
--- if the previous check result is checkdst,
|
--- if the previous check result is checkdst,
|
||||||
--- then packets having destination address in
|
--- then packets having destination address in
|
||||||
|
|
||||||
|
@ -62,6 +59,18 @@ We can have multiple instances of component and `server` sections. The relation
|
||||||
dst_ips_forward_file
|
dst_ips_forward_file
|
||||||
dst_ips_forward will go through the redir chain
|
dst_ips_forward will go through the redir chain
|
||||||
|
|
||||||
|
--- otherwise, the default action can be specified with
|
||||||
|
|
||||||
|
dst_default [bypass], forward
|
||||||
|
|
||||||
|
--- for local out tcp packets, the default action can be specified with
|
||||||
|
|
||||||
|
local_default [bypass], forward, checkdst
|
||||||
|
|
||||||
|
ss-rules uses kernel ipset mechanism for storing addresses/networks. Those ipsets are also part of the API and can be populated by other programs, e.g. dnsmasq with builtin ipset support. For more details please read output of `ss-rules --help`
|
||||||
|
|
||||||
|
Note also that `src_ips_xx` and `dst_ips_xx` actually also accepts cidr network representation. Names are retained for backward compatibility coniderations
|
||||||
|
|
||||||
## notes and faq
|
## notes and faq
|
||||||
|
|
||||||
Useful paths and commands for debugging
|
Useful paths and commands for debugging
|
||||||
|
|
|
@ -107,7 +107,7 @@ ss_xxx() {
|
||||||
|
|
||||||
[ -x "$bin" ] || return
|
[ -x "$bin" ] || return
|
||||||
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
|
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
|
||||||
"validate_${cfgtype}_section" "$cfg"
|
"validate_${cfgtype}_section" "$cfg" || return 1
|
||||||
[ "$disabled" = 0 ] || return
|
[ "$disabled" = 0 ] || return
|
||||||
|
|
||||||
if ss_mkjson \
|
if ss_mkjson \
|
||||||
|
@ -127,21 +127,17 @@ ss_xxx() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ss_rules_cb() {
|
ss_rules_cb() {
|
||||||
local cfgserver
|
local cfgserver server
|
||||||
local server
|
|
||||||
|
|
||||||
[ "$cfgtype" != ss_server ] || return
|
|
||||||
config_get cfgserver "$cfg" server
|
|
||||||
config_get server "$cfgserver" server
|
|
||||||
|
|
||||||
ss_rules_servers="$ss_rules_servers $server"
|
|
||||||
if [ "$cfgtype" = ss_redir ]; then
|
if [ "$cfgtype" = ss_redir ]; then
|
||||||
|
config_get cfgserver "$cfg" server
|
||||||
|
config_get server "$cfgserver" server
|
||||||
|
ss_redir_servers="$ss_redir_servers $server"
|
||||||
if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then
|
if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then
|
||||||
eval "ss_rules_redir_tcp_$cfg=$local_port"
|
eval "ss_rules_redir_tcp_$cfg=$local_port"
|
||||||
fi
|
fi
|
||||||
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
|
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
|
||||||
eval "ss_rules_redir_udp_$cfg=$local_port"
|
eval "ss_rules_redir_udp_$cfg=$local_port"
|
||||||
eval "ss_rules_redir_server_udp_$cfg=$server"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -150,48 +146,37 @@ ss_rules() {
|
||||||
local cfg="ss_rules"
|
local cfg="ss_rules"
|
||||||
local bin="$ss_bindir/ss-rules"
|
local bin="$ss_bindir/ss-rules"
|
||||||
local cfgtype
|
local cfgtype
|
||||||
local args local_port_tcp local_port_udp server_udp
|
local local_port_tcp local_port_udp
|
||||||
local i a_args d_args
|
|
||||||
|
|
||||||
[ -x "$bin" ] || return 1
|
[ -x "$bin" ] || return 1
|
||||||
config_get cfgtype "$cfg" TYPE
|
config_get cfgtype "$cfg" TYPE
|
||||||
[ "$cfgtype" = ss_rules ] || return 1
|
[ "$cfgtype" = ss_rules ] || return 1
|
||||||
|
|
||||||
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)"
|
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)"
|
||||||
validate_ss_rules_section "$cfg"
|
validate_ss_rules_section "$cfg" || return 1
|
||||||
[ "$disabled" = 0 ] || return 1
|
[ "$disabled" = 0 ] || return 1
|
||||||
|
|
||||||
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
|
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
|
||||||
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
|
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
|
||||||
eval server_udp="\$ss_rules_redir_server_udp_$redir_udp"
|
[ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
|
||||||
[ -z "$local_port_udp" ] || args="$args -U"
|
ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)"
|
||||||
case "$local_default" in
|
|
||||||
forward) args="$args -O" ;;
|
|
||||||
checkdst) args="$args -o" ;;
|
|
||||||
esac
|
|
||||||
case "$src_default" in
|
|
||||||
bypass) d_args=RETURN ;;
|
|
||||||
forward) d_args=SS_SPEC_WAN_FW ;;
|
|
||||||
checkdst) d_args=SS_SPEC_WAN_AC ;;
|
|
||||||
esac
|
|
||||||
ss_rules_servers="$(echo "$ss_rules_servers" | tr ' ' '\n' | sort -u)"
|
|
||||||
for i in $src_ips_bypass; do a_args="b,$i $a_args"; done
|
|
||||||
for i in $src_ips_forward; do a_args="g,$i $a_args"; done
|
|
||||||
for i in $src_ips_checkdst; do a_args="n,$i $a_args"; done
|
|
||||||
|
|
||||||
"$bin" \
|
"$bin" \
|
||||||
-s "$ss_rules_servers" \
|
-s "$ss_redir_servers" \
|
||||||
-l "$local_port_tcp" \
|
-l "$local_port_tcp" \
|
||||||
-S "$server_udp" \
|
|
||||||
-L "$local_port_udp" \
|
-L "$local_port_udp" \
|
||||||
-B "$dst_ips_bypass_file" \
|
--src-default "$src_default" \
|
||||||
-W "$dst_ips_forward_file" \
|
--dst-default "$dst_default" \
|
||||||
-b "$dst_ips_bypass" \
|
--local-default "$local_default" \
|
||||||
-w "$dst_ips_forward" \
|
--dst-bypass-file "$dst_ips_bypass_file" \
|
||||||
-e "$ipt_args" \
|
--dst-forward-file "$dst_ips_forward_file" \
|
||||||
-a "$a_args" \
|
--dst-bypass "$dst_ips_bypass" \
|
||||||
-d "$d_args" \
|
--dst-forward "$dst_ips_forward" \
|
||||||
$args \
|
--src-bypass "$src_ips_bypass" \
|
||||||
|
--src-forward "$src_ips_forward" \
|
||||||
|
--src-checkdst "$src_ips_checkdst" \
|
||||||
|
--ifnames "$ifnames" \
|
||||||
|
--ipt-extra "$ipt_args" \
|
||||||
|| "$bin" -f
|
|| "$bin" -f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,15 +284,17 @@ validate_ss_rules_section() {
|
||||||
'disabled:bool:0' \
|
'disabled:bool:0' \
|
||||||
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
|
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||||
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
|
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||||
'src_ips_bypass:list(ipaddr)' \
|
'src_ips_bypass:list(or(ip4addr,cidr4))' \
|
||||||
'src_ips_forward:list(ipaddr)' \
|
'src_ips_forward:list(or(ip4addr,cidr4))' \
|
||||||
'src_ips_checkdst:list(ipaddr)' \
|
'src_ips_checkdst:list(or(ip4addr,cidr4))' \
|
||||||
'dst_ips_bypass_file:file' \
|
'dst_ips_bypass_file:file' \
|
||||||
'dst_ips_bypass:list(ipaddr)' \
|
'dst_ips_bypass:list(or(ip4addr,cidr4))' \
|
||||||
'dst_ips_forward_file:file' \
|
'dst_ips_forward_file:file' \
|
||||||
'dst_ips_forward:list(ipaddr)' \
|
'dst_ips_forward:list(or(ip4addr,cidr4))' \
|
||||||
'src_default:or("bypass", "forward", "checkdst")' \
|
'src_default:or("bypass", "forward", "checkdst"):checkdst' \
|
||||||
'local_default:or("bypass", "forward", "checkdst")' \
|
'dst_default:or("bypass", "forward"):bypass' \
|
||||||
|
'local_default:or("bypass", "forward", "checkdst"):bypass' \
|
||||||
|
'ifnames:list(maxlength(15))' \
|
||||||
'ipt_args:string'
|
'ipt_args:string'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,260 +1,243 @@
|
||||||
#!/bin/sh
|
#!/bin/sh -e
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2017 Jian Chang <aa65535@live.com>
|
# Copyright (C) 2017 Yousong Zhou <yszhou4tech@gmail.com>
|
||||||
|
#
|
||||||
|
# The design idea was derived from ss-rules by Jian Chang <aa65535@live.com>
|
||||||
#
|
#
|
||||||
# This is free software, licensed under the GNU General Public License v3.
|
# This is free software, licensed under the GNU General Public License v3.
|
||||||
# See /LICENSE for more information.
|
# See /LICENSE for more information.
|
||||||
#
|
#
|
||||||
|
|
||||||
usage() {
|
ss_usage() {
|
||||||
cat <<-EOF
|
cat >&2 <<EOF
|
||||||
Usage: ss-rules [options]
|
Usage: ss-rules [options]
|
||||||
|
|
||||||
Valid options are:
|
-h, --help Show this help message then exit
|
||||||
|
-f, --flush Flush rules, ipset then exit
|
||||||
|
-l <port> Local port number of ss-redir with TCP mode
|
||||||
|
-L <port> Local port number of ss-redir with UDP mode
|
||||||
|
-s <ips> List of ip addresses of remote shadowsocks server
|
||||||
|
--ifnames Only apply rules on packets from these ifnames
|
||||||
|
--src-bypass <ips|cidr>
|
||||||
|
--src-forward <ips|cidr>
|
||||||
|
--src-checkdst <ips|cidr>
|
||||||
|
--src-default <bypass|forward|checkdst>
|
||||||
|
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 <ips|cidr>
|
||||||
|
--dst-forward <ips|cidr>
|
||||||
|
--dst-bypass-file <file>
|
||||||
|
--dst-forward-file <file>
|
||||||
|
--dst-default <bypass|forward>
|
||||||
|
Same as with their --src-xx equivalent
|
||||||
|
--local-default <bypass|forward|checkdst>
|
||||||
|
Default action for local out TCP traffic
|
||||||
|
|
||||||
-s <server_ips> ip address of shadowsocks remote server
|
The following ipsets will be created by ss-rules. They are also intended to be
|
||||||
-l <local_port> port number of shadowsocks local server
|
populated by other programs like dnsmasq with ipset support
|
||||||
-S <server_ips> ip address of shadowsocks remote UDP server
|
|
||||||
-L <local_port> port number of shadowsocks local UDP server
|
ss_rules_src_bypass
|
||||||
-B <ip_list_file> a file whose content is bypassed ip list
|
ss_rules_src_forward
|
||||||
-b <wan_ips> wan ip of will be bypassed
|
ss_rules_src_checkdst
|
||||||
-W <ip_list_file> a file whose content is forwarded ip list
|
ss_rules_dst_bypass
|
||||||
-w <wan_ips> wan ip of will be forwarded
|
ss_rules_dst_forward
|
||||||
-I <interface> proxy only for the given interface
|
|
||||||
-d <target> the default target of lan access control
|
|
||||||
-a <lan_hosts> lan ip of access control, need a prefix to
|
|
||||||
define proxy type
|
|
||||||
-e <extra_args> extra arguments for iptables
|
|
||||||
-o apply the rules to the OUTPUT chain
|
|
||||||
-O apply the global 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
|
|
||||||
-h show this help message and exit
|
|
||||||
EOF
|
EOF
|
||||||
exit $1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loger() {
|
o_dst_bypass_="
|
||||||
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
|
0.0.0.0/8
|
||||||
logger -st ss-rules[$$] -p$1 $2
|
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
|
||||||
|
|
||||||
|
__errmsg() {
|
||||||
|
echo "ss-rules: $*" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_rules() {
|
ss_rules_parse_args() {
|
||||||
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
|
while [ "$#" -gt 0 ]; do
|
||||||
if command -v ip >/dev/null 2>&1; then
|
case "$1" in
|
||||||
ip rule del fwmark 1 lookup 100 2>/dev/null
|
-h|--help) ss_usage; exit 0;;
|
||||||
ip route del local default dev lo table 100 2>/dev/null
|
-f|--flush) ss_rules_flush; exit 0;;
|
||||||
fi
|
-l) o_redir_tcp_port="$2"; shift 2;;
|
||||||
for setname in $(ipset -n list | grep "ss_spec"); do
|
-L) o_redir_udp_port="$2"; shift 2;;
|
||||||
ipset destroy $setname 2>/dev/null
|
-s) o_remote_servers="$2"; shift 2;;
|
||||||
done
|
--ifnames) o_ifnames="$2"; shift 2;;
|
||||||
FWI=$(uci get firewall.shadowsocks.path 2>/dev/null)
|
--ipt-extra) o_ipt_extra="$2"; shift 2;;
|
||||||
[ -n "$FWI" ] && echo '# firewall include file' >$FWI
|
--src-default) o_src_default="$2"; shift 2;;
|
||||||
return 0
|
--dst-default) o_dst_default="$2"; shift 2;;
|
||||||
}
|
--local-default) o_local_default="$2"; shift 2;;
|
||||||
|
--src-bypass) o_src_bypass="$2"; shift 2;;
|
||||||
ipset_init() {
|
--src-forward) o_src_forward="$2"; shift 2;;
|
||||||
ipset -! restore <<-EOF || return 1
|
--src-checkdst) o_src_checkdst="$2"; shift 2;;
|
||||||
create ss_spec_src_ac hash:ip hashsize 64
|
--dst-bypass) o_dst_bypass="$2"; shift 2;;
|
||||||
create ss_spec_src_bp hash:ip hashsize 64
|
--dst-forward) o_dst_forward="$2"; shift 2;;
|
||||||
create ss_spec_src_fw hash:ip hashsize 64
|
--dst-bypass-file) o_dst_bypass_file="$2"; shift 2;;
|
||||||
create ss_spec_dst_sp hash:net hashsize 64
|
--dst-forward-file) o_dst_forward_file="$2"; shift 2;;
|
||||||
create ss_spec_dst_bp hash:net hashsize 64
|
*) __errmsg "unknown option $1"; return 1;;
|
||||||
create ss_spec_dst_fw hash:net hashsize 64
|
|
||||||
$(gen_lan_host_ipset_entry)
|
|
||||||
$(gen_special_purpose_ip | sed -e "s/^/add ss_spec_dst_sp /")
|
|
||||||
$(sed -e "s/^/add ss_spec_dst_bp /" ${WAN_BP_LIST:=/dev/null} 2>/dev/null)
|
|
||||||
$(for ip in $WAN_BP_IP; do echo "add ss_spec_dst_bp $ip"; done)
|
|
||||||
$(sed -e "s/^/add ss_spec_dst_fw /" ${WAN_FW_LIST:=/dev/null} 2>/dev/null)
|
|
||||||
$(for ip in $WAN_FW_IP; do echo "add ss_spec_dst_fw $ip"; done)
|
|
||||||
EOF
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
ipt_nat() {
|
|
||||||
include_ac_rules nat
|
|
||||||
ipt="iptables -t nat"
|
|
||||||
$ipt -A SS_SPEC_WAN_FW -p tcp \
|
|
||||||
-j REDIRECT --to-ports $local_port || return 1
|
|
||||||
if [ -n "$OUTPUT" ]; then
|
|
||||||
$ipt -N SS_SPEC_WAN_DG
|
|
||||||
$ipt -A SS_SPEC_WAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
|
|
||||||
$ipt -A SS_SPEC_WAN_DG -p tcp $EXT_ARGS -j $OUTPUT
|
|
||||||
$ipt -I OUTPUT 1 -p tcp -j SS_SPEC_WAN_DG
|
|
||||||
fi
|
|
||||||
return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
ipt_mangle() {
|
|
||||||
[ -n "$TPROXY" ] || return 0
|
|
||||||
if !(lsmod | grep -q TPROXY && command -v ip >/dev/null); then
|
|
||||||
loger 4 "TPROXY or ip not found."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
ip rule add fwmark 1 lookup 100
|
|
||||||
ip route add local default dev lo table 100
|
|
||||||
include_ac_rules mangle
|
|
||||||
iptables -t mangle -A SS_SPEC_WAN_FW -p udp \
|
|
||||||
-j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01
|
|
||||||
return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
export_ipt_rules() {
|
|
||||||
[ -n "$FWI" ] || return 0
|
|
||||||
cat <<-CAT >>$FWI
|
|
||||||
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
|
|
||||||
iptables-restore -n <<-EOF
|
|
||||||
$(iptables-save | grep -E "SS_SPEC|^\*|^COMMIT" |\
|
|
||||||
sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/")
|
|
||||||
EOF
|
|
||||||
CAT
|
|
||||||
return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_lan_host_ipset_entry() {
|
|
||||||
for host in $LAN_HOSTS; do
|
|
||||||
case "${host:0:1}" in
|
|
||||||
n|N)
|
|
||||||
echo add ss_spec_src_ac ${host:2}
|
|
||||||
;;
|
|
||||||
b|B)
|
|
||||||
echo add ss_spec_src_bp ${host:2}
|
|
||||||
;;
|
|
||||||
g|G)
|
|
||||||
echo add ss_spec_src_fw ${host:2}
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then
|
||||||
|
__errmsg "Requires at least -l or -L option"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_special_purpose_ip() {
|
ss_rules_flush() {
|
||||||
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
|
local setname
|
||||||
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
|
|
||||||
$server
|
|
||||||
$SERVER
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
include_ac_rules() {
|
iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters
|
||||||
local protocol=$([ "$1" = "mangle" ] && echo udp || echo tcp)
|
while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done
|
||||||
iptables-restore -n <<-EOF
|
ip route flush table 100
|
||||||
*$1
|
for setname in $(ipset -n list | grep "ss_rules_"); do
|
||||||
:SS_SPEC_LAN_DG - [0:0]
|
ipset destroy "$setname" 2>/dev/null || true
|
||||||
:SS_SPEC_LAN_AC - [0:0]
|
|
||||||
:SS_SPEC_WAN_AC - [0:0]
|
|
||||||
:SS_SPEC_WAN_FW - [0:0]
|
|
||||||
-A SS_SPEC_LAN_DG -m set --match-set ss_spec_dst_sp dst -j RETURN
|
|
||||||
-A SS_SPEC_LAN_DG -p $protocol $EXT_ARGS -j SS_SPEC_LAN_AC
|
|
||||||
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_bp src -j RETURN
|
|
||||||
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_fw src -j SS_SPEC_WAN_FW
|
|
||||||
-A SS_SPEC_LAN_AC -m set --match-set ss_spec_src_ac src -j SS_SPEC_WAN_AC
|
|
||||||
-A SS_SPEC_LAN_AC -j ${LAN_TARGET:=SS_SPEC_WAN_AC}
|
|
||||||
-A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_fw dst -j SS_SPEC_WAN_FW
|
|
||||||
-A SS_SPEC_WAN_AC -m set --match-set ss_spec_dst_bp dst -j RETURN
|
|
||||||
-A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
|
|
||||||
$(gen_prerouting_rules $protocol)
|
|
||||||
COMMIT
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_prerouting_rules() {
|
|
||||||
[ -z "$IFNAMES" ] && echo -I PREROUTING 1 -p $1 -j SS_SPEC_LAN_DG
|
|
||||||
for ifname in $IFNAMES; do
|
|
||||||
echo -I PREROUTING 1 -i $ifname -p $1 -j SS_SPEC_LAN_DG
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
while getopts ":s:l:S:L:B:b:W:w:I:d:a:e:oOuUfh" arg; do
|
ss_rules_ipset_init() {
|
||||||
case "$arg" in
|
ipset --exist restore <<-EOF
|
||||||
s)
|
create ss_rules_src_bypass hash:net hashsize 64
|
||||||
server=$(for ip in $OPTARG; do echo $ip; done)
|
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
|
||||||
|
$(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
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_rules_ipset_mkadd() {
|
||||||
|
local setname="$1"; shift
|
||||||
|
local i
|
||||||
|
|
||||||
|
for i in $*; do
|
||||||
|
echo "add $setname $i"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_rules_iptchains_init() {
|
||||||
|
ss_rules_iptchains_init_tcp
|
||||||
|
ss_rules_iptchains_init_udp
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_rules_iptchains_init_tcp() {
|
||||||
|
local ipt="iptables -t nat"
|
||||||
|
local local_target
|
||||||
|
local forward_rules
|
||||||
|
local r
|
||||||
|
|
||||||
|
[ -n "$o_redir_tcp_port" ] || return 0
|
||||||
|
|
||||||
|
ss_rules_iptchains_init_ nat tcp
|
||||||
|
|
||||||
|
case "$o_local_default" in
|
||||||
|
checkdst) local_target=ss_rules_dst ;;
|
||||||
|
forward) local_target=ss_rules_forward ;;
|
||||||
|
bypass|*) return 0;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_rules_iptchains_init_udp() {
|
||||||
|
[ -n "$o_redir_udp_port" ] || return 0
|
||||||
|
ss_rules_iptchains_init_ mangle udp
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_rules_iptchains_init_() {
|
||||||
|
local table="$1"
|
||||||
|
local proto="$2"
|
||||||
|
local forward_rules
|
||||||
|
local src_default_target dst_default_target
|
||||||
|
|
||||||
|
case "$proto" in
|
||||||
|
tcp)
|
||||||
|
forward_rules="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port"
|
||||||
;;
|
;;
|
||||||
l)
|
udp)
|
||||||
local_port=$OPTARG
|
ip rule add fwmark 1 lookup 100
|
||||||
;;
|
ip route add local default dev lo table 100
|
||||||
S)
|
forward_rules="-A ss_rules_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01"
|
||||||
SERVER=$(for ip in $OPTARG; do echo $ip; done)
|
|
||||||
;;
|
|
||||||
L)
|
|
||||||
LOCAL_PORT=$OPTARG
|
|
||||||
;;
|
|
||||||
B)
|
|
||||||
WAN_BP_LIST=$OPTARG
|
|
||||||
;;
|
|
||||||
b)
|
|
||||||
WAN_BP_IP=$OPTARG
|
|
||||||
;;
|
|
||||||
W)
|
|
||||||
WAN_FW_LIST=$OPTARG
|
|
||||||
;;
|
|
||||||
w)
|
|
||||||
WAN_FW_IP=$OPTARG
|
|
||||||
;;
|
|
||||||
I)
|
|
||||||
IFNAMES=$OPTARG
|
|
||||||
;;
|
|
||||||
d)
|
|
||||||
LAN_TARGET=$OPTARG
|
|
||||||
;;
|
|
||||||
a)
|
|
||||||
LAN_HOSTS=$OPTARG
|
|
||||||
;;
|
|
||||||
e)
|
|
||||||
EXT_ARGS=$OPTARG
|
|
||||||
;;
|
|
||||||
o)
|
|
||||||
OUTPUT=SS_SPEC_WAN_AC
|
|
||||||
;;
|
|
||||||
O)
|
|
||||||
OUTPUT=SS_SPEC_WAN_FW
|
|
||||||
;;
|
|
||||||
u)
|
|
||||||
TPROXY=1
|
|
||||||
;;
|
|
||||||
U)
|
|
||||||
TPROXY=2
|
|
||||||
;;
|
|
||||||
f)
|
|
||||||
flush_rules
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
h)
|
|
||||||
usage 0
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
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
|
||||||
|
iptables-restore --noflush <<-EOF
|
||||||
|
*$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
|
||||||
|
-A ss_rules_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default"
|
||||||
|
$forward_rules
|
||||||
|
COMMIT
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
[ -z "$server" -o -z "$local_port" ] && usage 2
|
ss_rules_iptchains_mkprerules() {
|
||||||
|
local proto="$1"
|
||||||
|
|
||||||
if [ "$TPROXY" = 1 ]; then
|
if [ -z "$o_ifnames" ]; then
|
||||||
unset SERVER
|
echo "-I PREROUTING 1 -p $proto -j ss_rules_pre_src"
|
||||||
LOCAL_PORT=$local_port
|
else
|
||||||
elif [ "$TPROXY" = 2 ]; then
|
echo "$o_ifnames" \
|
||||||
: ${SERVER:?"You must assign an ip for the udp relay server."}
|
| tr ' ' '\n' \
|
||||||
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
|
| sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ss_rules_pre_src/"
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
flush_rules && ipset_init && ipt_nat && ipt_mangle && export_ipt_rules
|
ss_rules_parse_args "$@"
|
||||||
RET=$?
|
ss_rules_flush
|
||||||
[ "$RET" = 0 ] || loger 3 "Start failed!"
|
ss_rules_ipset_init
|
||||||
exit $RET
|
ss_rules_iptchains_init
|
||||||
|
|
Loading…
Reference in a new issue