diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile new file mode 100644 index 000000000..74bf8ebae --- /dev/null +++ b/shadowsocks-rust/Makefile @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2017-2020 Yousong Zhou +# Copyright (C) 2021-2023 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=shadowsocks-rust +PKG_VERSION:=1.16.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/shadowsocks/shadowsocks-rust/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=da4c6256247207b2579721046292bab1a2ac62301878c73ff778c168caa8a990 + +PKG_MAINTAINER:=Tianling Shen +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE + +PKG_BUILD_DEPENDS:=rust/host + +RUST_PKG_FEATURES:=local-redir + +include $(INCLUDE_DIR)/package.mk +#include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk +include $(TOPDIR)/feeds/openmptcprouter/rust/rust-package.mk + +define Package/shadowsocks-rust/Default + define Package/shadowsocks-rust-$(1) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocks-rust $(1) + URL:=https://github.com/shadowsocks/shadowsocks-rust + DEPENDS:=$$(RUST_ARCH_DEPENDS) + endef + + define Package/shadowsocks-rust-$(1)/install + $$(INSTALL_DIR) $$(1)/usr/bin + $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/bin/$(1) $$(1)/usr/bin/ + endef +endef + +define Package/shadowsocks-rust-config + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocks-rust config + URL:=https://github.com/shadowsocks/shadowsocks-rust + DEPENDS:=$$(RUST_ARCH_DEPENDS) +endef + + +define Package/shadowsocks-rust-config/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) ./files/ssr-rules $(1)/usr/bin + $(INSTALL_BIN) ./files/ssr-rules6 $(1)/usr/bin + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DATA) ./files/firewall.ssr-rules $(1)/etc + $(INSTALL_BIN) ./files/ssr-rules.defaults $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./files/shadowsocks-rust.config $(1)/etc/config/shadowsocks-rust + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/shadowsocks-rust.init $(1)/etc/init.d/shadowsocks-rust +endef + +SHADOWSOCKS_COMPONENTS:=sslocal ssmanager ssserver ssurl ssservice +define shadowsocks-rust/templates + $(foreach component,$(SHADOWSOCKS_COMPONENTS), + $(call Package/shadowsocks-rust/Default,$(component)) + ) +endef +$(eval $(call shadowsocks-rust/templates)) + +$(eval $(call BuildPackage,shadowsocks-rust-config)) +$(foreach component,$(SHADOWSOCKS_COMPONENTS), \ + $(eval $(call BuildPackage,shadowsocks-rust-$(component))) \ +) diff --git a/shadowsocks-rust/files/firewall.ssr-rules b/shadowsocks-rust/files/firewall.ssr-rules new file mode 100644 index 000000000..87e4769b6 --- /dev/null +++ b/shadowsocks-rust/files/firewall.ssr-rules @@ -0,0 +1,2 @@ +#!/bin/sh +/etc/init.d/shadowsocks-rust rules_up diff --git a/shadowsocks-rust/files/shadowsocks-rust.config b/shadowsocks-rust/files/shadowsocks-rust.config new file mode 100644 index 000000000..82d13a389 --- /dev/null +++ b/shadowsocks-rust/files/shadowsocks-rust.config @@ -0,0 +1,51 @@ +config ss_redir hi1 + option server 'sss0' + option local_address '::' + option local_port '1100' + option mode 'tcp_and_udp' + option timeout '1000' + option fast_open 0 + option verbose 0 + option syslog 1 + option reuse_port 1 + option mptcp 1 + option ipv6_first 1 + option no_delay 1 + +config ss_redir hi2 + option server 'sss0' + option local_address '0.0.0.0' + option local_port '1100' + option mode 'tcp_and_udp' + option timeout '1000' + option fast_open 1 + option verbose 0 + option syslog 1 + option reuse_port 1 + option mptcp 1 + option ipv6_first 1 + option no_delay 1 + option disabled 1 + +config ss_rules 'ss_rules' + option disabled 0 + option redir_tcp 'hi1' + option src_default 'forward' + option dst_default 'forward' + option local_default 'forward' + option server 'sss0' + +config server 'sss0' + option disabled 1 + option server '192.168.1.3' + option server_port '65280' + option key '' + option method '2022-blake3-aes-256-gcm' + option obfs 0 + +config ss_tunnel 'dns' + option disabled 1 + option mode 'tcp_and_udp' + option server 'sss0' + option local_port '5353' + option tunnel_address '8.8.8.8:53' \ No newline at end of file diff --git a/shadowsocks-rust/files/shadowsocks-rust.init b/shadowsocks-rust/files/shadowsocks-rust.init new file mode 100644 index 000000000..ef9e77704 --- /dev/null +++ b/shadowsocks-rust/files/shadowsocks-rust.init @@ -0,0 +1,494 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (C) 2017-2019 Yousong Zhou +# Copyright (C) 2019-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +USE_PROCD=1 +EXTRA_COMMANDS="rules_up rules_down rules_exist" +START=91 + +ss_confdir=/var/etc/shadowsocks-rust +ss_bindir=/usr/bin + +ss_mkjson_server_conf() { + local cfgserver + + config_get cfgserver "$cfg" server + [ -n "$cfgserver" ] || return 1 + eval "$(validate_server_section "$cfg" ss_validate_mklocal)" + validate_server_section "$cfgserver" || return 1 + [ "$disabled" = 0 ] || return 1 + ss_mkjson_server_conf_ "$cfgserver" +} + +ss_mkjson_server_conf_() { + [ -n "$server_port" ] || return 1 + [ -z "$method" ] || json_add_string method "$method" + [ -z "$server" ] || json_add_string server "$server" + json_add_int server_port "$server_port" + [ -z "$password" ] || { + #password="$(echo $password | sed 's/+/-/g; s/\//_/g;')" + json_add_string password "$password" + } + [ -z "$password" ] && return 1 + [ -z "$plugin" ] || json_add_string plugin "$plugin" + [ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts" + if [ "$obfs" = 1 ]; then + if [ "$obfs_plugin" = "obfs" ]; then + obfs_options="obfs=$obfs_type" + [ -z "$obfs_host" ] || obfs_options="$obfs_options;obfs-host=$obfs_host" + [ -z "$obfs_uri" ] || obfs_options="$obfs_options;obfs-uri=$obfs_uri" + [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" + [ "$mptcp" = 1 ] && obfs_options="$obfs_options;mptcp" + [ -z "$timeout" ] || obfs_options="$obfs_options;t=$timeout" + json_add_string plugin "/usr/bin/obfs-local" + json_add_string plugin_opts "$obfs_options" + fi + if [ "$obfs_plugin" = "v2ray" ]; then + obfs_options="loglevel=default" + [ "$obfs_type" = "tls" ] && obfs_options="tls" + [ -z "$obfs_host" ] || obfs_options="$obfs_options;host=$obfs_host" + [ -z "$obfs_uri" ] || obfs_options="$obfs_options;path=$obfs_uri" + [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" + json_add_string plugin "/usr/bin/v2ray-plugin" + json_add_string plugin_opts "$obfs_options" + fi + fi +} + +ss_mkjson_ss_local_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_redir_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_server_conf() { + ss_mkjson_server_conf_ +} + +ss_mkjson_ss_tunnel_conf() { + ss_mkjson_server_conf || return 1 + [ -n "$tunnel_address" ] || return 1 + json_add_string tunnel_address "$tunnel_address" +} + +ss_xxx() { + local cfg="$1" + local cfgtype="$2" + local bin="$ss_bindir/sslocal" + local confjson="$ss_confdir/$cfgtype.$cfg.json" + + [ -x "$bin" ] || return + eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)" + "validate_${cfgtype}_section" "$cfg" || return + [ "$disabled" = 0 ] || return + + json_init + ss_mkjson_${cfgtype}_conf || return + json_add_boolean use_syslog 1 + json_add_boolean ipv6_first "$ipv6_first" + json_add_boolean fast_open "$fast_open" + json_add_boolean reuse_port "$reuse_port" + json_add_boolean no_delay "$no_delay" + json_add_boolean mptcp "$mptcp" + [ "$cfgtype" != "ss_local" ] && json_add_string protocol "${cfgtype/ss_/}" + [ -z "$local_address" ] || json_add_string local_address "$local_address" + [ -z "$local_port" ] || json_add_int local_port "$local_port" + [ -z "$mode" ] || json_add_string mode "$mode" + [ -z "$mtu" ] || json_add_int mtu "$mtu" + [ -z "$timeout" ] || json_add_int timeout "$timeout" + [ -z "$user" ] || json_add_string user "$user" + json_dump -i >"$confjson" + + procd_open_instance "$cfgtype.$cfg" + procd_set_param command "$bin" -c "$confjson" + [ "$verbose" = 0 ] || procd_append_param command -v + [ -z "$bind_address" ] || procd_append_param command -b "$bind_address" + procd_set_param file "$confjson" + procd_set_param limits nofile="512000 512000" + procd_set_param respawn + procd_close_instance + ss_rules_cb +} + +ss_rules_restart() { + local cfg="$1" + local cfgtype="$2" + + eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)" + "validate_${cfgtype}_section" "$cfg" || return 1 + ss_rules_cb +} + +ss_rules_cb() { + local cfgserver 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" + eval "ss_rules6_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_rules6_redir_udp_$cfg=$local_port" + fi + fi +} + +ss_redir_ports() { + port=$(uci -q get shadowsocks-rust.$1.local_port) + server=$(uci -q get shadowsocks-rust.$1.server) + disabled=$(uci -q get shadowsocks-rust.$1.disabled) + if [ "$disabled" != "1" ] && ([ "$server" = "$2" ] || [ "$2" = "" ]); then + if [ "$port" -lt "$min_ss_redir_ports" ]; then + min_ss_redir_ports=$port + fi + if [ "$port" -gt "$max_ss_redir_ports" ]; then + max_ss_redir_ports=$port + fi + fi +} + +ss_rules() { + local cfg="$1" + local bin="$ss_bindir/ssr-rules" + local bin6="$ss_bindir/ssr-rules6" + local cfgtype + local cfgrulesserver + local local_port_tcp local_port_udp + local local_port_tcp6 local_port_udp6 + local args + local rule_name + if [ "$cfg" = "ss_rules" ]; then + rule_name="def" + else + rule_name="$(echo $cfg | sed 's/_rule//' | cut -c -7)" + fi + + [ -x "$bin" ] || return 1 + #"$bin" -f + [ -x "$bin6" ] || return 1 + #"$bin6" -f + + config_get cfgtype "$cfg" TYPE + [ "$cfgtype" = ss_rules ] || return 1 + + config_get cfgrulesserver "$cfg" server + + eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" + validate_ss_rules_section "$cfg" || return 1 + [ "$disabled" != "1" ] || return 0 + [ "$(uci -q get shadowsocks-rust.${cfgrulesserver}.disabled)" != "1" ] || return 0 + if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then + min_ss_redir_ports="65535" + max_ss_redir_ports="0" + config_load shadowsocks-rust + config_foreach ss_redir_ports ss_redir $cfgrulesserver + if [ "$min_ss_redir_ports" != "$max_ss_redir_ports" ]; then + all_ss_redir_ports=$min_ss_redir_ports-$max_ss_redir_ports + else + all_ss_redir_ports=$min_ss_redir_ports + fi + local_port_tcp="$all_ss_redir_ports" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp="$min_ss_redir_ports" + fi + #eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + local_port_tcp6="$all_ss_redir_ports" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp6="$min_ss_redir_ports" + fi + #eval local_port_udp6="\$ss_rules6_redir_udp_$redir_udp" + else + eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" + eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + eval local_port_tcp6="\$ss_rules6_redir_tcp_$redir_tcp" + eval local_port_udp6="\$ss_rules6_redir_udp_$redir_udp" + fi + [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 + ss_redir_servers4="$(echo "$ss_redir_servers" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + ss_redir_servers6="$(echo "$ss_redir_servers" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + [ -z "$ss_redir_servers4" ] && [ -z "$ss_redir_servers6" ] && { + ss_redir_servers4="$ss_redir_servers" + ss_redir_servers6="$ss_redir_servers" + } + #ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)" + dst_ips_bypass4="$(echo "$dst_ips_bypass" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + dst_ips_forward4="$(echo "$dst_ips_forward" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + src_ips_bypass4="$(echo "$src_ips_bypass" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + src_ips_forward4="$(echo "$src_ips_forward" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + src_ips_checkdst4="$(echo "$src_ips_checkdst" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort -u)" + dst_ips_bypass6="$(echo "$dst_ips_bypass" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + dst_ips_forward6="$(echo "$dst_ips_forward" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + src_ips_bypass6="$(echo "$src_ips_bypass" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + src_ips_forward6="$(echo "$src_ips_forward" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + src_ips_checkdst6="$(echo "$src_ips_checkdst" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + [ -z "$dst_ips_bypass4" ] && [ -z "$dst_ips_bypass6" ] && { + dst_ips_bypass4="$dst_ips_bypass" + dst_ips_bypass6="$dst_ips_bypass" + } + [ -z "$dst_ips_forward4" ] && [ -z "$dst_ips_forward6" ] && { + dst_ips_forward4="$dst_ips_forward" + dst_ips_forward6="$dst_ips_forward" + } + [ -z "$src_ips_bypass4" ] && [ -z "$src_ips_bypass6" ] && { + src_ips_bypass4="$src_ips_bypass" + src_ips_bypass6="$src_ips_bypass" + } + [ -z "$src_ips_forward4" ] && [ -z "$src_ips_forward6" ] && { + src_ips_forward4="$src_ips_forward" + src_ips_forward6="$src_ips_forward" + } + [ -z "$src_ips_checkdst4" ] && [ -z "$src_ips_checkdst6" ] && { + src_ips_checkdst4="$src_ips_checkdst" + src_ips_checkdst6="$src_ips_checkdst" + } + [ "$dst_forward_recentrst" = 0 ] || args="$args --dst-forward-recentrst" + + ss_rules_call + ss_rules_call6 +} + +ss_rules_call() { + "$bin" "$@" \ + -s "$ss_redir_servers4" \ + ${local_port_tcp:+-l "$local_port_tcp"} \ + ${local_port_udp:+-L "$local_port_udp"} \ + ${src_default:+--src-default "$src_default"} \ + ${dst_default:+--dst-default "$dst_default"} \ + ${local_default:+--local-default "$local_default"} \ + ${dst_ips_bypass_file:+--dst-bypass-file "$dst_ips_bypass_file"} \ + ${dst_ips_forward_file:+--dst-forward-file "$dst_ips_forward_file"} \ + ${dst_ips_bypass4:+--dst-bypass "$dst_ips_bypass4"} \ + ${dst_ips_forward4:+--dst-forward "$dst_ips_forward4"} \ + ${src_ips_bypass4:+--src-bypass "$src_ips_bypass4"} \ + ${src_ips_forward4:+--src-forward "$src_ips_forward4"} \ + ${src_ips_checkdst4:+--src-checkdst "$src_ips_checkdst4"} \ + ${ifnames:+--ifnames "$ifnames"} \ + ${ipt_args:+--ipt-extra "$ipt_args"} \ + ${cfg:+--rule-name "$rule_name"} \ + $args \ + || "$bin" "$@" -f +} + +ss_rules_call6() { + "$bin6" "$@" \ + -s "$ss_redir_servers6" \ + ${local_port_tcp:+-l "$local_port_tcp6"} \ + ${local_port_udp:+-L "$local_port_udp6"} \ + ${src_default:+--src-default "$src_default"} \ + ${dst_default:+--dst-default "$dst_default"} \ + ${local_default:+--local-default "$local_default"} \ + ${dst_ips_bypass_file:+--dst-bypass-file "$dst_ips_bypass_file"} \ + ${dst_ips_forward_file:+--dst-forward-file "$dst_ips_forward_file"} \ + ${dst_ips_bypass6:+--dst-bypass "$dst_ips_bypass6"} \ + ${dst_ips_forward6:+--dst-forward "$dst_ips_forward6"} \ + ${src_ips_bypass6:+--src-bypass "$src_ips_bypass6"} \ + ${src_ips_forward6:+--src-forward "$src_ips_forward6"} \ + ${src_ips_checkdst6:+--src-checkdst "$src_ips_checkdst6"} \ + ${ifnames:+--ifnames "$ifnames"} \ + ${ipt_args:+--ipt-extra "$ipt_args"} \ + ${cfg:+--rule-name "$rule_name"} \ + $args \ + || "$bin6" "$@" -f +} + +start_service() { + local cfgtype + + mkdir -p "$ss_confdir" + config_load shadowsocks-rust + for cfgtype in ss_local ss_redir ss_server ss_tunnel; do + config_foreach ss_xxx "$cfgtype" "$cfgtype" + done + # Add rule to match traffic marked by firewall for bypass + ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 + rules_up + [ -f /etc/firewall.gre-tunnel ] && sh /etc/firewall.gre-tunnel > /dev/null 2>&1 +} + +stop_service() { + rules_down + rm -rf "$ss_confdir" +} + +reload_service() { + restart "$@" +} + +rules_exist() { + [ -n "$(iptables-save 2>/dev/null | grep 'A ssr')" ] && return 0 + return 1 +} + +server_state() { + config_get disabled "$1" disabled "0" + [ "$disabled" = "0" ] && enabled="1" + config_get password "$1" password + [ -n "$password" ] && passkey=$password +} + +rules_up() { + rules_exist && { + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null + return 0 + } + [ "$(uci -q get shadowsocks-rust.ss_rules.disabled)" = "1" ] && return 0 + enabled="0" + passkey="" + config_load shadowsocks-rust + config_foreach server_state server + [ "$enabled" = "0" ] && return + [ -z "$passkey" ] && return + logger -t "Shadowsocks-rust" "Rules UP" + for cfgtype in ss_redir; do + config_foreach ss_rules_restart "$cfgtype" "$cfgtype" + done + config_foreach ss_rules ss_rules + [ -z "$(iptables-save 2>/dev/null | grep :ssr)" ] && logger -t "Shadowsocks-rust" "Rules not applied" + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { + logger -t "Shadowsocks-rust" "Reload omr-bypass rules" + /etc/init.d/omr-bypass reload_rules + } + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null +} + +rules_down() { + rules_exist || return 0 + logger -t "Shadowsocks-rust" "Rules DOWN" + local bin="$ss_bindir/ssr-rules" + [ -x "$bin" ] && { + "$bin" -f >/dev/null 2>&1 + } + local bin6="$ss_bindir/ssr-rules6" + [ -x "$bin6" ] && { + "$bin6" -f >/dev/null 2>&1 + } +} + +service_triggers() { + procd_add_reload_interface_trigger wan* + procd_add_reload_trigger shadowsocks-rust + procd_open_validate + validate_server_section + validate_ss_local_section + validate_ss_redir_section + validate_ss_rules_section + validate_ss_server_section + validate_ss_tunnel_section + procd_close_validate +} + +ss_validate_mklocal() { + local tuple opts + + shift 2 + for tuple in "$@"; do + opts="${tuple%%:*} $opts" + done + [ -z "$opts" ] || echo "local $opts" +} + +ss_validate() { + uci_validate_section shadowsocks-rust "$@" +} + +validate_common_server_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + local stream_methods='"none", "plain", "chacha20-ietf-poly1305"' + local aead_methods='"aes-128-gcm", "aes-256-gcm","2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "chacha20-ietf-poly1305", "2022-blake3-chacha20-poly1305","2022-blake3-chacha8-poly1305"' + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'server:host' \ + 'server_port:port' \ + 'password:string' \ + "method:or($stream_methods, $aead_methods)" \ + 'plugin:string' \ + 'plugin_opts:string' \ + 'obfs:bool:0' \ + 'obfs_plugin:or("v2ray","obfs"):v2ray' \ + 'obfs_type:or("http","tls"):http' +} + +validate_common_client_options_() { + validate_common_options_ "$@" \ + 'server:uci("shadowsocks-rust", "@server")' \ + 'local_address:host:0.0.0.0' \ + 'local_port:port' +} + +validate_common_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'fast_open:bool:0' \ + 'ipv6_first:bool:0' \ + 'no_delay:bool:0' \ + 'mptcp:bool:0' \ + 'reuse_port:bool:0' \ + 'verbose:bool:0' \ + 'mode:or("tcp_only", "udp_only", "tcp_and_udp"):tcp_only' \ + 'mtu:uinteger' \ + 'timeout:uinteger' \ + 'user:string' +} + +validate_server_section() { + validate_common_server_options_ server "$1" "$2" +} + +validate_ss_local_section() { + validate_common_client_options_ ss_local "$1" "$2" +} + +validate_ss_redir_section() { + validate_common_client_options_ ss_redir "$1" "$2" +} + +validate_ss_rules_section() { + "${2:-ss_validate}" ss_rules "$1" \ + 'disabled:bool:0' \ + 'redir_tcp:or(uci("shadowsocks-rust", "@ss_redir"),"all")' \ + 'redir_udp:or(uci("shadowsocks-rust", "@ss_redir"),"all")' \ + 'src_ips_bypass:or(ipaddr,cidr)' \ + 'src_ips_forward:or(ipaddr,cidr)' \ + 'src_ips_checkdst:or(ipaddr,cidr)' \ + 'dst_ips_bypass_file:file' \ + 'dst_ips_bypass:or(ipaddr,cidr)' \ + 'dst_ips_forward_file:file' \ + 'dst_ips_forward:or(ipaddr,cidr)' \ + 'src_default:or("bypass", "forward", "checkdst"):checkdst' \ + 'dst_default:or("bypass", "forward"):bypass' \ + 'local_default:or("bypass", "forward", "checkdst"):bypass' \ + 'dst_forward_recentrst:bool:0' \ + 'ifnames:maxlength(15)' \ + 'ipt_args:string' +} + +validate_ss_server_section() { + validate_common_server_options_ ss_server "$1" \ + validate_common_options_ \ + "$2" \ + 'bind_address:ipaddr' +} + +validate_ss_tunnel_section() { + validate_common_client_options_ ss_tunnel "$1" \ + "$2" \ + 'tunnel_address:regex(".+\:[0-9]+")' +} diff --git a/shadowsocks-rust/files/ssr-rules b/shadowsocks-rust/files/ssr-rules new file mode 100755 index 000000000..e945d9ef9 --- /dev/null +++ b/shadowsocks-rust/files/ssr-rules @@ -0,0 +1,301 @@ +#!/bin/sh -e +# +# Copyright (C) 2017 Yousong Zhou +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) +# +# 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. +# + +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" +fi + + +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 + + ss_rules_src_bypass + ss_rules_src_forward + ss_rules_src_checkdst + ss_rules_dst_bypass + ss_rules_dst_bypass_all + ss_rules_dst_forward +EOF +} + +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 +} + +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-bypass_all) o_dst_bypass_all="$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;; + --rule-name) rule="$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 + if [ -n "$o_dst_forward_recentrst" ] && ! $IPTABLES -w -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)" +} + +ss_rules_flush() { + local setname + + $IPTABLESSAVE --counters 2>/dev/null | grep -v ssr_ | $IPTABLESRESTORE --counters + while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip route flush table 100 || true + for setname in $(ipset -n list | grep "ssr_${rule}"); do + ipset destroy "$setname" 2>/dev/null || true + done +} + +ss_rules_ipset_init() { + ipset --exist restore <<-EOF + create ssr_${rule}_src_bypass hash:net hashsize 64 + create ssr_${rule}_src_forward hash:net hashsize 64 + create ssr_${rule}_src_checkdst hash:net hashsize 64 + create ss_rules_dst_bypass_all hash:net hashsize 64 + create ssr_${rule}_dst_bypass hash:net hashsize 64 + create ssr_${rule}_dst_bypass_ hash:net hashsize 64 + create ssr_${rule}_dst_forward hash:net hashsize 64 + create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600 + $(ss_rules_ipset_mkadd ssr_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(ss_rules_ipset_mkadd ss_rules_dst_bypass_all "$o_dst_bypass_all") + $(ss_rules_ipset_mkadd ssr_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + $(ss_rules_ipset_mkadd ssr_${rule}_src_bypass "$o_src_bypass") + $(ss_rules_ipset_mkadd ssr_${rule}_src_forward "$o_src_forward") + $(ss_rules_ipset_mkadd ssr_${rule}_src_checkdst "$o_src_checkdst") + $(ss_rules_ipset_mkadd ssr_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + 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_mark + ss_rules_iptchains_init_tcp + ss_rules_iptchains_init_udp +} + +ss_rules_iptchains_init_mark() { + if [ "$($IPTABLES -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE --noflush <<-EOF + *mangle + -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 + COMMIT + EOF + fi +} + +ss_rules_iptchains_init_tcp() { + local local_target + + [ -n "$o_redir_tcp_port" ] || return 0 + + ss_rules_iptchains_init_ nat tcp + + case "$o_local_default" in + checkdst) local_target=ssr_${rule}_dst ;; + forward) local_target=ssr_${rule}_forward ;; + bypass|*) return 0;; + esac + if [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then + $IPTABLESRESTORE --noflush <<-EOF + *nat + :ssr_${rule}_local_out - + -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass_all dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN + -A ssr_${rule}_local_out -m mark --mark 0x539 -j RETURN + -A ssr_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" + COMMIT + EOF + fi +} + +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 + local recentrst_mangle_rules recentrst_addset_rules + + case "$proto" in + tcp) + forward_rules="-A ssr_${rule}_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 ssr_${rule}_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 ssr_${rule}_dst -m set --match-set ss_rules_dst_forward_recentrst_ dst -j ssr_${rule}_forward + " + fi + ;; + udp) + ip rule add fwmark 1 lookup 100 || true + ip route add local default dev lo table 100 || true + forward_rules="-A ssr_${rule}_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01" + ;; + esac + case "$o_src_default" in + forward) src_default_target=ssr_${rule}_forward ;; + checkdst) src_default_target=ssr_${rule}_dst ;; + bypass|*) src_default_target=RETURN ;; + esac + case "$o_dst_default" in + forward) dst_default_target=ssr_${rule}_forward ;; + bypass|*) dst_default_target=RETURN ;; + esac + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE --noflush + *$table + :ssr_${rule}_pre_src - + :ssr_${rule}_src - + :ssr_${rule}_dst - + :ssr_${rule}_forward - + $(ss_rules_iptchains_mkprerules "$proto") + -A ssr_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN + -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 + -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j RETURN + -A ssr_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN + -A ssr_${rule}_pre_src -m mark --mark 0x539 -j RETURN + -A ssr_${rule}_dst -m set --match-set ss_rules_dst_bypass_all dst -j RETURN + -A ssr_${rule}_dst -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN + -A ssr_${rule}_pre_src -p $proto $o_ipt_extra -j ssr_${rule}_src + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_bypass src -j RETURN + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_forward src -j ssr_${rule}_forward + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_checkdst src -j ssr_${rule}_dst + -A ssr_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" + -A ssr_${rule}_dst -m set --match-set ssr_${rule}_dst_forward dst -j ssr_${rule}_forward + $recentrst_addset_rules + -A ssr_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" + $forward_rules + COMMIT + $recentrst_mangle_rules + EOF +} + +ss_rules_iptchains_mkprerules() { + local proto="$1" + + if [ -z "$o_ifnames" ]; then + echo "-A PREROUTING -p $proto -j ssr_${rule}_pre_src" + else + echo $o_ifnames \ + | tr ' ' '\n' \ + | sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ssr_${rule}_pre_src/" + fi +} + +ss_rules_parse_args "$@" +#ss_rules_flush +ss_rules_ipset_init +ss_rules_iptchains_init diff --git a/shadowsocks-rust/files/ssr-rules.defaults b/shadowsocks-rust/files/ssr-rules.defaults new file mode 100755 index 000000000..2c5011c13 --- /dev/null +++ b/shadowsocks-rust/files/ssr-rules.defaults @@ -0,0 +1,12 @@ +#!/bin/sh + +s=firewall.ssr_rules +uci get "$s" >/dev/null || { + uci batch <<-EOF + set $s=include + set $s.path=/etc/firewall.ssr-rules + set $s.reload=1 + commit firewall + EOF +} +exit 0 \ No newline at end of file diff --git a/shadowsocks-rust/files/ssr-rules6 b/shadowsocks-rust/files/ssr-rules6 new file mode 100755 index 000000000..2c2a3eddc --- /dev/null +++ b/shadowsocks-rust/files/ssr-rules6 @@ -0,0 +1,285 @@ +#!/bin/sh -e +# +# Copyright (C) 2017 Yousong Zhou +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) +# +# 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. +# + +if [ -f /usr/sbin/iptables-legacy ]; then + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + + + +ss_rules6_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 + + ss_rules6_src_bypass + ss_rules6_src_forward + ss_rules6_src_checkdst + ss_rules6_dst_bypass + ss_rules6_dst_forward +EOF +} + +o_dst_bypass_=" + fe80::/10 + fd00::/8 + ::1 +" +o_src_default=bypass +o_dst_default=bypass +o_local_default=bypass + +__errmsg() { + echo "ss-rules6: $*" >&2 +} + +ss_rules6_parse_args() { + while [ "$#" -gt 0 ]; do + case "$1" in + -h|--help) ss_rules6_usage; exit 0;; + -f|--flush) ss_rules6_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-bypass_all) o_dst_bypass_all="$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;; + --rule-name) rule="$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 + if [ -n "$o_dst_forward_recentrst" ] && ! $IP6TABLES -w -m recent -h >/dev/null; then + __errmsg "Please install ip6tables-mod-conntrack-extra with opkg" + return 1 + fi + o_remote_servers="$(for s in $o_remote_servers; do resolveip -6 "$s"; done)" +} + +ss_rules6_flush() { + local setname + + $IP6TABLESSAVE --counters 2>/dev/null | grep -v ssr6_ | $IP6TABLESRESTORE --counters + while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip -f inet6 route flush table 100 || true + for setname in $(ipset -n list | grep "ssr6_${rule}"); do + ipset destroy "$setname" 2>/dev/null || true + done +} + +ss_rules6_ipset_init() { + ipset --exist restore <<-EOF + create ssr6_${rule}_src_bypass hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_checkdst hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_bypass hash:net family inet6 hashsize 64 + create ss_rules6_dst_bypass_all hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_bypass_ hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_forward_recrst_ hash:ip family inet6 hashsize 64 timeout 3600 + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(ss_rules6_ipset_mkadd ss_rules6_dst_bypass_all "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_bypass "$o_src_bypass") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_forward "$o_src_forward") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_checkdst "$o_src_checkdst") + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + EOF +} + +ss_rules6_ipset_mkadd() { + local setname="$1"; shift + local i + + for i in $*; do + echo "add $setname $i" + done +} + +ss_rules6_iptchains_init() { + ss_rules6_iptchains_init_mark + ss_rules6_iptchains_init_tcp + ss_rules6_iptchains_init_udp +} + +ss_rules6_iptchains_init_mark() { + if [ "$($IP6TABLES -w -t mangle -L PREROUTING | grep ss_rules6_dst_bypass_all)" = "" ]; then + $IP6TABLESRESTORE --noflush <<-EOF + *mangle + -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 + COMMIT + EOF + fi +} + + +ss_rules6_iptchains_init_tcp() { + local local_target + + [ -n "$o_redir_tcp_port" ] || return 0 + + ss_rules6_iptchains_init_ nat tcp + + case "$o_local_default" in + checkdst) local_target=ssr6_${rule}_dst ;; + forward) local_target=ssr6_${rule}_forward ;; + bypass|*) return 0;; + esac + + $IP6TABLESRESTORE --noflush <<-EOF + *nat + :ssr6_${rule}_local_out - + -I OUTPUT 1 -p tcp -j ssr6_${rule}_local_out + -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN + -A ssr6_${rule}_local_out -m mark --mark 0x6539 -j RETURN + -A ssr6_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" + COMMIT + EOF +} + +ss_rules6_iptchains_init_udp() { + [ -n "$o_redir_udp_port" ] || return 0 + ss_rules6_iptchains_init_ mangle udp +} + +ss_rules6_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 ssr6_${rule}_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_rules6_recentrst --set --rsource + COMMIT + " + recentrst_addset_rules=" + -A ssr6_${rule}_dst -m recent --name ss_rules6_recentrst --rcheck --rdest --seconds 3 --hitcount 3 -j SET --add-set ss_rules6_dst_forward_recrst_ dst --exist + -A ssr6_${rule}_dst -m set --match-set ss_rules6_dst_forward_recrst_ dst -j ssr6_${rule}_forward + " + fi + ;; + udp) + ip -f inet6 rule add fwmark 1 lookup 100 || true + ip -f inet6 route add local default dev lo table 100 || true + forward_rules="-A ssr6_${rule}_forward -p udp -j TPROXY --on-port "$o_redir_udp_port" --tproxy-mark 0x01/0x01" + ;; + esac + case "$o_src_default" in + forward) src_default_target=ssr6_${rule}_forward ;; + checkdst) src_default_target=ssr6_${rule}_dst ;; + bypass|*) src_default_target=RETURN ;; + esac + case "$o_dst_default" in + forward) dst_default_target=ssr6_${rule}_forward ;; + bypass|*) dst_default_target=RETURN ;; + esac + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE --noflush + *$table + :ssr6_${rule}_pre_src - + :ssr6_${rule}_src - + :ssr6_${rule}_dst - + :ssr6_${rule}_forward - + $(ss_rules6_iptchains_mkprerules "$proto") + -A ssr6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN + -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 + -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN + -A ssr6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN + -A ssr6_${rule}_pre_src -m mark --mark 0x6539 -j RETURN + -A ssr6_${rule}_dst -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN + -A ssr6_${rule}_dst -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN + -A ssr6_${rule}_pre_src -p $proto $o_ipt_extra -j ssr6_${rule}_src + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_bypass src -j RETURN + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_forward src -j ssr6_${rule}_forward + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_checkdst src -j ssr6_${rule}_dst + -A ssr6_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" + -A ssr6_${rule}_dst -m set --match-set ssr6_${rule}_dst_forward dst -j ssr6_${rule}_forward + $recentrst_addset_rules + -A ssr6_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" + $forward_rules + COMMIT + $recentrst_mangle_rules + EOF +} + +ss_rules6_iptchains_mkprerules() { + local proto="$1" + + if [ -z "$o_ifnames" ]; then + echo "-A PREROUTING -p $proto -j ssr6_${rule}_pre_src" + else + echo $o_ifnames \ + | tr ' ' '\n' \ + | sed "s/.*/-I PREROUTING 1 -i \\0 -p $proto -j ssr6_${rule}_pre_src/" + fi +} + +ss_rules6_parse_args "$@" +ss_rules6_flush +ss_rules6_ipset_init +ss_rules6_iptchains_init