From fdaf2de2aee717dc6ae9a39ef9ba6f0388993e5d Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Wed, 23 Feb 2022 08:55:08 +0000 Subject: [PATCH] shadowsocks-libev: convert to using nft It will be mostly implemented with ucode templates installed at /usr/share/ss-rules and called from init script. The generated nftables rules will be stored at /etc/nftables.d/ Incompatible changes were introduced as described in the README.md file - Netfilter ipset was replaced with nftables sets - UCI options ipt_args and dst_forward_recentrst of section ss_rules are now deprecated. The former does not apply to nftables. The later not yet implemented with nftables. Signed-off-by: Yousong Zhou --- net/shadowsocks-libev/Makefile | 28 +- net/shadowsocks-libev/README.md | 7 +- .../files/shadowsocks-libev.init | 83 ++--- net/shadowsocks-libev/files/ss-rules | 298 ------------------ net/shadowsocks-libev/files/ss-rules.defaults | 10 - net/shadowsocks-libev/files/ss-rules/chain.uc | 118 +++++++ net/shadowsocks-libev/files/ss-rules/set.uc | 113 +++++++ .../files/ss-rules/ss-rules.uc | 8 + 8 files changed, 297 insertions(+), 368 deletions(-) delete mode 100755 net/shadowsocks-libev/files/ss-rules delete mode 100755 net/shadowsocks-libev/files/ss-rules.defaults create mode 100644 net/shadowsocks-libev/files/ss-rules/chain.uc create mode 100644 net/shadowsocks-libev/files/ss-rules/set.uc create mode 100644 net/shadowsocks-libev/files/ss-rules/ss-rules.uc diff --git a/net/shadowsocks-libev/Makefile b/net/shadowsocks-libev/Makefile index 1da8b2a9b..d5d26f53c 100644 --- a/net/shadowsocks-libev/Makefile +++ b/net/shadowsocks-libev/Makefile @@ -14,7 +14,7 @@ include $(TOPDIR)/rules.mk # PKG_NAME:=shadowsocks-libev PKG_VERSION:=3.3.5 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION) @@ -89,25 +89,19 @@ define Package/shadowsocks-libev-ss-rules SUBMENU:=Web Servers/Proxies TITLE:=shadowsocks-libev ss-rules URL:=https://github.com/shadowsocks/shadowsocks-libev - DEPENDS:=+ip +ipset +iptables-mod-tproxy +kmod-ipt-nat +resolveip +shadowsocks-libev-ss-redir +shadowsocks-libev-config + DEPENDS:=+firewall4 \ + +ip \ + +resolveip \ + +ucode \ + +ucode-mod-fs \ + +shadowsocks-libev-ss-redir \ + +shadowsocks-libev-config \ + +kmod-nft-tproxy endef define Package/shadowsocks-libev-ss-rules/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) ./files/ss-rules $(1)/usr/bin - $(INSTALL_DIR) $(1)/etc/uci-defaults - $(INSTALL_DATA) ./files/firewall.ss-rules $(1)/etc - $(INSTALL_BIN) ./files/ss-rules.defaults $(1)/etc/uci-defaults -endef - -define Package/shadowsocks-libev-ss-rules/prerm -#!/bin/sh -s=firewall.ss_rules -uci get "$$s" >/dev/null || exit 0 -uci batch <<-EOF - delete $$s - commit firewall -EOF + $(INSTALL_DIR) $(1)/usr/share/ss-rules + $(INSTALL_DATA) ./files/ss-rules/* $(1)/usr/share/ss-rules/ endef define Build/Prepare diff --git a/net/shadowsocks-libev/README.md b/net/shadowsocks-libev/README.md index 6be10e7f9..736fb3bf9 100644 --- a/net/shadowsocks-libev/README.md +++ b/net/shadowsocks-libev/README.md @@ -71,9 +71,7 @@ We can have multiple instances of component and `server` sections. The relation local_default [bypass], forward, checkdst -Bool option `dst_forward_recentrst` requires iptables/netfilter `recent` match module (`opkg install iptables-mod-conntrack-extra`). When enabled, `ss-rules` will setup iptables rules to forward through `ss-redir` those packets whose destination have recently sent to us multiple tcp-rst. - -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` +ss-rules now uses nft set for storing addresses/networks. Those set names are also part of the API and can be populated by other programs, e.g. dnsmasq with builtin nft set support Note also that `src_ips_xx` and `dst_ips_xx` actually also accepts cidr network representation. Option names are retained in its current form for backward compatibility coniderations @@ -81,6 +79,7 @@ Note also that `src_ips_xx` and `dst_ips_xx` actually also accepts cidr network | Commit date | Commit ID | Subject | Comment | | ----------- | --------- | ------- | ------- | +| | | shadowsocks-libev: ss-rules: convert to using nft | ss-rules now uses nftables. UCI option ipt_args and dst_forward_recentrst are now deprecated and removed | | 2020-08-03 | 7d7cbae75 | shadowsocks-libev: support ss-server option local_address_{v4,v6} | ss_server bind_address now deprecated, use local_address | | 2019-05-09 | afe7d3424 | shadowsocks-libev: move plugin options to server section | This is a revision against c19e949 committed 2019-05-06 | | 2017-07-02 | b61af9703 | shadowsocks-libev: rewrite | Packaging of shadowsocks-libev was rewritten from scratch | @@ -162,7 +161,7 @@ Restart shadowsocks-libev components Check if things are in place - iptables-save | grep ss_rules + nft list ruleset | sed -r -n '/^\t[a-z]+ ss_rules[^ ]+ \{/,/^\t\}/p' netstat -lntp | grep -E '8053|1100' ps ww | grep ss- diff --git a/net/shadowsocks-libev/files/shadowsocks-libev.init b/net/shadowsocks-libev/files/shadowsocks-libev.init index dc94b952f..0805e4019 100644 --- a/net/shadowsocks-libev/files/shadowsocks-libev.init +++ b/net/shadowsocks-libev/files/shadowsocks-libev.init @@ -12,6 +12,9 @@ START=99 ss_confdir=/var/etc/shadowsocks-libev ss_bindir=/usr/bin +ssrules_uc="/usr/share/ss-rules/ss-rules.uc" +ssrules_nft="/etc/nftables.d/90-ss-rules.nft" + ss_mkjson_server_conf() { local cfgserver @@ -111,14 +114,11 @@ ss_rules_cb() { ss_rules() { local cfg="ss_rules" - local bin="$ss_bindir/ss-rules" local cfgtype local local_port_tcp local_port_udp - local args + local remote_servers - [ -x "$bin" ] || return 1 - "$bin" -f - "$bin" -6 -f + [ -s "$ssrules_uc" ] || return 1 config_get cfgtype "$cfg" TYPE [ "$cfgtype" = ss_rules ] || return 1 @@ -130,32 +130,41 @@ ss_rules() { eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 - ss_redir_servers="$(echo "$ss_redir_servers" | tr ' ' '\n' | sort -u)" - [ "$dst_forward_recentrst" = 0 ] || args="$args --dst-forward-recentrst" - - ss_rules_call - ss_rules_call -6 -} + remote_servers="$(echo $ss_redir_servers \ + | tr ' ' '\n' \ + | sort -u \ + | xargs -n 1 resolveip \ + | sort -u)" -ss_rules_call() { - "$bin" "$@" \ - -s "$ss_redir_servers" \ - -l "$local_port_tcp" \ - -L "$local_port_udp" \ - --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" \ - $args \ - || "$bin" "$@" -f + local tmp="/tmp/ssrules" + json_init + json_add_string o_remote_servers "$remote_servers" + json_add_int o_redir_tcp_port "$local_port_tcp" + json_add_int o_redir_udp_port "$local_port_udp" + json_add_string o_ifnames "$ifnames" + json_add_string o_local_default "$local_default" + json_add_string o_src_bypass "$src_ips_bypass" + json_add_string o_src_forward "$src_ips_forward" + json_add_string o_src_checkdst "$src_ips_checkdst" + json_add_string o_src_default "$src_default" + json_add_string o_dst_bypass "$dst_ips_bypass" + json_add_string o_dst_forward "$dst_ips_forward" + json_add_string o_dst_bypass_file "$dst_ips_bypass_file" + json_add_string o_dst_forward_file "$dst_ips_forward_file" + json_add_string o_dst_default "$dst_default" + json_dump -i >"$tmp.json" + + if ucode -S -i "$ssrules_uc" -E "$tmp.json" >"$tmp.nft" \ + && ! cmp -s "$tmp.nft" "$ssrules_nft"; then + echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" + if nft -f "$tmp.nft.chk" -c; then + mv "$tmp.nft" "$ssrules_nft" + fw4 reload + fi + rm -f "$tmp.nft.chk" + fi + rm -f "$tmp.json" + rm -f "$tmp.nft" } start_service() { @@ -170,12 +179,10 @@ start_service() { } stop_service() { - local bin="$ss_bindir/ss-rules" - - [ -x "$bin" ] && { - "$bin" -f - "$bin" -6 -f - } + if [ -f "$ssrules_nft" ]; then + rm -f "$ssrules_nft" + fw4 reload + fi rm -rf "$ss_confdir" } @@ -276,9 +283,7 @@ validate_ss_rules_section() { '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' + 'ifnames:maxlength(15)' } validate_ss_server_section() { diff --git a/net/shadowsocks-libev/files/ss-rules b/net/shadowsocks-libev/files/ss-rules deleted file mode 100755 index ed033afcf..000000000 --- a/net/shadowsocks-libev/files/ss-rules +++ /dev/null @@ -1,298 +0,0 @@ -#!/bin/sh -e -# -# Copyright (C) 2017 Yousong Zhou -# -# The design idea was derived from ss-rules by Jian Chang -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -__errmsg() { - echo "ss-rules: $*" >&2 -} - -if [ "$1" = "-6" ]; then - if ! ip6tables -t nat -L -n &>/dev/null; then - __errmsg "Skipping ipv6. Requires ip6tables-mod-nat" - exit 1 - fi - o_use_ipv6=1; shift -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_forward -EOF -} - -o_dst_bypass4_=" - 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_dst_bypass6_=" - ::1/128 - ::/128 - ::ffff:0:0/96 - 64:ff9b:1::/48 - 100::/64 - 2001:2::/48 - 2001:db8::/32 - fe80::/10 - 2001::/23 - fc00::/7 -" -o_src_default=bypass -o_dst_default=bypass -o_local_default=bypass - -alias grep_af="sed -ne '/:/!p'" -o_dst_bypass_="$o_dst_bypass4_" -if [ -n "$o_use_ipv6" ]; then - alias grep_af="sed -ne /:/p" - alias iptables=ip6tables - alias iptables-save=ip6tables-save - alias iptables-restore=ip6tables-restore - alias ip="ip -6" - o_af=6 - o_dst_bypass_="$o_dst_bypass6_" -fi - -ss_rules_parse_args() { - while [ "$#" -gt 0 ]; do - case "$1" in - -h|--help) ss_rules_usage; exit 0;; - -f|--flush) ss_rules_flush; exit 0;; - -l) o_redir_tcp_port="$2"; shift 2;; - -L) o_redir_udp_port="$2"; shift 2;; - -s) o_remote_servers="$2"; shift 2;; - --ifnames) o_ifnames="$2"; shift 2;; - --ipt-extra) o_ipt_extra="$2"; shift 2;; - --src-default) o_src_default="$2"; shift 2;; - --dst-default) o_dst_default="$2"; shift 2;; - --local-default) o_local_default="$2"; shift 2;; - --src-bypass) o_src_bypass="$2"; shift 2;; - --src-forward) o_src_forward="$2"; shift 2;; - --src-checkdst) o_src_checkdst="$2"; shift 2;; - --dst-bypass) o_dst_bypass="$2"; shift 2;; - --dst-forward) o_dst_forward="$2"; shift 2;; - --dst-forward-recentrst) o_dst_forward_recentrst=1; shift 1;; - --dst-bypass-file) o_dst_bypass_file="$2"; shift 2;; - --dst-forward-file) o_dst_forward_file="$2"; shift 2;; - *) __errmsg "unknown option $1"; return 1;; - esac - done - - if [ -z "$o_redir_tcp_port" -a -z "$o_redir_udp_port" ]; then - __errmsg "Requires at least -l or -L option" - return 1 - fi - if [ -n "$o_dst_forward_recentrst" ] && ! iptables -m recent -h >/dev/null; then - __errmsg "Please install iptables-mod-conntrack-extra" - return 1 - fi - o_remote_servers="$(for s in $o_remote_servers; do resolveip "$s" | grep_af; done)" -} - -ss_rules_flush() { - local setname - - iptables-save --counters | grep -v ss_rules_ | iptables-restore --counters - while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done - ip route flush table 100 2>/dev/null || true - for setname in $(ipset -n list | grep "ss_rules${o_af}_"); do - ipset destroy "$setname" 2>/dev/null || true - done -} - -ss_rules_ipset_init() { - ipset --exist restore <<-EOF - create ss_rules${o_af}_src_bypass hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_src_forward hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_src_checkdst hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_dst_bypass hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_dst_bypass_ hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_dst_forward hash:net family inet$o_af hashsize 64 - create ss_rules${o_af}_dst_forward_rrst_ hash:ip family inet$o_af hashsize 8 timeout 3600 - $(ss_rules_ipset_mkadd ss_rules${o_af}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") - $(ss_rules_ipset_mkadd ss_rules${o_af}_src_bypass "$o_src_bypass") - $(ss_rules_ipset_mkadd ss_rules${o_af}_src_forward "$o_src_forward") - $(ss_rules_ipset_mkadd ss_rules${o_af}_src_checkdst "$o_src_checkdst") - $(ss_rules_ipset_mkadd ss_rules${o_af}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null)") - $(ss_rules_ipset_mkadd ss_rules${o_af}_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 | grep_af -} - -ss_rules_iptchains_init() { - ss_rules_iptchains_init_tcp - ss_rules_iptchains_init_udp -} - -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=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${o_af}_dst_bypass_ dst -j RETURN - -A ss_rules_local_out $o_ipt_extra -j $local_target - 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 - local recentrst_mangle_rules recentrst_addset_rules - - case "$proto" in - tcp) - forward_rules="-A ss_rules_forward -p tcp -j REDIRECT --to-ports $o_redir_tcp_port" - if [ -n "$o_dst_forward_recentrst" ]; then - recentrst_mangle_rules=" - *mangle - -I PREROUTING 1 -p tcp -m tcp --tcp-flags RST RST -m recent --name ss_rules_recentrst --set --rsource - COMMIT - " - recentrst_addset_rules=" - -A ss_rules_dst -m recent --name ss_rules_recentrst --rcheck --rdest --seconds 3 --hitcount 3 -j SET --add-set ss_rules${o_af}_dst_forward_rrst_ dst --exist - -A ss_rules_dst -m set --match-set ss_rules${o_af}_dst_forward_rrst_ dst -j ss_rules_forward - " - fi - ;; - 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 - case "$o_src_default" in - forward) src_default_target=ss_rules_forward ;; - checkdst) src_default_target=ss_rules_dst ;; - bypass|*) src_default_target=RETURN ;; - esac - case "$o_dst_default" in - forward) dst_default_target=ss_rules_forward ;; - bypass|*) dst_default_target=RETURN ;; - esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore --noflush - *$table - :ss_rules_pre_src - - :ss_rules_src - - :ss_rules_dst - - :ss_rules_forward - - $(ss_rules_iptchains_mkprerules "$proto") - -A ss_rules_pre_src -m set --match-set ss_rules${o_af}_dst_bypass_ dst -j RETURN - -A ss_rules_pre_src $o_ipt_extra -j ss_rules_src - -A ss_rules_src -m set --match-set ss_rules${o_af}_src_bypass src -j RETURN - -A ss_rules_src -m set --match-set ss_rules${o_af}_src_forward src -j ss_rules_forward - -A ss_rules_src -m set --match-set ss_rules${o_af}_src_checkdst src -j ss_rules_dst - -A ss_rules_src -j $src_default_target - -A ss_rules_dst -m set --match-set ss_rules${o_af}_dst_bypass dst -j RETURN - -A ss_rules_dst -m set --match-set ss_rules${o_af}_dst_forward dst -j ss_rules_forward - $recentrst_addset_rules - -A ss_rules_dst -j $dst_default_target - $forward_rules - COMMIT - $recentrst_mangle_rules - EOF -} - -ss_rules_iptchains_mkprerules() { - local proto="$1" - - 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 -} - -ss_rules_parse_args "$@" -ss_rules_flush -ss_rules_ipset_init -ss_rules_iptchains_init diff --git a/net/shadowsocks-libev/files/ss-rules.defaults b/net/shadowsocks-libev/files/ss-rules.defaults deleted file mode 100755 index c89e2d0b8..000000000 --- a/net/shadowsocks-libev/files/ss-rules.defaults +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -s=firewall.ss_rules -uci get "$s" >/dev/null && exit 0 -uci batch <<-EOF - set $s=include - set $s.path=/etc/firewall.ss-rules - set $s.reload=1 - commit firewall -EOF diff --git a/net/shadowsocks-libev/files/ss-rules/chain.uc b/net/shadowsocks-libev/files/ss-rules/chain.uc new file mode 100644 index 000000000..00362f694 --- /dev/null +++ b/net/shadowsocks-libev/files/ss-rules/chain.uc @@ -0,0 +1,118 @@ +{% +function get_local_verdict() { + let v = o_local_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return null; + } +} + +function get_src_default_verdict() { + let v = o_src_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_dst_default_verdict() { + let v = o_dst_default; + if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_ifnames() { + let res = []; + for (let ifname in split(o_ifnames, /[ \t\n]/)) { + ifname = trim(ifname); + if (ifname) push(res, ifname); + } + return res; +} + +let type, hook, priority, redir_port; +if (proto == "tcp") { + type = "nat"; + hook = "prerouting"; + priority = -1; + redir_port = o_redir_tcp_port; +} else if (proto == "udp") { + type = "filter"; + hook = "prerouting"; + priority = "mangle"; + redir_port = o_redir_udp_port; + if (system(" + set -o errexit + while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip rule add fwmark 1 lookup 100 + ip route flush table 100 2>/dev/null || true + ip route add local default dev lo table 100 + ") != 0) { + return ; + } +} else { + return; +} + +%} +{% if (redir_port): %} + +chain ss_rules_pre_{{ proto }} { + type {{ type }} hook {{ hook }} priority {{ priority }}; + meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto ss_rules_pre_src_{{ proto }}; +} + +chain ss_rules_pre_src_{{ proto }} { + ip daddr @ss_rules_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + goto ss_rules_src_{{ proto }}; +} + +chain ss_rules_src_{{ proto }} { + ip saddr @ss_rules_src_bypass accept; + ip saddr @ss_rules_src_forward goto ss_rules_forward_{{ proto }}; + ip saddr @ss_rules_src_checkdst goto ss_rules_dst_{{ proto }}; + ip6 saddr @ss_rules6_src_bypass accept; + ip6 saddr @ss_rules6_src_forward goto ss_rules_forward_{{ proto }}; + ip6 saddr @ss_rules6_src_checkdst goto ss_rules_dst_{{ proto }}; + {{ get_src_default_verdict() }}; +} + +chain ss_rules_dst_{{ proto }} { + ip daddr @ss_rules_dst_bypass accept; + ip daddr @ss_rules_dst_forward goto ss_rules_forward_{{ proto }}; + ip6 daddr @ss_rules6_dst_bypass accept; + ip6 daddr @ss_rules6_dst_forward goto ss_rules_forward_{{ proto }}; + {{ get_dst_default_verdict() }}; +} + +{% if (proto == "tcp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto tcp redirect to :{{ redir_port }}; +} +{% let local_verdict = get_local_verdict(); if (local_verdict): %} +chain ss_rules_local_out { + type {{ type }} hook output priority -1; + meta l4proto != tcp accept; + ip daddr @ss_rules_dst_bypass_ accept; + ip daddr @ss_rules_dst_bypass accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass accept; + {{ local_verdict }}; +} +{% endif %} +{% elif (proto == "udp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto udp meta mark set 1 tproxy to :{{ redir_port }}; +} +{% endif %} +{% endif %} diff --git a/net/shadowsocks-libev/files/ss-rules/set.uc b/net/shadowsocks-libev/files/ss-rules/set.uc new file mode 100644 index 000000000..5947f6ccd --- /dev/null +++ b/net/shadowsocks-libev/files/ss-rules/set.uc @@ -0,0 +1,113 @@ +{% +let fs = require("fs"); + +let o_dst_bypass4_ = " + 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 +"; +let o_dst_bypass6_ = " + ::1/128 + ::/128 + ::ffff:0:0/96 + 64:ff9b:1::/48 + 100::/64 + fe80::/10 + 2001::/23 + fc00::/7 +"; +let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_; + +let set_suffix = { + "src_bypass": { + str: o_src_bypass, + }, + "src_forward": { + str: o_src_forward, + }, + "src_checkdst": { + str: o_src_checkdst, + }, + "dst_bypass": { + str: o_dst_bypass, + file: o_dst_bypass_file, + }, + "dst_bypass_": { + str: o_dst_bypass_, + }, + "dst_forward": { + str: o_dst_forward, + file: o_dst_forward_file, + }, + "dst_forward_rrst_": {}, +}; + +function set_name(suf, af) { + if (af == 4) { + return "ss_rules_"+suf; + } else { + return "ss_rules6_"+suf; + } +} + +function set_elements_parse(res, str, af) { + for (let addr in split(str, /[ \t\n]/)) { + addr = trim(addr); + if (!addr) continue; + if (af == 4 && index(addr, ":") != -1) continue; + if (af == 6 && index(addr, ":") == -1) continue; + push(res, addr); + } +} + +function set_elements(suf, af) { + let obj = set_suffix[suf]; + let res = []; + let addr; + + let str = obj["str"]; + if (str) { + set_elements_parse(res, str, af); + } + + let file = obj["file"]; + if (file) { + let fd = fs.open(file); + if (fd) { + str = fd.read("all"); + set_elements_parse(res, str, af); + } + } + + return res; +} +%} + +{% for (let suf in set_suffix): for (let af in [4, 6]): %} +set {{ set_name(suf, af) }} { + type ipv{{af}}_addr; + flags interval; +{% let elems = set_elements(suf, af); if (length(elems)): %} + elements = { +{% for (let i = 0; i < length(elems); i++): %} + {{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %} +{% endfor %} + } +{% endif %} +} +{% endfor; endfor %} diff --git a/net/shadowsocks-libev/files/ss-rules/ss-rules.uc b/net/shadowsocks-libev/files/ss-rules/ss-rules.uc new file mode 100644 index 000000000..f3955b2ef --- /dev/null +++ b/net/shadowsocks-libev/files/ss-rules/ss-rules.uc @@ -0,0 +1,8 @@ +{% + +include("set.uc"); +include("chain.uc", {proto: "tcp"}); +include("chain.uc", {proto: "udp"}); + +%} +