diff --git a/Makefile b/Makefile index 4ccbc20b85..0144b0c5ff 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ $(if $(findstring $(space),$(TOPDIR)),$(error ERROR: The path to the OpenWrt dir world: -DISTRO_PKG_CONFIG:=$(shell which -a pkg-config | grep -E '\/usr' | head -n 1) +DISTRO_PKG_CONFIG:=$(shell command -pv pkg-config | grep -E '\/usr' | head -n 1) export PATH:=$(TOPDIR)/staging_dir/host/bin:$(PATH) ifneq ($(OPENWRT_BUILD),1) @@ -64,7 +64,7 @@ dirclean: clean cacheclean: ifneq ($(CONFIG_CCACHE),) - rm -rf $(CCACHE_DIR) + $(STAGING_DIR_HOST)/bin/ccache -C endif ifndef DUMP_TARGET_DB diff --git a/include/cmake.mk b/include/cmake.mk index 96c4d7df34..de8022ca57 100644 --- a/include/cmake.mk +++ b/include/cmake.mk @@ -15,7 +15,7 @@ MAKE_PATH = $(firstword $(CMAKE_BINARY_SUBDIR) .) ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) cmake_tool=$(TOOLCHAIN_DIR)/bin/$(1) else - cmake_tool=$(shell which $(1)) + cmake_tool=$(shell command -v $(1)) endif ifeq ($(CONFIG_CCACHE),) diff --git a/include/prereq.mk b/include/prereq.mk index 83ac21242c..6d14140792 100644 --- a/include/prereq.mk +++ b/include/prereq.mk @@ -52,7 +52,7 @@ endef define RequireCommand define Require/$(1) - which $(1) + command -pv $(1) endef $$(eval $$(call Require,$(1),$(2))) @@ -106,7 +106,7 @@ define SetupHostCommand $(call QuoteHostCommand,$(11)) $(call QuoteHostCommand,$(12)); do \ if [ -n "$$$$$$$$cmd" ]; then \ bin="$$$$$$$$(PATH="$(subst $(space),:,$(filter-out $(STAGING_DIR_HOST)/%,$(subst :,$(space),$(PATH))))" \ - which "$$$$$$$${cmd%% *}")"; \ + command -pv "$$$$$$$${cmd%% *}")"; \ if [ -x "$$$$$$$$bin" ] && eval "$$$$$$$$cmd" >/dev/null 2>/dev/null; then \ mkdir -p "$(STAGING_DIR_HOST)/bin"; \ ln -sf "$$$$$$$$bin" "$(STAGING_DIR_HOST)/bin/$(strip $(1))"; \ diff --git a/include/toplevel.mk b/include/toplevel.mk index 4003b48241..23bae149d4 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -19,7 +19,6 @@ else SOURCE_DATE_EPOCH:=$(shell $(TOPDIR)/scripts/get_source_date_epoch.sh) endif -HOSTCC ?= $(CC) export REVISION export SOURCE_DATE_EPOCH export GIT_CONFIG_PARAMETERS='core.autocrlf=false' @@ -59,13 +58,6 @@ export PATH:=$(path) unexport TAR_OPTIONS -ifneq ($(shell $(HOSTCC) 2>&1 | grep clang),) - export HOSTCC_REAL?=$(HOSTCC) - export HOSTCC_WRAPPER:=$(TOPDIR)/scripts/clang-gcc-wrapper -else - export HOSTCC_WRAPPER:=$(HOSTCC) -endif - ifeq ($(FORCE),) .config scripts/config/conf scripts/config/mconf: staging_dir/host/.prereq-build endif @@ -115,7 +107,7 @@ endif scripts/config/%onf: CFLAGS+= -O2 scripts/config/%onf: @$(_SINGLE)$(SUBMAKE) $(if $(findstring s,$(OPENWRT_VERBOSE)),,-s) \ - -C scripts/config $(notdir $@) CC="$(HOSTCC_WRAPPER)" + -C scripts/config $(notdir $@) $(eval $(call rdep,scripts/config,scripts/config/mconf)) @@ -269,8 +261,8 @@ package/symlinks-clean: help: cat README.md -distclean: cacheclean - rm -rf bin build_dir .config* dl feeds key-build* logs package/feeds package/openwrt-packages staging_dir tmp +distclean: + rm -rf bin build_dir .ccache .config* dl feeds key-build* logs package/feeds package/openwrt-packages staging_dir tmp @$(_SINGLE)$(SUBMAKE) -C scripts/config clean ifeq ($(findstring v,$(DEBUG)),) diff --git a/package/ctcgfw/bpytop/Makefile b/package/ctcgfw/bpytop/Makefile index 2908832451..eae751164d 100644 --- a/package/ctcgfw/bpytop/Makefile +++ b/package/ctcgfw/bpytop/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bpytop -PKG_VERSION:=1.0.53 +PKG_VERSION:=1.0.54 PKG_RELEASE:=1 PYPI_NAME:=bpytop -PKG_HASH:=d08b8120444e7f35fe032b33495ca551b5890702130c45ad8a56c1fa978fc358 +PKG_HASH:=a25665e71627a5ec918e6ecf4422bea1ba449069958f64c3879029cfb58a0ac1 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE @@ -35,17 +35,11 @@ define Package/bpytop/description endef define Package/bpytop/install - $(call Py3Package/$(1)/install,$(1)) - $(call Py3Package/ProcessFilespec,$(1),$(PKG_INSTALL_DIR),$(1)) - $(FIND) $(1) -name '*.exe' -delete - $(call Python3/CompileAll,$(1)) - $(call Python3/DeleteSourceFiles,$(1)) - $(call Python3/DeleteEmptyDirs,$(1)) - if [ -d "$(1)/usr/bin" ]; then \ - $(call Python3/FixShebang,$(1)/usr/bin/*) ; \ - fi - $(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/share/bpytop - $(CP) $(PKG_BUILD_DIR)/bpytop-themes/* $(PKG_INSTALL_DIR)/usr/share/bpytop/ + $(call Py3Package/$(1)/install,$(PKG_BUILD_DIR)) + $(INSTALL_DIR) $(1)/usr + $(CP) $(PKG_INSTALL_DIR)/usr/* $(1)/usr/ + $(INSTALL_DIR) $(1)/usr/share/bpytop + $(CP) $(PKG_BUILD_DIR)/bpytop-themes/* $(1)/usr/share/bpytop/ endef $(eval $(call Py3Package,bpytop)) diff --git a/package/ctcgfw/luci-app-openclash/Makefile b/package/ctcgfw/luci-app-openclash/Makefile index 25cbdb543a..99f26fa2c1 100644 --- a/package/ctcgfw/luci-app-openclash/Makefile +++ b/package/ctcgfw/luci-app-openclash/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-openclash -PKG_VERSION:=0.41.13 +PKG_VERSION:=0.41.14 PKG_RELEASE:=beta PKG_MAINTAINER:=vernesong diff --git a/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/groups-config.lua b/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/groups-config.lua index 062524445b..61c69a2bf2 100644 --- a/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/groups-config.lua +++ b/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/groups-config.lua @@ -52,7 +52,7 @@ end o = s:option(ListValue, "type", translate("Group Type")) o.rmempty = true o.description = translate("Choose The Operation Mode") -o:value("select", translate("Select")) +o:value("select", translate("Select ")) o:value("url-test", translate("URL-Test")) o:value("fallback", translate("Fallback")) o:value("load-balance", translate("Load-Balance")) diff --git a/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/other-rules-edit.lua b/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/other-rules-edit.lua index cf64d3c9b6..9e2f35fd98 100644 --- a/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/other-rules-edit.lua +++ b/package/ctcgfw/luci-app-openclash/luasrc/model/cbi/openclash/other-rules-edit.lua @@ -152,6 +152,17 @@ end o:value("DIRECT") o:value("REJECT") +o = s:option(ListValue, "Disney", translate("Disney")) +o:depends("rule_name", "lhie1") +o.rmempty = true +for groupname in string.gmatch(groupnames, "([^'##\n']+)##") do + if groupname ~= nil and groupname ~= "" then + o:value(groupname) + end +end +o:value("DIRECT") +o:value("REJECT") + o = s:option(ListValue, "Spotify", translate("Spotify")) o:depends("rule_name", "lhie1") o.rmempty = true diff --git a/package/ctcgfw/luci-app-openclash/po/zh-cn/openclash.zh-cn.po b/package/ctcgfw/luci-app-openclash/po/zh-cn/openclash.zh-cn.po index a0ee35c7c5..0fb33bd8b3 100644 --- a/package/ctcgfw/luci-app-openclash/po/zh-cn/openclash.zh-cn.po +++ b/package/ctcgfw/luci-app-openclash/po/zh-cn/openclash.zh-cn.po @@ -490,6 +490,9 @@ msgstr "微软服务流量" msgid "Netflix" msgstr "Netflix流量" +msgid "Disney" +msgstr "Disney流量" + msgid "Spotify" msgstr "Spotify流量" @@ -783,7 +786,7 @@ msgstr "检测频率(秒)" msgid "Tolerance(ms)" msgstr "节点切换容忍值(毫秒)" -msgid "Select" +msgid "Select " msgstr "Select【手动选择】" msgid "URL-Test" diff --git a/package/ctcgfw/luci-app-openclash/root/etc/init.d/openclash b/package/ctcgfw/luci-app-openclash/root/etc/init.d/openclash old mode 100644 new mode 100755 index 4d790de579..01cca803da --- a/package/ctcgfw/luci-app-openclash/root/etc/init.d/openclash +++ b/package/ctcgfw/luci-app-openclash/root/etc/init.d/openclash @@ -1197,17 +1197,18 @@ firewall_redirect_exclude() set_firewall() { -if [ "$(iptables -t nat -nL PREROUTING --line-number |grep "udp dpt:53" |grep "0.0.0.0/0 \{0,\}0.0.0.0/0" |wc -l)" -gt 1 ] && [ "$enable_redirect_dns" -eq 1 ]; then + +if [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(iptables -t nat -nL PREROUTING --line-number |grep "redir ports 53$")"]; then + iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 + iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 +fi + +if [ "$(iptables -t nat -nL PREROUTING --line-number |grep "redir ports 53" |wc -l)" -gt 2 ] && [ "$enable_redirect_dns" -eq 1 ]; then echo "发现53端口被劫持,清理防火墙规则..." >$START_LOG - pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/0.0.0.0\/0 \{0,\}0.0.0.0\/0 \{0,\}udp dpt:53/=' 2>/dev/null |sort -rn) + pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/redir ports 53/=' 2>/dev/null |sort -rn) for pre_line in $pre_lines; do iptables -t nat -D PREROUTING "$pre_line" >/dev/null 2>&1 done - iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 >/dev/null 2>&1 - sleep 2 -elif [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(iptables -t nat -nL PREROUTING --line-number |grep "redir ports 53$")"]; then - iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 - iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 fi if [ -z "$(uci get firewall.openclash 2>/dev/null)" ] || [ -z "$(uci get ucitrack.@openclash[-1].init 2>/dev/null)" ]; then @@ -1313,12 +1314,11 @@ if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 3 ]; then iptables -t nat -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1 fi iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port" - if [ -z "$en_mode_tun" ]; then - iptables -t nat -I PREROUTING -p tcp -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports "$proxy_port" - iptables -t nat -I PREROUTING -p tcp -d 8.8.4.4 --dport 53 -j REDIRECT --to-ports "$proxy_port" - fi iptables -t nat -A PREROUTING -p tcp -j openclash if [ -z "$en_mode_tun" ]; then + #Google dns + iptables -t nat -I PREROUTING -p tcp -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports "$proxy_port" + iptables -t nat -I PREROUTING -p tcp -d 8.8.4.4 --dport 53 -j REDIRECT --to-ports "$proxy_port" #udp if [ "$enable_udp_proxy" -eq 1 ]; then modprobe xt_TPROXY >/dev/null 2>&1 @@ -1754,6 +1754,8 @@ reload() do_run_mode 2>/dev/null get_config 2>/dev/null set_firewall 2>/dev/null + /etc/init.d/dnsmasq restart >/dev/null 2>&1 echo "${LOGTIME} Reload OpenClash Firewall Rules" >> $LOG_FILE + echo "" >$START_LOG fi } diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_get.sh b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_get.sh index 6e8a840dbd..861addc6fb 100755 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_get.sh +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_get.sh @@ -14,6 +14,12 @@ PORT=$(uci get openclash.config.cn_port 2>/dev/null) LOG_FILE="/tmp/openclash.log" LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") +if [ -z "$CONFIG_FILE" ] || [ ! -f "$CONFIG_FILE" ]; then + CONFIG_FILE=$(uci get openclash.config.config_path 2>/dev/null) + CONFIG_NAME=$(echo "$CONFIG_FILE" |awk -F '/' '{print $5}' 2>/dev/null) + HISTORY_PATH="/etc/openclash/history/$CONFIG_NAME" +fi + if [ -n "$(pidof clash)" ] && [ -f "$CONFIG_FILE" ]; then curl -m 5 --retry 2 -w %{http_code}"\n" -H "Authorization: Bearer ${SECRET}" -H "Content-Type:application/json" -X GET http://"$LAN_IP":"$PORT"/proxies > "$CURL_CACHE" 2>/dev/null if [ "$(sed -n '$p' "$CURL_CACHE" 2>/dev/null)" = "200" ]; then diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_set.sh b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_set.sh index c98c754c2f..b3aebddd4a 100755 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_set.sh +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_history_set.sh @@ -43,6 +43,12 @@ close_all_conection() { curl -m 5 --retry 2 -H "Authorization: Bearer ${SECRET}" -H "Content-Type:application/json" -X DELETE http://"$LAN_IP":"$PORT"/connections >/dev/null 2>&1 } +if [ -z "$CONFIG_FILE" ] || [ ! -f "$CONFIG_FILE" ]; then + CONFIG_FILE=$(uci get openclash.config.config_path 2>/dev/null) + CONFIG_NAME=$(echo "$CONFIG_FILE" |awk -F '/' '{print $5}' 2>/dev/null) + HISTORY_PATH="/etc/openclash/history/$CONFIG_NAME" +fi + if [ -s "$HISTORY_PATH" ] && [ ! -z "$(pidof clash)" ]; then cat "$HISTORY_PATH" |while read -r line do diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_watchdog.sh b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_watchdog.sh index 77308d0b63..56df60e4a9 100755 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_watchdog.sh +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/openclash_watchdog.sh @@ -85,7 +85,10 @@ fi last_line=$(iptables -t nat -nL PREROUTING --line-number |awk '{print $1}' 2>/dev/null |awk 'END {print}' |sed -n '$p') op_line=$(iptables -t nat -nL PREROUTING --line-number |grep "openclash" 2>/dev/null |awk '{print $1}' 2>/dev/null |head -1) if [ "$last_line" != "$op_line" ] && [ -z "$core_type" ]; then - iptables -t nat -D PREROUTING -p tcp -j openclash + pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/openclash/=' 2>/dev/null |sort -rn) + for pre_line in $pre_lines; do + iptables -t nat -D PREROUTING "$pre_line" >/dev/null 2>&1 + done >/dev/null 2>&1 iptables -t nat -A PREROUTING -p tcp -j openclash echo "$LOGTIME Watchdog: Reset Firewall For Enabling Redirect." >>$LOG_FILE fi diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/lhie1.yaml b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/lhie1.yaml index b63075d868..a7ee21f734 100644 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/lhie1.yaml +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/lhie1.yaml @@ -4,12 +4,14 @@ rules: - RULE-SET,Netflix,Netflix - RULE-SET,Spotify,Spotify - RULE-SET,YouTube,YouTube +- RULE-SET,Disney Plus,Disney - RULE-SET,Bilibili,AsianTV - RULE-SET,iQiyi,AsianTV - RULE-SET,Letv,AsianTV - RULE-SET,Netease Music,AsianTV - RULE-SET,Tencent Video,AsianTV - RULE-SET,Youku,AsianTV +- RULE-SET,WeTV,AsianTV - RULE-SET,ABC,GlobalTV - RULE-SET,Abema TV,GlobalTV - RULE-SET,Amazon,GlobalTV @@ -18,7 +20,7 @@ rules: - RULE-SET,Bahamut,GlobalTV - RULE-SET,BBC iPlayer,GlobalTV - RULE-SET,DAZN,GlobalTV -- RULE-SET,Disney Plus,GlobalTV +- RULE-SET,Discovery Plus,GlobalTV - RULE-SET,encoreTVB,GlobalTV - RULE-SET,Fox Now,GlobalTV - RULE-SET,Fox+,GlobalTV @@ -57,12 +59,14 @@ script: "Netflix": "Netflix", "Spotify": "Spotify", "YouTube": "YouTube", + "Disney Plus": "Disney", "Bilibili": "AsianTV", "iQiyi": "AsianTV", "Letv": "AsianTV", "Netease Music": "AsianTV", "Tencent Video": "AsianTV", "Youku": "AsianTV", + "WeTV": "AsianTV", "ABC": "GlobalTV", "Abema TV": "GlobalTV", "Amazon": "GlobalTV", @@ -71,7 +75,7 @@ script: "Bahamut": "GlobalTV", "BBC iPlayer": "GlobalTV", "DAZN": "GlobalTV", - "Disney Plus": "GlobalTV", + "Discovery Plus": "GlobalTV", "encoreTVB": "GlobalTV", "Fox Now": "GlobalTV", "Fox+": "GlobalTV", @@ -187,6 +191,12 @@ rule-providers: url: https://cdn.jsdelivr.net/gh/lhie1/Rules@master/Clash/Provider/Media/Youku.yaml path: "./Rules/Media/Youku" interval: 86400 + WeTV: + type: http + behavior: classical + url: https://cdn.jsdelivr.net/gh/lhie1/Rules@master/Clash/Provider/Media/WeTV.yaml + path: "./Rules/Media/WeTV" + interval: 86400 ABC: type: http behavior: classical @@ -235,6 +245,12 @@ rule-providers: url: https://cdn.jsdelivr.net/gh/lhie1/Rules@master/Clash/Provider/Media/DAZN.yaml path: "./Rules/Media/DAZN" interval: 86400 + Discovery Plus: + type: http + behavior: classical + url: https://cdn.jsdelivr.net/gh/lhie1/Rules@master/Clash/Provider/Media/Discovery%20Plus.yaml + path: "./Rules/Media/Discovery_Plus" + interval: 86400 Disney Plus: type: http behavior: classical diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/openclash_version b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/openclash_version index 291c2a415d..3ce5b71ede 100644 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/openclash_version +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/res/openclash_version @@ -1,2 +1,2 @@ -v0.41.13-beta -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYQAAAAqCAMAAACEAtzLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFDMzkyQ0RDNDQ1MTExRUI4NjdBQTY3QjFBMTczMkI4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFDMzkyQ0RENDQ1MTExRUI4NjdBQTY3QjFBMTczMkI4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QUMzOTJDREE0NDUxMTFFQjg2N0FBNjdCMUExNzMyQjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QUMzOTJDREI0NDUxMTFFQjg2N0FBNjdCMUExNzMyQjgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5OAPH3AAADAFBMVEWxytlISEgFXI5kq9OlpaWKiorh7/cihLw6lspJns6Gv98Fbakqjcbv9PcGXpGUxeEccaLR0dFjlbE9PT3R4uuenp6CgoLR5vJFgaIGVYLe3t61tbUVapo/Pz8GZp1ubm4Jca0GcKza2trn5+fOzs6StclFmsqRkZFFRUVLS0s1dZobhcFycnIkapKCrsd3d3eFhYUkeqoEU4CcnJwHVoRiYmJjnLy/v782kcasrKx4eHhWlrpFkb1YpdJ1tNmhoaHg4OBDQ0OizOVBQUEFZZsKdbOixtqy0eOUlJTCwsIIXIsKaqAFYJRqamq6urrIyMgEWYmz1urFxcUXYYxAQEAXgLzAwMA0fKYFaaK2trbKysoJYZMIZJjw9PcgdaZlZWVgYGCiwNLB2eekzubR3+gYbZ4JbaaDq8JUi6sJaJ50p8QFcrCNjY0GbKU1hrRIi7IHdLFkp81zn7kJWIWCqsAEYpivr690dHRHnMwFa6WJweKiv9GTvtZ0sdUmbphnrtYnisIJb6oBcrNZWVlTU1NRUVFUVFRVVVULfL0Ke7xSUlIFdrcHeLlWVlYDdbUOf8AEdrYDdLQDdLUEdbYOgMASg8MSg8QShMQThMUAcrIGd7hXV1cOf78Nfr8Nfr4Mfb4Mfb0Je7sJersIeboIebkJero6OjqqqqrV1dXU1NSrq6vC3u6pqanw9/s7OzuAgIB+fn719fWBgYGEvN2Evd3q6urB3u6DvNz09PTB1eDz8/OFvt5MTEyCss5/f3+CqcAIV4XB3e3B3e7g6vDC3++Fvd6EtNDo6OjA1N/g6u9Gm8vC3u+Fvd2Xl5cJeLjW1tZHm8xEmcpVos+Dr8iEq8IUXomCu9s3k8jB2+rC1eFEf6Gjo6PD3++DudcFdLSDsMmixNfB1+O4uLgwk8smh70vksvB1+QFZ5+RuM/C3OsKebkHd7ZGibCEscwmcZwCc7QRgsMPgMEQgcJaWlpfX19NTU1eXl5cXFxbW1tPT09QUFBYWFhdXV1OTk7///////90ZaeHAAABAHRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AU/cHJQAAC+FJREFUeNrsVwtYVGUaPoOAgDYI0ww3CVDEGS+ALKRSCiNYInlbo0DxkpphVGua3bay1hEZZHZrt70UXRbF4TrlKCAXC9Tymna/b2Wbu+1u7T0tNV72v5wz55yZwXi2nqdmHt/n4fzf9363//zvzDmD0N/vvHPCF/6ASb/zQXxyr6O/X+jP9Q8JiAi/9Ul8EtUvOCec8RNM+o1v4hOHcOcZvxHh1z6Ke4UJX/sLJv3LR/En4euLInzv8CcR/uOrEL70G1wU4QeApf/2VQhf+Q0uivBDEOFRX4XwX7/B0l/4KryKYJg6deotCd/9MS0zGJa5nASDYTA12YbswYrwxEB4dPjGsLBQ76GQ0OGyFxriNUlJh4aF3TttvHtGGMKe+P8hbHJHVokTDLnHszZ9SximGlS+E8dddgEWDabFy3h5kMOWPjkQwtn9BId4CU0DwlxOKP7grVxBr+RH4whzSwlD2IDTQ8NCn7wwPETIbgNGNen1yWSW4duKMBVTla5tMnJdWgNjv2MRnhoA3Vhy80+uuBqO8R6hEAfQLdrDNzrwgme1igYOjHljzAG5yDWi+6mBxw8c4xDOq5GVi64EHYVJ32U4/y1BRFD5CUCCaB5HV9VgWhh1xkEOW/q0dwwHxq0neBcrPUIOLEE3t9lH/AWPajX9bjTttF5AsDqrW+riBReKcQgex9aVpTNrTCajTmebM9jDTjOo9DIYEryLoBmNHNFsQEmft1pJLqmHLEKWwZCl/LioXSLC773iqekQ1q+emVgaDYdbaHwUIjvRzZ3uDz7qxAse5Wp6/frZawrXzI4G3LJol+GhIYreoaHDFTERoaHKHAnuIjihj9/MLJuJGg3YxbxdaBCvx3OBpvNNaMpqIk8uGm2iLxFnE8sDspjbkMUcDlf3zXq0yd8Jm7pWbn7ekEvLnNeRJk3gjdMaKNWQJmYmXEfdEuXWRzxdyTEeGM6tlQivrFyAN2ZSZzEQUqnCMdzQ+2d0c6e3t/cNHKt0h5penMiGXIED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 \ No newline at end of file +v0.41.14-beta +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYQAAAAqCAMAAACEAtzLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkRDN0NGMEEzNEZERDExRUI4OTNBQjE5MDVENEVFMEQ1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkRDN0NGMEE0NEZERDExRUI4OTNBQjE5MDVENEVFMEQ1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6REM3Q0YwQTE0RkREMTFFQjg5M0FCMTkwNUQ0RUUwRDUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6REM3Q0YwQTI0RkREMTFFQjg5M0FCMTkwNUQ0RUUwRDUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4d4xgdAAADAFBMVEVjlbGStcojhbxJns7h7/cFaaKUxeEccaLR0dEFbak9PT3R4uuenp6CgoKxytnv9PcHX5EGVYLe3t7R5vKGvt+1tbUVapo/Pz9ubm5Ui6va2trn5+c1dZrOzs4GZp0GcKyRkZFjnL1GRkZLS0uCrsdycnJFgKIJca1Fmsp3d3eFhYVFj7okeqqcnJwHVoQFZZtiYmIkapK/v7+srKx4eHgEU4AqjMWhoaHg4OBDQ0OizOVBQUFYpdJ1tdmixtqLi4uy0eOUlJTCwsIbhcFqamrw9Pe6urrIyMgHXI5XlbkJaqDFxcVAQEAXgLzAwMA0fKYEWYm2trYIZJnKysoXYYyiwNE7l8sJbaUFYJTR3+gIXI0gdaYIYpVlZWVmrdUKdbNgYGCz1urB2ecYbZ6np6eDq8I4lMiNjY0FcrCCqsCkzuaTvtavr682kcYEYph0dHRHnMyJweJzn7l0sdUmb5lortcnicA1h7UBcrNZWVlTU1NRUVFUVFRVVVUFdrdSUlILfL0Ke7wHeLkGd7hWVlYEdbYOgMAOf8AEdrYDdLUDdbUDdLQSg8MSg8QShMQThMUAcrIOf79XV1cNfr8Nfr4Mfb4Mfb0JersJe7sJeroIeboIebk6OjqqqqrV1dXC3u7U1NSrq6tISEipqanB3u7w9/s7OzuAgIB+fn6Evd319fVJSUmBgYGEvN3B1eDq6uqFvt709PTz8/ODvNxMTEwEXI6Css5/f3+CqcAIV4SlpaXB3e3B3e4JeLiEtNCFvd6Fvd3o6OjC3u/C3++Xl5dkqtKJiYnA1N8JWIXW1taDu9zg6u9Hm8xEmcpGm8sHdbKEq8Isj8fB1+M3k8iDr8hVos+DsMkUXonB2+qixNejo6PD3++Fudfg6vDB1+QFdLREf6EGXY8IaJ85lcm4uLgwk8vC3OsFZ6AKebmAudkHd7aEscwIWId1qMXC1eECc7QRgsMPgMEQgcJaWlpfX19NTU1eXl5cXFxbW1tPT09QUFBYWFhdXV1OTk7///////8d0mXsAAABAHRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AU/cHJQAAC25JREFUeNrsVwtYVGUaPgIqTDPEVfBC2BmUiy6ggjCiGXgrNkrUNDWv1S5Z2r3WEYOhabf2WlSrxjBcp2BQJlBL8FKa2l272MV2241at61t72mp8bL/5VxnBuPZ9nlq5vF9Hs7/fe//vd//n/89M2cQ+vrcN4/5Ihgw/jcBiBO3ufr6hL784LCAmPDrgMSJ2D7BPeZUkGD8rwITJ1zCzaeCxoRfBihuE8Z8HSwY/88AxQnh6/MmfOcIJhP+HagQvgwanDfhe4Cl/wpUCF8FDc6b8H0w4aeBCuE/QYOlPwtU+DXBNGnSpB8n/v+PaZnJtExJEk2mgWhyTDkDNeHhfvHGXXFxof6nFoa+oSahC/3WeNM6DUMc4h7+3yGs90Z2qRsM+Qez139LmCaZdLkbB5W4CPMH0uIlvDTAxZY+0h+GsPsJW+hnaioQpySh+J0/uTet03DE+TAaeVzoI+eGjwk5HmBEg9GYRLZt+rYmTMIkbWqfiHzFa2D0/9mER/tBHGb9bdzll8I1w2dqoYscqBS/cZcLz/uqfWitRl0i7tH+l+9/jkM4q0d2PjoTDRRmY6fp7LcEMUGXJwKJUngQnRUDaSEaxAEutvQx/5gMjHqxq+vFv2ONz5QLsxDHY/Zped5H7UNrNQrifJiBzXEIPsfWmW2wtJnNosFgnznQw0436fwymRL9m9A4EnlS6ERprz+tbJfcQzUh22TK1j4u+pSY8Fv/mIbIFxetSJ03Fi6vmRmxENrxFE+e+v077XjeR+1N6zRqFWUmh36sqQsNnayZkxAaqq2R4W2CG8aEDSyym2ngxFaWbYVTuh7MBxrONqAhu4F8c9HZBvoScTewOiCbpc5slnAo3TcY4VE/E3a9Vm1+1pRPZe4rSZMG8MbpTko506XKxCtpWqrd+tDHKjlmAJN5tAZDKitX4fUVNIkCPq7U4QCu7voDnuJJV1fX6zhQ6Q1vWqdRQA56ahh970zl+ccH6PYO0PXkQyBkGAtc3uJKoVqHrUB1hZyU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 \ No newline at end of file diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_proxys_set.sh b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_proxys_set.sh index bcf9149b44..a2d76b39ea 100755 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_proxys_set.sh +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_proxys_set.sh @@ -813,6 +813,20 @@ cat >> "$SERVER_FILE" <<-EOF EOF fi cat /tmp/Proxy_Provider >> $SERVER_FILE 2>/dev/null +cat >> "$SERVER_FILE" <<-EOF + - name: Disney + type: select + proxies: + - GlobalTV + - DIRECT +EOF +cat /tmp/Proxy_Server >> $SERVER_FILE 2>/dev/null +if [ -f "/tmp/Proxy_Provider" ]; then +cat >> "$SERVER_FILE" <<-EOF + use: +EOF +fi +cat /tmp/Proxy_Provider >> $SERVER_FILE 2>/dev/null cat >> "$SERVER_FILE" <<-EOF - name: Youtube type: select @@ -947,6 +961,7 @@ ${uci_set}Youtube="Youtube" ${uci_set}Apple="Apple" ${uci_set}Microsoft="Microsoft" ${uci_set}Netflix="Netflix" +${uci_set}Disney="Disney" ${uci_set}Spotify="Spotify" ${uci_set}Steam="Steam" ${uci_set}AdBlock="AdBlock" @@ -964,6 +979,7 @@ ${uci_set}Others="Others" ${UCI_DEL_LIST}="AsianTV" >/dev/null 2>&1 && ${UCI_ADD_LIST}="AsianTV" >/dev/null 2>&1 ${UCI_DEL_LIST}="GlobalTV" >/dev/null 2>&1 && ${UCI_ADD_LIST}="GlobalTV" >/dev/null 2>&1 ${UCI_DEL_LIST}="Netflix" >/dev/null 2>&1 && ${UCI_ADD_LIST}="Netflix" >/dev/null 2>&1 + ${UCI_DEL_LIST}="Disney" >/dev/null 2>&1 && ${UCI_ADD_LIST}="Disney" >/dev/null 2>&1 ${UCI_DEL_LIST}="Spotify" >/dev/null 2>&1 && ${UCI_ADD_LIST}="Spotify" >/dev/null 2>&1 ${UCI_DEL_LIST}="Steam" >/dev/null 2>&1 && ${UCI_ADD_LIST}="Steam" >/dev/null 2>&1 ${UCI_DEL_LIST}="Telegram" >/dev/null 2>&1 && ${UCI_ADD_LIST}="Telegram" >/dev/null 2>&1 diff --git a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_rules_change.sh b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_rules_change.sh index 63d6715c0a..a6358fa7f3 100755 --- a/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_rules_change.sh +++ b/package/ctcgfw/luci-app-openclash/root/usr/share/openclash/yml_rules_change.sh @@ -137,6 +137,7 @@ yml_other_rules_get() config_get "Youtube" "$section" "Youtube" "" config_get "Apple" "$section" "Apple" "" config_get "Netflix" "$section" "Netflix" "" + config_get "Disney" "$section" "Disney" "" config_get "Spotify" "$section" "Spotify" "" config_get "Steam" "$section" "Steam" "" config_get "AdBlock" "$section" "AdBlock" "" @@ -180,6 +181,7 @@ if [ "$2" != "0" ]; then || [ -z "$(grep -F "$Youtube" /tmp/Proxy_Group)" ]\ || [ -z "$(grep -F "$Apple" /tmp/Proxy_Group)" ]\ || [ -z "$(grep -F "$Netflix" /tmp/Proxy_Group)" ]\ + || [ -z "$(grep -F "$Disney" /tmp/Proxy_Group)" ]\ || [ -z "$(grep -F "$Spotify" /tmp/Proxy_Group)" ]\ || [ -z "$(grep -F "$Steam" /tmp/Proxy_Group)" ]\ || [ -z "$(grep -F "$AdBlock" /tmp/Proxy_Group)" ]\ @@ -227,6 +229,7 @@ if [ "$2" != "0" ]; then .gsub(/,YouTube$/, ',$Youtube#d') .gsub(/,Apple$/, ',$Apple#d') .gsub(/,Netflix$/, ',$Netflix#d') + .gsub(/,Disney$/, ',$Disney#d') .gsub(/,Spotify$/, ',$Spotify#d') .gsub(/,Steam$/, ',$Steam#d') .gsub(/,AdBlock$/, ',$AdBlock#d') @@ -244,6 +247,7 @@ if [ "$2" != "0" ]; then .gsub!(/: \"YouTube\"/,': \"$Youtube#d\"') .gsub!(/: \"Apple\"/,': \"$Apple#d\"') .gsub!(/: \"Netflix\"/,': \"$Netflix#d\"') + .gsub!(/: \"Disney\"/,': \"$Disney#d\"') .gsub!(/: \"Spotify\"/,': \"$Spotify#d\"') .gsub!(/: \"Steam\"/,': \"$Steam#d\"') .gsub!(/: \"AdBlock\"/,': \"$AdBlock#d\"') diff --git a/package/ctcgfw/mt7601u-ap/Makefile b/package/ctcgfw/mt7601u-ap/Makefile new file mode 100644 index 0000000000..56fb9ae7ea --- /dev/null +++ b/package/ctcgfw/mt7601u-ap/Makefile @@ -0,0 +1,68 @@ +# +# Copyright (C) 2020 CTCGFW Project-OpenWrt +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mt7601u-ap +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2020-05-01 +PKG_SOURCE_URL:=https://github.com/Anthony96922/mt7601u-ap.git +PKG_SOURCE_VERSION:=624307427149e53b75937ccbe7cb235ec3ef2f58 +PKG_MIRROR_HASH:=70e8f7e94ddca09e1f55ef1b30a47fa7c504750ec654bc0c500f1a3d491eca97 + +PKG_MAINTAINER:=[CTCGFW] Project OpenWrt +PKG_BUILD_PARALLEL:=1 + +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/mt7601u-ap + SUBMENU:=Wireless Drivers + TITLE:=AP driver for MT7601U dongles + DEPENDS:=+kmod-usb-core +wireless-tools @USB_SUPPORT + FILES:=$(PKG_BUILD_DIR)/os/linux/mt7601Uap.ko + AUTOLOAD:=$(call AutoProbe,mt7601Uap) + CONFLICTS:=kmod-mt7601u +endef + +define KernelPackage/mt7601u-ap/description + AP driver for MT7601U chipset based adapters +endef + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(KERNEL_CROSS)" \ + LINUX_SRC="$(LINUX_DIR)" \ + RT28xx_DIR="$(PKG_BUILD_DIR)" \ + RT28xx_MODE=AP \ + CHIPSET=7601U \ + MODULE=7601U \ + OSABL=NO \ + +define Build/Prepare + $(Build/Prepare/Default) + $(CP) $(PKG_BUILD_DIR)/os/linux/Makefile.6 $(PKG_BUILD_DIR)/os/linux/Makefile +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + M="$(PKG_BUILD_DIR)/os/linux" \ + modules +endef + +define KernelPackage/mt7601u-ap/install + $(INSTALL_DIR) $(1)/etc/wifi/RT2870AP + $(INSTALL_DATA) $(PKG_BUILD_DIR)/RT2870AP.txt $(1)/etc/wifi/RT2870AP/ +endef + +$(eval $(call KernelPackage,mt7601u-ap)) diff --git a/package/libs/wolfssl/patches/120-enable-secret-callback.patch b/package/libs/wolfssl/patches/120-enable-secret-callback.patch new file mode 100644 index 0000000000..9c9b361d01 --- /dev/null +++ b/package/libs/wolfssl/patches/120-enable-secret-callback.patch @@ -0,0 +1,10 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -943,6 +943,7 @@ then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXT_CACHE" ++ AM_CFLAGS="$AM_CFLAGS -DHAVE_SECRET_CALLBACK" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_EITHER_SIDE" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_EXTRA_X509_SMALL" + diff --git a/package/lienol/luci-app-passwall/Makefile b/package/lienol/luci-app-passwall/Makefile index c57ca08c26..81094c77f3 100644 --- a/package/lienol/luci-app-passwall/Makefile +++ b/package/lienol/luci-app-passwall/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=4 -PKG_RELEASE:=4 -PKG_DATE:=20201221 +PKG_RELEASE:=6 +PKG_DATE:=20210104 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) @@ -136,10 +136,6 @@ define Package/$(PKG_NAME)/conffiles /usr/share/passwall/rules/direct_ip /usr/share/passwall/rules/proxy_host /usr/share/passwall/rules/proxy_ip -/usr/share/passwall/rules/proxy_host2 -/usr/share/passwall/rules/proxy_ip2 -/usr/share/passwall/rules/proxy_host3 -/usr/share/passwall/rules/proxy_ip3 endef define Package/$(PKG_NAME)/install diff --git a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua index 75b10d9424..e1375137f0 100644 --- a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua +++ b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua @@ -135,21 +135,13 @@ end function get_now_use_node() local e = {} - local tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1 - e.tcp = tonumber(tcp_node_num) - for i = 1, tcp_node_num, 1 do - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/TCP_" .. i) - if data then - e["TCP" .. i] = util.trim(data) - end + local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/TCP") + if data then + e["TCP"] = util.trim(data) end - local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1 - e.udp = tonumber(udp_node_num) - for i = 1, udp_node_num, 1 do - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/UDP_" .. i) - if data then - e["UDP" .. i] = util.trim(data) - end + local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/UDP") + if data then + e["UDP"] = util.trim(data) end luci.http.prepare_content("application/json") luci.http.write_json(e) @@ -158,8 +150,7 @@ end function get_redir_log() local proto = luci.http.formvalue("proto") proto = proto:upper() - local index = luci.http.formvalue("index") - local filename = proto .. "_" .. index + local filename = proto if nixio.fs.access("/var/etc/passwall/" .. filename .. ".log") then local content = luci.sys.exec("cat /var/etc/passwall/" .. filename .. ".log") content = content:gsub("\n", "
") @@ -183,19 +174,13 @@ function status() local e = {} e.dns_mode_status = luci.sys.call("netstat -apn | grep ':7913 ' >/dev/null") == 0 e.haproxy_status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0 - local tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1 - for i = 1, tcp_node_num, 1 do - e["kcptun_tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp_%s' >/dev/null", appname, i)) == 0 - e["tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP_%s' >/dev/null", appname, i)) == 0 - end + e["kcptun_tcp_node_status"] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp' >/dev/null", appname)) == 0 + e["tcp_node_status"] = luci.sys.call(string.format("ps -w | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP' >/dev/null", appname)) == 0 - local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1 - for i = 1, udp_node_num, 1 do - if (ucic:get(appname, "@global[0]", "udp_node" .. i) or "nil") == "tcp" then - e["udp_node%s_status" % i] = e["tcp_node%s_status" % i] - else - e["udp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep -i 'UDP_%s' >/dev/null", appname, i)) == 0 - end + if (ucic:get(appname, "@global[0]", "udp_node") or "nil") == "tcp" then + e["udp_node_status"] = e["tcp_node_status"] + else + e["udp_node_status"] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep -i 'UDP' >/dev/null", appname)) == 0 end luci.http.prepare_content("application/json") luci.http.write_json(e) @@ -255,9 +240,8 @@ end function set_node() local protocol = luci.http.formvalue("protocol") - local number = luci.http.formvalue("number") local section = luci.http.formvalue("section") - ucic:set(appname, "@global[0]", protocol .. "_node" .. number, section) + ucic:set(appname, "@global[0]", protocol .. "_node", section) ucic:commit(appname) luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &") luci.http.redirect(luci.dispatcher.build_url("admin", "services", appname, "log")) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua index 7759a0a7c0..63d823a3ab 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua @@ -155,6 +155,7 @@ function gen_outbound(node, tag, relay_port) address = node.address, port = tonumber(node.port), method = node.method or nil, + flow = node.flow or nil, password = node.password or "", users = (node.username and node.password) and {{user = node.username, pass = node.password}} or nil diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua index 78fc29f06c..d700d457d2 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua @@ -40,20 +40,6 @@ o = s:option(Value, "mac", translate("MAC")) o.rmempty = true sys.net.mac_hints(function(e, t) o:value(e, "%s (%s)" % {e, t}) end) ----- TCP Node -local tcp_node_num = m:get("@global_other[0]", "tcp_node_num") or 1 -if tonumber(tcp_node_num) > 1 then - o = s:option(ListValue, "tcp_node", translate("TCP Node")) - for i = 1, tcp_node_num, 1 do o:value(i, "TCP_" .. i) end -end - ----- UDP Node -local udp_node_num = m:get("@global_other[0]", "udp_node_num") or 1 -if tonumber(udp_node_num) > 1 then - o = s:option(ListValue, "udp_node", translate("UDP Node")) - for i = 1, udp_node_num, 1 do o:value(i, "UDP_" .. i) end -end - ---- TCP Proxy Mode o = s:option(ListValue, "tcp_proxy_mode", "TCP" .. translate("Proxy Mode")) o.default = "default" diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua index e9baecd5ec..e17aa025d8 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua @@ -25,22 +25,16 @@ o.rmempty = false o = s:option(Value, "testing_time", translate("How often is a diagnosis made"), translate("Units:minutes")) o.default = "3" ----- TCP Node --- local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) --- 暂时只支持TCP1 -local tcp_node_num = 1 -for i = 1, tcp_node_num, 1 do - o = s:option(ListValue, "tcp_main" .. i, "TCP " .. i .. " " .. translate("Main node")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - end +o = s:option(ListValue, "tcp_main", "TCP " .. translate("Main node")) +for k, v in pairs(nodes_table) do + o:value(v.id, v.remarks) +end - o = s:option(DynamicList, "tcp_node" .. i, "TCP " .. i .. " " .. translate("List of backup nodes")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - end - - o = s:option(Flag, "restore_switch" .. i, "TCP " .. i .. " " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) +o = s:option(DynamicList, "tcp_node", "TCP " .. translate("List of backup nodes")) +for k, v in pairs(nodes_table) do + o:value(v.id, v.remarks) end +o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) + return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 27990677d6..24236c0d61 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -74,62 +74,51 @@ o = s:taboption("Main", Flag, "enabled", translate("Main switch")) o.rmempty = false ---- TCP Node -local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) -for i = 1, tcp_node_num, 1 do - o = s:taboption("Main", ListValue, "tcp_node" .. i, translate("TCP Node") .. " " .. i) - if i == 1 then - o.title = translate("TCP Node") - o.description = "" - --o.description = translate("For proxy specific list.") - --o.description = o.description .. "
" - local current_node = luci.sys.exec(string.format("[ -f '/var/etc/%s/id/TCP_%s' ] && echo -n $(cat /var/etc/%s/id/TCP_%s)", appname, i, appname, i)) - if current_node and current_node ~= "" and current_node ~= "nil" then - local n = uci:get_all(appname, current_node) - if n then - if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then - local remarks = api.get_full_node_remarks(n) - local url = d.build_url("admin", "services", appname, "node_config", current_node) - o.description = o.description .. translatef("Current node: %s", string.format('%s', url, remarks)) .. "
" - end - if n.protocol and n.protocol == "_shunt" then - uci:foreach(appname, "shunt_rules", function(e) - local id = e[".name"] - local remarks = translate(e.remarks) - if n[id] and n[id] ~= "nil" then - local url = d.build_url("admin", "services", appname, "node_config", n[id]) - local r = api.get_full_node_remarks(uci:get_all(appname, n[id])) - o.description = o.description .. remarks .. ":" .. string.format('%s', url, r) .. "
" - end - end) - local id = "default_node" - local remarks = translate("Default") - if n[id] and n[id] ~= "nil" then - local url = d.build_url("admin", "services", appname, "node_config", n[id]) - local r = api.get_full_node_remarks(uci:get_all(appname, n[id])) - o.description = o.description .. remarks .. ":" .. string.format('%s', url, r) .. "
" - end +o = s:taboption("Main", ListValue, "tcp_node", translate("TCP Node")) +o.title = translate("TCP Node") +o.description = "" +--o.description = translate("For proxy specific list.") +--o.description = o.description .. "
" +local current_node = luci.sys.exec(string.format("[ -f '/var/etc/%s/id/TCP' ] && echo -n $(cat /var/etc/%s/id/TCP)", appname, appname)) +if current_node and current_node ~= "" and current_node ~= "nil" then + local n = uci:get_all(appname, current_node) + if n then + if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then + local remarks = api.get_full_node_remarks(n) + local url = d.build_url("admin", "services", appname, "node_config", current_node) + o.description = o.description .. translatef("Current node: %s", string.format('%s', url, remarks)) .. "
" + end + if n.protocol and n.protocol == "_shunt" then + uci:foreach(appname, "shunt_rules", function(e) + local id = e[".name"] + local remarks = translate(e.remarks) + if n[id] and n[id] ~= "nil" then + local url = d.build_url("admin", "services", appname, "node_config", n[id]) + local r = api.get_full_node_remarks(uci:get_all(appname, n[id])) + o.description = o.description .. remarks .. ":" .. string.format('%s', url, r) .. "
" end + end) + local id = "default_node" + local remarks = translate("Default") + if n[id] and n[id] ~= "nil" then + local url = d.build_url("admin", "services", appname, "node_config", n[id]) + local r = api.get_full_node_remarks(uci:get_all(appname, n[id])) + o.description = o.description .. remarks .. ":" .. string.format('%s', url, r) .. "
" end end end - o:value("nil", translate("Close")) - for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end end +o:value("nil", translate("Close")) +for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end ----- UDP Node -local udp_node_num = tonumber(m:get("@global_other[0]", "udp_node_num") or 1) -for i = 1, udp_node_num, 1 do - o = s:taboption("Main", ListValue, "udp_node" .. i, translate("UDP Node") .. " " .. i) - o:value("nil", translate("Close")) - if i == 1 then - o.title = translate("UDP Node") - --o.description = translate("For proxy game network, DNS hijack etc.") .. "
" .. translate("The selected server will not use Kcptun.") - o:value("tcp_", translate("Same as the tcp node")) - --o:value("tcp", translate("Same as the tcp node")) - --o:value("tcp_", translate("Same as the tcp node") .. "(" .. translate("New process") .. ")") - end - for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end -end +o = s:taboption("Main", ListValue, "udp_node", translate("UDP Node")) +o:value("nil", translate("Close")) +o.title = translate("UDP Node") +--o.description = translate("For proxy game network, DNS hijack etc.") .. "
" .. translate("The selected server will not use Kcptun.") +o:value("tcp_", translate("Same as the tcp node")) +--o:value("tcp", translate("Same as the tcp node")) +--o:value("tcp_", translate("Same as the tcp node") .. "(" .. translate("New process") .. ")") +for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end s:tab("DNS", translate("DNS")) @@ -306,14 +295,12 @@ o.default = "default" o.rmempty = false s:tab("log", translate("Log")) -for i = 1, tcp_node_num, 1 do - o = s:taboption("log", Flag, "close_log_tcp_" .. i , translate("Close") .. translate("Log") .. " " .. translate("TCP Node") .. " " .. i) - o.rmempty = false -end -for i = 1, udp_node_num, 1 do - o = s:taboption("log", Flag, "close_log_udp_" .. i, translate("Close") .. translate("Log") .. " " .. translate("UDP Node") .. " " .. i) - o.rmempty = false -end +o = s:taboption("log", Flag, "close_log_tcp", translate("Close") .. translate("Log") .. " " .. translate("TCP Node")) +o.rmempty = false + +o = s:taboption("log", Flag, "close_log_udp", translate("Close") .. translate("Log") .. " " .. translate("UDP Node")) +o.rmempty = false + loglevel = s:taboption("log", ListValue, "loglevel", "X/V2ray" .. translate("Log Level")) loglevel.default = "warning" loglevel:value("debug") @@ -355,10 +342,7 @@ o.default = 1 o.rmempty = false o = s:option(ListValue, "node", translate("Socks Node")) -local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) -for i = 1, tcp_node_num, 1 do - o:value("tcp" .. i, translatef("Same as the tcp %s node", i)) -end +o:value("tcp", translate("Same as the tcp node")) for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end o = s:option(Value, "port", "Socks" .. translate("Listen Port")) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua index 02c785f935..f11d3f3cf1 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua @@ -454,8 +454,10 @@ tls:depends("type", "Trojan-Go") xtls = s:option(Flag, "xtls", translate("XTLS")) xtls.default = 0 xtls:depends({ type = "Xray", protocol = "vless", tls = "1" }) +xtls:depends({ type = "Xray", protocol = "trojan", tls = "1" }) flow = s:option(Value, "flow", translate("flow")) +flow.default = "xtls-rprx-direct" flow:value("xtls-rprx-origin") flow:value("xtls-rprx-origin-udp443") flow:value("xtls-rprx-direct") diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua index e9eddc103b..d7efef2c21 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua @@ -121,29 +121,10 @@ o.rmempty = true --]] -- [[ Other Settings ]]-- -s = m:section(TypedSection, "global_other", translate("Other Settings"), - "" .. translatef( - "You can only set up a maximum of %s nodes for the time being, Used for access control.", - "3") .. "") +s = m:section(TypedSection, "global_other", translate("Other Settings")) s.anonymous = true s.addremove = false ----- TCP Node Number Option -o = s:option(ListValue, "tcp_node_num", "TCP" .. translate("Node Number")) -o.default = "1" -o.rmempty = false -o:value("1") -o:value("2") -o:value("3") - ----- UDP Node Number Option -o = s:option(ListValue, "udp_node_num", "UDP" .. translate("Node Number")) -o.default = "1" -o.rmempty = false -o:value("1") -o:value("2") -o:value("3") - o = s:option(MultiValue, "status", translate("Status info")) o:value("big_icon", translate("Big icon")) -- 大图标 o:value("show_check_port", translate("Show node check")) -- 显示节点检测 diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua index bf95912e54..d6bb806ea9 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua @@ -17,7 +17,7 @@ s:tab("proxy_list3", translate("Proxy List") .. " 3") ---- Direct Hosts local direct_host = string.format("/usr/share/%s/rules/direct_host", appname) -o = s:taboption("direct_list", TextValue, "direct_hosts", "", "" .. translate("Join the direct hosts list of domain names will not proxy.") .. "") +o = s:taboption("direct_list", TextValue, "direct_host", "", "" .. translate("Join the direct hosts list of domain names will not proxy.") .. "") o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) return fs.readfile(direct_host) or "" end @@ -91,80 +91,4 @@ o.validate = function(self, value) return value end ----- Proxy Hosts 2 -local proxy_host2 = string.format("/usr/share/%s/rules/proxy_host2", appname) -o = s:taboption("proxy_list2", TextValue, "proxy_host2", "", "" .. translate("These had been joined websites will use proxy. Please input the domain names of websites,every line can input only one website domain. For example: google.com.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_host2) or "" end -o.write = function(self, section, value) fs.writefile(proxy_host2, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_host2, "") end -o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - ----- Proxy IP 2 -local proxy_ip2 = string.format("/usr/share/%s/rules/proxy_ip2", appname) -o = s:taboption("proxy_list2", TextValue, "blacklist_ip2", "", "" .. translate("These had been joined ip addresses will use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example: 35.24.0.0/24 or 8.8.4.4.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_ip2) or "" end -o.write = function(self, section, value) fs.writefile(proxy_ip2, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_ip2, "") end -o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if not datatypes.ipmask4(ipmask) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Proxy Hosts 3 -local proxy_host3 = string.format("/usr/share/%s/rules/proxy_host3", appname) -o = s:taboption("proxy_list3", TextValue, "proxy_host3", "", "" .. translate("These had been joined websites will use proxy. Please input the domain names of websites,every line can input only one website domain. For example: google.com.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_host3) or "" end -o.write = function(self, section, value) fs.writefile(proxy_host3, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_host3, "") end -o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - ----- Proxy IP 3 -local proxy_ip3 = string.format("/usr/share/%s/rules/proxy_ip3", appname) -o = s:taboption("proxy_list3", TextValue, "blacklist_ip3", "", "" .. translate("These had been joined ip addresses will use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example: 35.24.0.0/24 or 8.8.4.4.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_ip3) or "" end -o.write = function(self, section, value) fs.writefile(proxy_ip3, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_ip3, "") end -o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if not datatypes.ipmask4(ipmask) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua index 4d38285ebf..9c155db14f 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua @@ -58,6 +58,7 @@ function gen_config(user) local clients = {} for i = 1, #user.uuid do clients[i] = { + flow = (user.xtls and user.xtls == "1") and user.flow or nil, password = user.uuid[i], level = tonumber(user.level) } @@ -77,6 +78,31 @@ function gen_config(user) } end + if user.fallback and user.fallback == "1" then + local fallbacks = {} + for i = 1, #user.fallback_list do + local fallbackStr = user.fallback_list[i] + if fallbackStr then + local tmp = {} + string.gsub(fallbackStr, '[^' .. "," .. ']+', function(w) + table.insert(tmp, w) + end) + local dest = tmp[1] or "" + local path = tmp[2] + if dest:find("%.") then + else + dest = tonumber(dest) + end + fallbacks[i] = { + path = path, + dest = dest, + xver = 1 + } + end + end + settings.fallbacks = fallbacks + end + routing = { domainStrategy = "IPOnDemand", rules = { @@ -110,7 +136,7 @@ function gen_config(user) network = user.transport, security = "none", xtlsSettings = (user.tls and user.tls == "1" and user.xtls and user.xtls == "1") and { - --alpn = {"http/1.1"}, + alpn = {"http/1.1"}, disableSystemRoot = false, certificates = { { @@ -120,6 +146,7 @@ function gen_config(user) } } or nil, tlsSettings = (user.tls and user.tls == "1") and { + alpn = {"http/1.1"}, disableSystemRoot = false, certificates = { { @@ -151,7 +178,7 @@ function gen_config(user) header = {type = user.mkcp_guise} } or nil, wsSettings = (user.transport == "ws") and { - acceptProxyProtocol = false, + acceptProxyProtocol = true, headers = (user.ws_host) and {Host = user.ws_host} or nil, path = user.ws_path } or nil, diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua index 8d9c6212e8..2efd15eb86 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua @@ -297,6 +297,7 @@ tls:depends({ type = "Xray", protocol = "vmess" }) tls:depends({ type = "Xray", protocol = "vless" }) tls:depends({ type = "Xray", protocol = "socks" }) tls:depends({ type = "Xray", protocol = "shadowsocks" }) +tls:depends({ type = "Xray", protocol = "trojan" }) tls:depends({ type = "V2ray", protocol = "vmess" }) tls:depends({ type = "V2ray", protocol = "vless" }) tls:depends({ type = "V2ray", protocol = "socks" }) @@ -308,15 +309,14 @@ tls:depends("type", "Trojan-Go") xtls = s:option(Flag, "xtls", translate("XTLS")) xtls.default = 0 xtls:depends({ type = "Xray", protocol = "vless", tls = "1" }) +xtls:depends({ type = "Xray", protocol = "trojan", tls = "1" }) flow = s:option(Value, "flow", translate("flow")) -flow.default = "xtls-rprx-origin" +flow.default = "xtls-rprx-direct" flow:value("xtls-rprx-origin") flow:value("xtls-rprx-origin-udp443") flow:value("xtls-rprx-direct") flow:value("xtls-rprx-direct-udp443") -flow:value("xtls-rprx-splice") -flow:value("xtls-rprx-splice-udp443") flow:depends("xtls", "1") -- [[ TLS部分 ]] -- @@ -330,7 +330,7 @@ tls_allowInsecure:depends({ type = "Trojan-Go", tls = "1" }) tls_serverName = s:option(Value, "tls_serverName", translate("Domain")) tls_serverName:depends("tls", "1") -tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") +tls_certificateFile = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") tls_certificateFile.validate = function(self, value, t) if value and value ~= "" then if not nixio.fs.access(value) then @@ -341,9 +341,10 @@ tls_certificateFile.validate = function(self, value, t) end return nil end +tls_certificateFile.default = "/etc/config/ssl/" .. arg[1] .. ".pem" tls_certificateFile:depends("tls", "1") -tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") +tls_keyFile = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") tls_keyFile.validate = function(self, value, t) if value and value ~= "" then if not nixio.fs.access(value) then @@ -354,6 +355,7 @@ tls_keyFile.validate = function(self, value, t) end return nil end +tls_keyFile.default = "/etc/config/ssl/" .. arg[1] .. ".key" tls_keyFile:depends("tls", "1") tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) @@ -509,12 +511,14 @@ quic_guise = s:option(ListValue, "quic_guise", translate("Camouflage Type")) for a, t in ipairs(header_type_list) do quic_guise:value(t) end quic_guise:depends("transport", "quic") --- [[ VLESS Fallback部分 ]]-- ---[[ +-- [[ Fallback部分 ]]-- fallback = s:option(Flag, "fallback", translate("Fallback")) -fallback:depends({ type = "Xray", protocol = "vless", transport = "tcp", tls = "1" }) -fallback:depends({ type = "V2ray", protocol = "vless", transport = "tcp", tls = "1" }) +fallback:depends({ type = "Xray", protocol = "vless", transport = "tcp" }) +fallback:depends({ type = "Xray", protocol = "trojan", transport = "tcp" }) +fallback:depends({ type = "V2ray", protocol = "vless", transport = "tcp" }) +fallback:depends({ type = "V2ray", protocol = "trojan", transport = "tcp" }) +--[[ fallback_alpn = s:option(Value, "fallback_alpn", "Fallback alpn") fallback_alpn:depends("fallback", "1") @@ -529,6 +533,9 @@ fallback_xver.default = 0 fallback_xver:depends("fallback", "1") ]]-- +fallback_list = s:option(DynamicList, "fallback_list", "Fallback", translate("dest,path")) +fallback_list:depends("fallback", "1") + ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) ss_aead:depends("type", "Trojan-Go") ss_aead.default = "0" diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm index dacce36afa..8e033c92aa 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm @@ -1,7 +1,5 @@ <% local api = require "luci.model.cbi.passwall.api.api" -local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1) -local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1) local auto_switch = api.uci_get_type("auto_switch", "enable", 0) -%>