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_VERSION:=3.0.8
|
||||
PKG_RELEASE:=6
|
||||
PKG_RELEASE:=7
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
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_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_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]
|
||||
|
||||
--- for local out tcp packets, the default action can be specified with
|
||||
|
||||
local_default [bypass], forward, checkdst
|
||||
|
||||
--- if the previous check result is checkdst,
|
||||
--- 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 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
|
||||
|
||||
Useful paths and commands for debugging
|
||||
|
|
|
@ -107,7 +107,7 @@ ss_xxx() {
|
|||
|
||||
[ -x "$bin" ] || return
|
||||
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
|
||||
"validate_${cfgtype}_section" "$cfg"
|
||||
"validate_${cfgtype}_section" "$cfg" || return 1
|
||||
[ "$disabled" = 0 ] || return
|
||||
|
||||
if ss_mkjson \
|
||||
|
@ -127,21 +127,17 @@ ss_xxx() {
|
|||
}
|
||||
|
||||
ss_rules_cb() {
|
||||
local cfgserver
|
||||
local server
|
||||
local cfgserver 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
|
||||
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
|
||||
eval "ss_rules_redir_tcp_$cfg=$local_port"
|
||||
fi
|
||||
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
|
||||
eval "ss_rules_redir_udp_$cfg=$local_port"
|
||||
eval "ss_rules_redir_server_udp_$cfg=$server"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
@ -150,48 +146,37 @@ ss_rules() {
|
|||
local cfg="ss_rules"
|
||||
local bin="$ss_bindir/ss-rules"
|
||||
local cfgtype
|
||||
local args local_port_tcp local_port_udp server_udp
|
||||
local i a_args d_args
|
||||
local local_port_tcp local_port_udp
|
||||
|
||||
[ -x "$bin" ] || return 1
|
||||
config_get cfgtype "$cfg" TYPE
|
||||
[ "$cfgtype" = ss_rules ] || return 1
|
||||
|
||||
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
|
||||
|
||||
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
|
||||
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
|
||||
eval server_udp="\$ss_rules_redir_server_udp_$redir_udp"
|
||||
[ -z "$local_port_udp" ] || args="$args -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
|
||||
[ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
|
||||
ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)"
|
||||
|
||||
"$bin" \
|
||||
-s "$ss_rules_servers" \
|
||||
-s "$ss_redir_servers" \
|
||||
-l "$local_port_tcp" \
|
||||
-S "$server_udp" \
|
||||
-L "$local_port_udp" \
|
||||
-B "$dst_ips_bypass_file" \
|
||||
-W "$dst_ips_forward_file" \
|
||||
-b "$dst_ips_bypass" \
|
||||
-w "$dst_ips_forward" \
|
||||
-e "$ipt_args" \
|
||||
-a "$a_args" \
|
||||
-d "$d_args" \
|
||||
$args \
|
||||
--src-default "$src_default" \
|
||||
--dst-default "$dst_default" \
|
||||
--local-default "$local_default" \
|
||||
--dst-bypass-file "$dst_ips_bypass_file" \
|
||||
--dst-forward-file "$dst_ips_forward_file" \
|
||||
--dst-bypass "$dst_ips_bypass" \
|
||||
--dst-forward "$dst_ips_forward" \
|
||||
--src-bypass "$src_ips_bypass" \
|
||||
--src-forward "$src_ips_forward" \
|
||||
--src-checkdst "$src_ips_checkdst" \
|
||||
--ifnames "$ifnames" \
|
||||
--ipt-extra "$ipt_args" \
|
||||
|| "$bin" -f
|
||||
}
|
||||
|
||||
|
@ -299,15 +284,17 @@ validate_ss_rules_section() {
|
|||
'disabled:bool:0' \
|
||||
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||
'src_ips_bypass:list(ipaddr)' \
|
||||
'src_ips_forward:list(ipaddr)' \
|
||||
'src_ips_checkdst:list(ipaddr)' \
|
||||
'src_ips_bypass:list(or(ip4addr,cidr4))' \
|
||||
'src_ips_forward:list(or(ip4addr,cidr4))' \
|
||||
'src_ips_checkdst:list(or(ip4addr,cidr4))' \
|
||||
'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:list(ipaddr)' \
|
||||
'src_default:or("bypass", "forward", "checkdst")' \
|
||||
'local_default:or("bypass", "forward", "checkdst")' \
|
||||
'dst_ips_forward:list(or(ip4addr,cidr4))' \
|
||||
'src_default:or("bypass", "forward", "checkdst"):checkdst' \
|
||||
'dst_default:or("bypass", "forward"):bypass' \
|
||||
'local_default:or("bypass", "forward", "checkdst"):bypass' \
|
||||
'ifnames:list(maxlength(15))' \
|
||||
'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.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
Usage: ss-rules [options]
|
||||
ss_usage() {
|
||||
cat >&2 <<EOF
|
||||
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
|
||||
-l <local_port> port number of shadowsocks local server
|
||||
-S <server_ips> ip address of shadowsocks remote UDP server
|
||||
-L <local_port> port number of shadowsocks local UDP server
|
||||
-B <ip_list_file> a file whose content is bypassed ip list
|
||||
-b <wan_ips> wan ip of will be bypassed
|
||||
-W <ip_list_file> a file whose content is forwarded ip list
|
||||
-w <wan_ips> wan ip of will be forwarded
|
||||
-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
|
||||
The following ipsets will be created by ss-rules. They are also intended to be
|
||||
populated by other programs like dnsmasq with ipset support
|
||||
|
||||
ss_rules_src_bypass
|
||||
ss_rules_src_forward
|
||||
ss_rules_src_checkdst
|
||||
ss_rules_dst_bypass
|
||||
ss_rules_dst_forward
|
||||
EOF
|
||||
exit $1
|
||||
}
|
||||
|
||||
loger() {
|
||||
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
|
||||
logger -st ss-rules[$$] -p$1 $2
|
||||
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
|
||||
|
||||
__errmsg() {
|
||||
echo "ss-rules: $*" >&2
|
||||
}
|
||||
|
||||
flush_rules() {
|
||||
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
|
||||
if command -v ip >/dev/null 2>&1; then
|
||||
ip rule del fwmark 1 lookup 100 2>/dev/null
|
||||
ip route del local default dev lo table 100 2>/dev/null
|
||||
fi
|
||||
for setname in $(ipset -n list | grep "ss_spec"); do
|
||||
ipset destroy $setname 2>/dev/null
|
||||
done
|
||||
FWI=$(uci get firewall.shadowsocks.path 2>/dev/null)
|
||||
[ -n "$FWI" ] && echo '# firewall include file' >$FWI
|
||||
return 0
|
||||
}
|
||||
|
||||
ipset_init() {
|
||||
ipset -! restore <<-EOF || return 1
|
||||
create ss_spec_src_ac hash:ip hashsize 64
|
||||
create ss_spec_src_bp hash:ip hashsize 64
|
||||
create ss_spec_src_fw hash:ip hashsize 64
|
||||
create ss_spec_dst_sp hash:net hashsize 64
|
||||
create ss_spec_dst_bp hash:net hashsize 64
|
||||
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}
|
||||
;;
|
||||
ss_rules_parse_args() {
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h|--help) ss_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-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
|
||||
|
||||
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() {
|
||||
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
|
||||
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
|
||||
}
|
||||
ss_rules_flush() {
|
||||
local setname
|
||||
|
||||
include_ac_rules() {
|
||||
local protocol=$([ "$1" = "mangle" ] && echo udp || echo tcp)
|
||||
iptables-restore -n <<-EOF
|
||||
*$1
|
||||
:SS_SPEC_LAN_DG - [0:0]
|
||||
: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
|
||||
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
|
||||
}
|
||||
|
||||
while getopts ":s:l:S:L:B:b:W:w:I:d:a:e:oOuUfh" arg; do
|
||||
case "$arg" in
|
||||
s)
|
||||
server=$(for ip in $OPTARG; do echo $ip; done)
|
||||
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
|
||||
$(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)
|
||||
local_port=$OPTARG
|
||||
;;
|
||||
S)
|
||||
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
|
||||
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
|
||||
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
|
||||
unset SERVER
|
||||
LOCAL_PORT=$local_port
|
||||
elif [ "$TPROXY" = 2 ]; then
|
||||
: ${SERVER:?"You must assign an ip for the udp relay server."}
|
||||
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
|
||||
fi
|
||||
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
|
||||
}
|
||||
|
||||
flush_rules && ipset_init && ipt_nat && ipt_mangle && export_ipt_rules
|
||||
RET=$?
|
||||
[ "$RET" = 0 ] || loger 3 "Start failed!"
|
||||
exit $RET
|
||||
ss_rules_parse_args "$@"
|
||||
ss_rules_flush
|
||||
ss_rules_ipset_init
|
||||
ss_rules_iptchains_init
|
||||
|
|
Loading…
Reference in a new issue