From 2b832ba5c39df1cf815359689cfd1aef8f9c6394 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Fri, 17 Jul 2020 20:00:42 +0800 Subject: [PATCH 01/11] luci-app-jd-dailybonus: sync with upstream source --- package/ctcgfw/luci-app-jd-dailybonus/Makefile | 4 ++-- package/ctcgfw/luci-app-jd-dailybonus/relnotes.txt | 12 ++++++++++++ .../root/usr/share/jd-dailybonus/newapp.sh | 10 ++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/package/ctcgfw/luci-app-jd-dailybonus/Makefile b/package/ctcgfw/luci-app-jd-dailybonus/Makefile index eb9953bfa4..fbd3aedb45 100644 --- a/package/ctcgfw/luci-app-jd-dailybonus/Makefile +++ b/package/ctcgfw/luci-app-jd-dailybonus/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-jd-dailybonus LUCI_PKGARCH:=all -PKG_VERSION:=0.8 -PKG_RELEASE:=20200715 +PKG_VERSION:=0.8.1 +PKG_RELEASE:=20200716 include $(INCLUDE_DIR)/package.mk diff --git a/package/ctcgfw/luci-app-jd-dailybonus/relnotes.txt b/package/ctcgfw/luci-app-jd-dailybonus/relnotes.txt index 8011b7715d..dac56e603d 100644 --- a/package/ctcgfw/luci-app-jd-dailybonus/relnotes.txt +++ b/package/ctcgfw/luci-app-jd-dailybonus/relnotes.txt @@ -4,6 +4,18 @@ # ######################################################## +######################################################## +// +// 0.8.1 2020-07-16 +// +// +######################################################## + + +Updates + +- UPDATE: 修正部分cookie无法更新到脚本的问题。 + ######################################################## // // 0.8 2020-07-15 diff --git a/package/ctcgfw/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/newapp.sh b/package/ctcgfw/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/newapp.sh index 37ce062258..94db34dd92 100755 --- a/package/ctcgfw/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/newapp.sh +++ b/package/ctcgfw/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/newapp.sh @@ -55,13 +55,19 @@ fill_cookie() { cookie1=$(uci_get_by_type global cookie) if [ ! "$cookie1" = "" ]; then varb="var Key = '$cookie1';" - sed -i "s/^var Key =.*/$varb/g" $JD_SCRIPT + a=$(sed -n '/var Key =/=' $JD_SCRIPT) + b=$((a-1)) + sed -i "${a}d" $JD_SCRIPT + sed -i "${b}a ${varb}" $JD_SCRIPT fi cookie2=$(uci_get_by_type global cookie2) if [ ! "$cookie2" = "" ]; then varb2="var DualKey = '$cookie2';" - sed -i "s/^var DualKey =.*/$varb2/g" $JD_SCRIPT + aa=$(sed -n '/var DualKey =/=' $JD_SCRIPT) + bb=$((aa-1)) + sed -i "${aa}d" $JD_SCRIPT + sed -i "${bb}a ${varb2}" $JD_SCRIPT fi stop=$(uci_get_by_type global stop) From 8f32714143a0d5e70d540b3b24fea7a413ca04ae Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Fri, 17 Jul 2020 20:15:53 +0800 Subject: [PATCH 02/11] trojan-go/trojan-plus: introduce package --- package/lienol/trojan-go/Makefile | 85 + package/lienol/trojan-plus/Makefile | 69 + .../patches/0001-C-S-Binary-Mods.patch | 3339 +++++++++++++++++ 3 files changed, 3493 insertions(+) create mode 100644 package/lienol/trojan-go/Makefile create mode 100644 package/lienol/trojan-plus/Makefile create mode 100644 package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch diff --git a/package/lienol/trojan-go/Makefile b/package/lienol/trojan-go/Makefile new file mode 100644 index 0000000000..f0e7434166 --- /dev/null +++ b/package/lienol/trojan-go/Makefile @@ -0,0 +1,85 @@ +# Copyright (C) 2020 Lienol +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=trojan-go +PKG_VERSION:=0.7.8 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/p4gefau1t/trojan-go.git +PKG_SOURCE_VERSION:=9866c030058870bf18d60f1d3677c6d4ed9de35d +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) + +PKG_CONFIG_DEPENDS := \ + CONFIG_TROJAN_GO_COMPRESS_GOPROXY \ + CONFIG_TROJAN_GO_COMPRESS_UPX + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/p4gefau1t/trojan-go +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/constant.Version=$(PKG_VERSION) \ + $(GO_PKG)/constant.Commit=$(PKG_SOURCE_VERSION) +GO_PKG_TAG:=-tags full + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + DEPENDS:=$$(GO_ARCH_DEPENDS) + TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. + URL:=https://github.com/p4gefau1t/trojan-go +endef + +define Package/$(PKG_NAME)/config + +menu "Configuration" + depends on PACKAGE_$(PKG_NAME) + +config TROJAN_GO_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config TROJAN_GO_COMPRESS_UPX + bool "Compress executable files with UPX" + default y + +endmenu + +endef + +ifeq ($(CONFIG_TROJAN_GO_COMPRESS_GOPROXY),y) +export GO111MODULE=on +export GOPROXY=https://goproxy.cn +endif + +define Build/Prepare + tar -zxvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 +endef + +define Build/Compile + $(call GoPackage/Build/Configure) + $(call GoPackage/Build/Compile) +ifeq ($(CONFIG_TROJAN_GO_COMPRESS_UPX),y) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) +endif +endef + +define Package/$(PKG_NAME)/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) $(1)/usr/bin/$(PKG_NAME) +endef + +$(eval $(call GoBinPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lienol/trojan-plus/Makefile b/package/lienol/trojan-plus/Makefile new file mode 100644 index 0000000000..76f9d6fb2f --- /dev/null +++ b/package/lienol/trojan-plus/Makefile @@ -0,0 +1,69 @@ +# +# Copyright (C) 2018-2019 wongsyrone +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +PKG_NAME:=trojan +PKG_VERSION:=10.0.1 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/Trojan-Plus-Group/trojan-plus.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=4af7ff4dd48c7257c354d4e6dafafcdf5f12379c +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +CMAKE_INSTALL:=1 +PKG_BUILD_PARALLEL:=0 +PKG_BUILD_DEPENDS:=openssl + +PKG_LICENSE:=GPL-3.0 +PKG_MAINTAINER:=Trojan-Plus-Group + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +TARGET_CXXFLAGS += -Wall -Wextra +TARGET_CXXFLAGS += $(FPIC) + +# LTO +TARGET_CXXFLAGS += -flto +TARGET_LDFLAGS += -flto + +# CXX standard +TARGET_CXXFLAGS += -std=c++11 +TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3 +TARGET_CXXFLAGS += -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -Wl,--gc-sections + +CMAKE_OPTIONS += \ + -DENABLE_MYSQL=OFF \ + -DENABLE_NAT=ON \ + -DENABLE_REUSE_PORT=ON \ + -DENABLE_SSL_KEYLOG=ON \ + -DENABLE_TLS13_CIPHERSUITES=ON \ + -DFORCE_TCP_FASTOPEN=OFF \ + -DSYSTEMD_SERVICE=OFF \ + -DOPENSSL_USE_STATIC_LIBS=FALSE \ + -DBoost_DEBUG=ON \ + -DBoost_NO_BOOST_CMAKE=ON + +define Package/trojan + SECTION:=net + CATEGORY:=Network + TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. + URL:=https://github.com/Trojan-Plus-Group/trojan-plus + DEPENDS:=+libpthread +libstdcpp +libopenssl \ + +boost +boost-system +boost-program_options +endef + +define Package/trojan/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan +endef + +$(eval $(call BuildPackage,trojan)) + diff --git a/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch b/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch new file mode 100644 index 0000000000..8b19c83480 --- /dev/null +++ b/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch @@ -0,0 +1,3339 @@ +From 2a15d2c886cb23f4d5a8ff975fa3c87819046390 Mon Sep 17 00:00:00 2001 +From: peter-tank <30540412+peter-tank@users.noreply.github.com> +Date: Sat, 4 Jul 2020 16:00:00 +0000 +Subject: [PATCH] C/S Binary Mods - no dns settings + +Signed-off-by: peter-tank <30540412+peter-tank@users.noreply.github.com> +--- + .gitmodules | 9 - + CMakeLists.txt | 114 ++---- + GSL | 1 - + badvpn | 1 - + src/core/pipeline.cpp | 1 - + src/core/service.cpp | 41 --- + src/core/service.h | 4 - + src/tun/dnsserver.cpp | 278 -------------- + src/tun/dnsserver.h | 107 ------ + src/tun/lwip_custom/arch/cc.h | 79 ---- + src/tun/lwip_custom/lwipopts.h | 84 ----- + src/tun/lwip_custom/sys.c | 29 -- + src/tun/lwip_tcp_client.cpp | 273 -------------- + src/tun/lwip_tcp_client.h | 81 ----- + src/tun/tundev.cpp | 644 --------------------------------- + src/tun/tundev.h | 146 -------- + src/tun/tunlocalsession.cpp | 215 ----------- + src/tun/tunlocalsession.h | 55 --- + src/tun/tunproxysession.cpp | 409 --------------------- + src/tun/tunproxysession.h | 59 --- + src/tun/tunsession.cpp | 40 -- + src/tun/tunsession.h | 108 ------ + src/tun/udplocalforwarder.cpp | 156 -------- + src/tun/udplocalforwarder.h | 63 ---- + trojan-plus-android-libs | 1 - + 25 files changed, 26 insertions(+), 2972 deletions(-) + delete mode 160000 GSL + delete mode 160000 badvpn + delete mode 100644 src/tun/dnsserver.cpp + delete mode 100644 src/tun/dnsserver.h + delete mode 100644 src/tun/lwip_custom/arch/cc.h + delete mode 100644 src/tun/lwip_custom/lwipopts.h + delete mode 100644 src/tun/lwip_custom/sys.c + delete mode 100644 src/tun/lwip_tcp_client.cpp + delete mode 100644 src/tun/lwip_tcp_client.h + delete mode 100644 src/tun/tundev.cpp + delete mode 100644 src/tun/tundev.h + delete mode 100644 src/tun/tunlocalsession.cpp + delete mode 100644 src/tun/tunlocalsession.h + delete mode 100644 src/tun/tunproxysession.cpp + delete mode 100644 src/tun/tunproxysession.h + delete mode 100644 src/tun/tunsession.cpp + delete mode 100644 src/tun/tunsession.h + delete mode 100644 src/tun/udplocalforwarder.cpp + delete mode 100644 src/tun/udplocalforwarder.h + delete mode 160000 trojan-plus-android-libs + +diff --git a/.gitmodules b/.gitmodules +index 68e3712..e69de29 100644 +--- a/.gitmodules ++++ b/.gitmodules +@@ -1,9 +0,0 @@ +-[submodule "badvpn"] +- path = badvpn +- url = https://github.com/Trojan-Plus-Group/badvpn +-[submodule "trojan-plus-android-libs"] +- path = trojan-plus-android-libs +- url = https://github.com/Trojan-Plus-Group/trojan-plus-android-libs.git +-[submodule "GSL"] +- path = GSL +- url = https://github.com/microsoft/GSL.git +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3fc087d..e3e1171 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -47,7 +47,7 @@ if(CMAKE_BUILD_TYPE STREQUAL Release AND NOT MSVC AND NOT APPLE) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") + +- if( ANDROID ) ++ if(ANDROID) + # I don't know why andorid's clang++ compiler will report "clang++: warning: argument unused during compilation: '-s' [-Wunused-command-line-argument]" + # so I add this to surpass warning + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Qunused-arguments") +@@ -68,73 +68,15 @@ else() + add_definitions(-Wall -Wextra) + endif() + +-if(ANDROID) +- option(ENABLE_ANDROID_LOG "Build with LogCat output" ON) +- if(ENABLE_ANDROID_LOG) +- add_definitions(-DENABLE_ANDROID_LOG=1) +- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -llog") +- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -llog") +- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -llog") +- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -llog") +- endif() +-endif() +- + # force 1.73 boost compiling warning note + add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS=1) + +-# badvpn definitions for tun2socks +-if(NOT MSVC) +- if(APPLE) +- add_definitions(-DBADVPN_FREEBSD=1) +- else() +- add_definitions(-DBADVPN_LINUX=1) +- endif() +-endif() +- +-add_definitions(-DBADVPN_THREADWORK_USE_PTHREAD=1 -DBADVPN_BREACTOR_BADVPN=1) +-add_definitions(-D_GNU_SOURCE=1 -DBADVPN_USE_SIGNALFD=1 -DBADVPN_USE_EPOLL=1) +-add_definitions(-DBADVPN_LITTLE_ENDIAN=1 -DBADVPN_THREAD_SAFE=1) +- + include_directories( + src +- src/tun/lwip_custom +- badvpn/lwip/src/include +- badvpn + ) + + set(TROJAN_SOURCE_FILES +- src/tun/lwip_custom/sys.c + +- badvpn/lwip/src/core/udp.c +- badvpn/lwip/src/core/memp.c +- badvpn/lwip/src/core/init.c +- badvpn/lwip/src/core/pbuf.c +- badvpn/lwip/src/core/tcp.c +- badvpn/lwip/src/core/tcp_out.c +- badvpn/lwip/src/core/netif.c +- badvpn/lwip/src/core/def.c +- badvpn/lwip/src/core/ip.c +- badvpn/lwip/src/core/mem.c +- badvpn/lwip/src/core/tcp_in.c +- badvpn/lwip/src/core/stats.c +- badvpn/lwip/src/core/inet_chksum.c +- badvpn/lwip/src/core/timeouts.c +- badvpn/lwip/src/core/ipv4/icmp.c +- badvpn/lwip/src/core/ipv4/igmp.c +- badvpn/lwip/src/core/ipv4/ip4_addr.c +- badvpn/lwip/src/core/ipv4/ip4_frag.c +- badvpn/lwip/src/core/ipv4/ip4.c +- badvpn/lwip/src/core/ipv4/autoip.c +- badvpn/lwip/src/core/ipv6/ethip6.c +- badvpn/lwip/src/core/ipv6/inet6.c +- badvpn/lwip/src/core/ipv6/ip6_addr.c +- badvpn/lwip/src/core/ipv6/mld6.c +- badvpn/lwip/src/core/ipv6/dhcp6.c +- badvpn/lwip/src/core/ipv6/icmp6.c +- badvpn/lwip/src/core/ipv6/ip6.c +- badvpn/lwip/src/core/ipv6/ip6_frag.c +- badvpn/lwip/src/core/ipv6/nd6.c +- + src/core/authenticator.cpp + src/core/config.cpp + src/core/log.cpp +@@ -161,45 +103,43 @@ set(TROJAN_SOURCE_FILES + src/ssl/ssldefaults.cpp + src/ssl/sslsession.cpp + +- src/tun/lwip_tcp_client.cpp +- src/tun/tundev.cpp +- src/tun/tunsession.cpp +- src/tun/tunproxysession.cpp +- src/tun/tunlocalsession.cpp +- src/tun/dnsserver.cpp +- src/tun/udplocalforwarder.cpp + ) + +-if(ANDROID) +- add_library(trojan SHARED ${TROJAN_SOURCE_FILES}) +-else() ++ + add_executable(trojan ${TROJAN_SOURCE_FILES}) +-endif() + + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) + target_link_libraries(trojan ${CMAKE_THREAD_LIBS_INIT}) + + # https://github.com/microsoft/GSL supported +-include_directories(${PROJECT_SOURCE_DIR}/GSL/include) +- ++#find_package(Microsoft.GSL CONFIG REQUIRED) ++if(${Microsoft.GSL_FOUND}) ++ message(STATUS "Found the Guidelines Support Library: ${Microsoft.GSL_DIR}") ++ target_link_libraries(trojan INTERFACE Microsoft.GSL::GSL) ++else() ++ set(GSL_URL https://github.com/Microsoft/GSL) ++ set(GSL_VERSION 0f6dbc9) ++ message(STATUS "Using and shipping ${GSL_URL} version ${GCL_VERSION}") ++ set(GSL_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/GSL) ++ if(NOT EXISTS ${GSL_DIR}) ++ execute_process(COMMAND git clone ${GSL_URL} ${GSL_DIR}) ++ endif() ++ execute_process(COMMAND git checkout ${GSL_VERSION} WORKING_DIRECTORY ${GSL_DIR}) ++ #install(DIRECTORY ${GSL_DIR}/gsl DESTINATION include) ++ #install(FILES ${GSL_DIR}/LICENSE DESTINATION include/gsl/LICENSE) ++ set(GSL_INCLUDE_DIR NAMES ${GSL_DIR}) ++ if(GSL_INCLUDE_DIR) ++ set(GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR}/include) ++ include_directories(${GSL_INCLUDE_DIRS}) ++ set(GSL_FOUND TRUE) ++ endif() ++endif() ++ + # for cland-tidy compiling database by default the file is small, generation is cheap + # as developer, I am always add this option... + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +-if (ANDROID) +- set(ANDROID_MY_LIBS ${PROJECT_SOURCE_DIR}/trojan-plus-android-libs) +- set(ANDROID_MY_LIBS_LIBRARIES +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libssl.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libcrypto.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libboost_system.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libboost_program_options.a) +- +- set(OPENSSL_VERSION 1.1.1) +- +- include_directories(${ANDROID_MY_LIBS}/include) +- target_link_libraries(trojan ${ANDROID_MY_LIBS_LIBRARIES}) +-else() + find_package(Boost 1.66.0 REQUIRED COMPONENTS system program_options) + include_directories(${Boost_INCLUDE_DIR}) + target_link_libraries(trojan ${Boost_LIBRARIES}) +@@ -210,7 +150,6 @@ else() + find_package(OpenSSL 1.1.0 REQUIRED) + include_directories(${OPENSSL_INCLUDE_DIR}) + target_link_libraries(trojan ${OPENSSL_LIBRARIES}) +-endif() + + if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1.1) + option(ENABLE_SSL_KEYLOG "Build with SSL KeyLog support" ON) +@@ -229,7 +168,7 @@ if(FORCE_TCP_FASTOPEN) + add_definitions(-DTCP_FASTOPEN=23 -DTCP_FASTOPEN_CONNECT=30) + endif() + +-if(NOT ANDROID) ++if(NOT ANDROID) + option(ENABLE_MYSQL "Build with MySQL support" ON) + if(ENABLE_MYSQL) + find_package(MySQL REQUIRED) +@@ -301,4 +240,3 @@ if(NOT ANDROID) + endif() + endif() + +- +diff --git a/GSL b/GSL +deleted file mode 160000 +index 98002ab..0000000 +--- a/GSL ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 98002ab60135fe70f4acd7e5b8a34f9ad1427807 +diff --git a/badvpn b/badvpn +deleted file mode 160000 +index 01feab8..0000000 +--- a/badvpn ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 01feab854625d1cc0e0391db394dd305b6dd1815 +diff --git a/src/core/pipeline.cpp b/src/core/pipeline.cpp +index 4dd0cbf..8fa5bce 100644 +--- a/src/core/pipeline.cpp ++++ b/src/core/pipeline.cpp +@@ -23,7 +23,6 @@ + #include "core/utils.h" + #include "proto/pipelinerequest.h" + #include "session/clientsession.h" +-#include "tun/tunsession.h" + + using namespace std; + using namespace boost::asio::ip; +diff --git a/src/core/service.cpp b/src/core/service.cpp +index e439e8c..e597c6e 100644 +--- a/src/core/service.cpp ++++ b/src/core/service.cpp +@@ -36,9 +36,6 @@ + #include "session/serversession.h" + #include "utils.h" + +-#include "tun/dnsserver.h" +-#include "tun/tundev.h" +- + using namespace std; + using namespace boost::asio::ip; + using namespace boost::asio::ssl; +@@ -58,12 +55,6 @@ Service::Service(Config& config, bool test) + #endif // ENABLE_NAT + + if (!test) { +- if (config.get_run_type() == Config::CLIENT_TUN || config.get_run_type() == Config::SERVERT_TUN) { +- m_tundev = make_shared(this, config.get_tun().tun_name, config.get_tun().net_ip, +- config.get_tun().net_mask, config.get_tun().mtu, config.get_tun().tun_fd); +- } +- +- if (config.get_run_type() != Config::CLIENT_TUN) { + tcp::resolver resolver(io_context); + tcp::endpoint listen_endpoint = + *resolver.resolve(config.get_local_addr(), to_string(config.get_local_port())).begin(); +@@ -119,7 +110,6 @@ Service::Service(Config& config, bool test) + _log_with_date_time("TCP_FASTOPEN_CONNECT is not supported", Log::WARN); + #endif // TCP_FASTOPEN_CONNECT + } +- } + } + + config.prepare_ssl_context(ssl_context, plain_http_response); +@@ -134,25 +124,6 @@ Service::Service(Config& config, bool test) + } + } + +- if (!test && config.get_dns().enabled) { +- if (config.get_run_type() == Config::SERVER || config.get_run_type() == Config::FORWARD) { +- _log_with_date_time("[dns] dns server cannot run in type 'server' or 'forward'", Log::ERROR); +- } else { +- if (DNSServer::get_dns_lock()) { +- m_dns_server = make_shared(this); +- if (m_dns_server->start()) { +- _log_with_date_time( +- "[dns] start local dns server at 0.0.0.0:" + to_string(config.get_dns().port), Log::WARN); +- +- if (m_tundev != nullptr) { +- m_tundev->set_dns_server(m_dns_server); +- } +- } +- } else { +- _log_with_date_time("[dns] dns server has been created in other process.", Log::WARN); +- } +- } +- } + } + + void Service::prepare_icmpd(Config& config, bool is_ipv4) { +@@ -175,10 +146,6 @@ void Service::run() { + rt = "nat"; + } else if (config.get_run_type() == Config::CLIENT) { + rt = "client"; +- } else if (config.get_run_type() == Config::CLIENT_TUN) { +- rt = "client tun"; +- } else if (config.get_run_type() == Config::SERVERT_TUN) { +- rt = "server tun"; + } else { + throw logic_error("unknow run type error"); + } +@@ -187,7 +154,6 @@ void Service::run() { + rt += " in pipeline mode"; + } + +- if (config.get_run_type() != Config::CLIENT_TUN) { + async_accept(); + if (config.get_run_type() == Config::FORWARD || config.get_run_type() == Config::NAT) { + udp_async_read(); +@@ -197,18 +163,11 @@ void Service::run() { + _log_with_date_time(string("trojan plus service (") + rt + ") started at " + + local_endpoint.address().to_string() + ':' + to_string(local_endpoint.port()), + Log::FATAL); +- } else { +- _log_with_date_time(string("trojan plus service (") + rt + ") started at [" + config.get_tun().tun_name + "] " + +- config.get_tun().net_ip + "/" + config.get_tun().net_mask, +- Log::FATAL); +- } + io_context.run(); + _log_with_date_time("trojan service stopped", Log::WARN); + } + + void Service::stop() { +- m_tundev = nullptr; +- m_dns_server = nullptr; + boost::system::error_code ec; + socket_acceptor.cancel(ec); + if (udp_socket.is_open()) { +diff --git a/src/core/service.h b/src/core/service.h +index 07e6e0f..5361e5d 100644 +--- a/src/core/service.h ++++ b/src/core/service.h +@@ -38,8 +38,6 @@ + #include "session/session.h" + #include "session/udpforwardsession.h" + +-class TUNDev; +-class DNSServer; + class Pipeline; + class icmpd; + class Service { +@@ -66,8 +64,6 @@ class Service { + std::shared_ptr icmp_processor; + void prepare_icmpd(Config& config, bool is_ipv4); + +- std::shared_ptr m_dns_server; +- std::shared_ptr m_tundev; + SendingDataAllocator m_sending_data_allocator; + + const Config& config; +diff --git a/src/tun/dnsserver.cpp b/src/tun/dnsserver.cpp +deleted file mode 100644 +index d19aa33..0000000 +--- a/src/tun/dnsserver.cpp ++++ /dev/null +@@ -1,278 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "dnsserver.h" +-#include "core/service.h" +-#include "proto/dns_header.h" +-#include "tun/udplocalforwarder.h" +-#include +-#include +- +-using namespace std; +-using namespace boost::asio::ip; +-using namespace trojan; +- +-FILE_LOCK_HANDLE DNSServer::s_dns_file_lock = INVALID_LOCK_HANDLE; +-bool DNSServer::get_dns_lock() { +- s_dns_file_lock = get_file_lock("./trojan_dns_lock.output"); +- return s_dns_file_lock != INVALID_LOCK_HANDLE; +-} +- +-DNSServer::DNSServer(Service* _service) : m_service(_service), m_serv_udp_socket(_service->get_io_context()) {} +- +-DNSServer::~DNSServer() { close_file_lock(s_dns_file_lock); } +- +-bool DNSServer::start() { +- boost::system::error_code ec; +- +- auto udp_bind_endpoint = udp::endpoint(make_address_v4("0.0.0.0"), m_service->get_config().get_dns().port); +- auto udp_protocol = udp_bind_endpoint.protocol(); +- +- m_serv_udp_socket.open(udp_protocol, ec); +- if (ec) { +- output_debug_info_ec(ec); +- return false; +- } +- m_serv_udp_socket.bind(udp_bind_endpoint, ec); +- if (ec) { +- output_debug_info_ec(ec); +- return false; +- } +- +- async_read_udp(); +- return true; +-} +- +-bool DNSServer::is_proxy_dns_msg(const dns_header& dns_hdr) { +- return dns_hdr.QR() == 0 && dns_hdr.RCODE() == 0 && dns_hdr.ANCOUNT() == 0 && dns_hdr.NSCOUNT() == 0 && +- dns_hdr.QDCOUNT() > 0; +-} +- +-bool DNSServer::is_proxy_dns_msg(const trojan::dns_question& qt) { +- return qt.get_QCLASS() == dns_header::QCLASS_INTERNET && +- (qt.get_QTYPE() == dns_header::QTYPE_A_RECORD || qt.get_QTYPE() == dns_header::QTYPE_AAAA_RECORD); +-} +- +-bool DNSServer::is_in_gfwlist(const string& domain) const { +- const auto& gfwlist = m_service->get_config().get_dns()._gfwlist; +- for (size_t start_size = domain.size(); start_size > 0; start_size--) { +- const auto& it = gfwlist.find(start_size); +- if (it != gfwlist.end()) { +- for (const auto& d : it->second) { +- int i = int(d.size() - 1); +- int j = int(domain.size() - 1); +- for (; i >= 0 && j >= 0; i--, j--) { +- if (d[i] != domain[j]) { +- break; +- } +- } +- +- if (i < 0) { +- return true; +- } +- } +- } +- } +- +- return false; +-} +- +-bool DNSServer::try_to_find_existed(const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data) { +- clear_weak_ptr_list(m_proxy_forwarders); +- clear_weak_ptr_list(m_forwarders); +- +- for (const auto& f : m_proxy_forwarders) { +- if (f.lock()->process(local_src, data)) { +- return true; +- } +- } +- +- for (const auto& f : m_forwarders) { +- if (f.lock()->process(local_src, data)) { +- return true; +- } +- } +- +- return false; +-} +-bool DNSServer::find_in_dns_cache( +- const udp::endpoint& local_src, const dns_header& header, const dns_question& question) { +- if (m_service->get_config().get_dns().enable_cached) { +- auto curr_time = time(nullptr); +- +- auto it = m_dns_cache.begin(); +- while (it != m_dns_cache.end()) { +- if (it->expired(curr_time)) { +- it = m_dns_cache.erase(it); +- } else { +- it++; +- } +- } +- +- for (auto& c : m_dns_cache) { +- if (c.get_domain() == question.get_QNAME()) { +- _log_with_endpoint_ALL(local_src, "[dns] find " + question.get_QNAME() + " in cache ttl: " + +- to_string(c.get_ttl() - (curr_time - c.get_cached_time()))); +- +- std::string& raw_data = c.get_answer_data(); +- raw_data[0] = header.ID() >> one_byte_shift_8_bits; +- raw_data[1] = header.ID() & one_byte_mask_0xFF; +- +- send_to_local(local_src, raw_data); +- return true; +- } +- } +- } +- +- return false; +-} +- +-void DNSServer::store_in_dns_cache(const string_view& data, bool proxyed) { +- if (m_service->get_config().get_dns().enable_cached) { +- string read_data(data); +- istringstream is(read_data); +- +- dns_answer answer; +- if (is >> answer) { +- if (!answer.get_questions().empty() && is_proxy_dns_msg(answer.get_questions()[0])) { +- +- const auto& domain = answer.get_questions()[0].get_QNAME(); +- uint32_t ttl = numeric_limits::max(); +- vector A_list; +- for (const auto& an : answer.get_answers()) { +- if (an.A != 0) { +- if (ttl > an.TTL) { // find min +- ttl = an.TTL; +- } +- +- A_list.emplace_back(an.A); +- } +- } +- +- if (ttl != numeric_limits::max()) { +- sort(A_list.begin(), A_list.end()); +- m_dns_cache.emplace_back(DNSCache(domain, ttl, A_list, proxyed, data)); +- _log_with_date_time_ALL("[dns] cache " + domain + " in ttl: " + to_string(ttl)); +- } +- } +- } +- } +-} +- +-void DNSServer::send_to_local(const udp::endpoint& local_src, const string_view& data) { +- _log_with_endpoint_ALL(local_src, "[dns] <-- " + to_string(data.length())); +- +- boost::system::error_code ec; +- m_serv_udp_socket.send_to(boost::asio::buffer(data), local_src, 0, ec); +-} +- +-void DNSServer::recv_up_stream_data(const udp::endpoint& local_src, const string_view& data, bool proxyed) { +- send_to_local(local_src, data); +- store_in_dns_cache(data, proxyed); +-} +- +-void DNSServer::in_recved(istream& is, const dns_header& header, const string_view& former_data) { +- bool proxy = false; +- dns_question qt; +- is >> qt; +- if (is) { +- if (is_proxy_dns_msg(qt)) { +- if (find_in_dns_cache(m_udp_recv_endpoint, header, qt)) { +- return; +- } +- proxy = is_in_gfwlist(qt.get_QNAME()); +- } +- } +- +- if (try_to_find_existed(m_udp_recv_endpoint, m_udp_read_buf)) { +- return; +- } +- +- if (proxy) { +- auto up_stream_ns_svr = m_service->get_config().get_dns().up_gfw_dns_server.at(0); +- auto dst = make_pair(up_stream_ns_svr, DEFAULT_UP_STREAM_NS_SVR_PORT); +- auto forwarder = make_shared( +- m_service, m_service->get_config(), m_service->get_ssl_context(), m_udp_recv_endpoint, dst, +- [this](const udp::endpoint& endpoint, const string_view& data) { recv_up_stream_data(endpoint, data, true); }, +- false, true); +- +- auto data = m_service->get_sending_data_allocator().allocate(former_data); +- m_service->start_session(forwarder, [this, forwarder, data](boost::system::error_code ec) { +- if (!ec) { +- m_proxy_forwarders.emplace_back(forwarder); +- forwarder->start_udp(streambuf_to_string_view(*data)); +- } +- m_service->get_sending_data_allocator().free(data); +- }); +- +- } else { +- auto up_stream_ns_svr = m_service->get_config().get_dns().up_dns_server.at(0); +- auto dst = udp::endpoint(make_address(up_stream_ns_svr), DEFAULT_UP_STREAM_NS_SVR_PORT); +- auto forwarder = make_shared( +- m_service, m_udp_recv_endpoint, dst, +- [this]( +- const udp::endpoint& endpoint, const string_view& data) { recv_up_stream_data(endpoint, data, false); }, +- true); +- +- forwarder->start(); +- +- if (forwarder->process(m_udp_recv_endpoint, former_data)) { +- m_forwarders.emplace_back(forwarder); +- } +- } +-} +-void DNSServer::async_read_udp() { +- auto self = shared_from_this(); +- auto prepare_size = m_service->get_config().get_udp_recv_buf(); +- m_udp_read_buf.begin_read(__FILE__, __LINE__); +- m_udp_read_buf.consume_all(); +- m_serv_udp_socket.async_receive_from(m_udp_read_buf.prepare(prepare_size), m_udp_recv_endpoint, +- [self, this](const boost::system::error_code error, size_t length) { +- m_udp_read_buf.end_read(); +- if (error) { +- async_read_udp(); +- return; +- } +- +- m_udp_read_buf.commit(length); +- const string_view& former_data = m_udp_read_buf; +- std::istream is(&(boost::asio::streambuf&)m_udp_read_buf); +- +- dns_header dns_hdr; +- is >> dns_hdr; +- +- if (is && is_proxy_dns_msg(dns_hdr)) { +- in_recved(is, dns_hdr, former_data); +- } +- +- async_read_udp(); +- }); +-} +- +-bool DNSServer::is_ip_in_gfwlist(uint32_t ip) const { +- for (const auto& dns : m_dns_cache) { +- if (dns.is_proxyed() && binary_search(dns.get_ips().cbegin(), dns.get_ips().cend(), ip)) { +- return true; +- } +- } +- +- return false; +-} +diff --git a/src/tun/dnsserver.h b/src/tun/dnsserver.h +deleted file mode 100644 +index f46d53d..0000000 +--- a/src/tun/dnsserver.h ++++ /dev/null +@@ -1,107 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_DNS_SERVER_HPP +-#define _TROJAN_DNS_SERVER_HPP +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "core/utils.h" +-#include "proto/dns_header.h" +- +-class UDPForwardSession; +-class UDPLocalForwarder; +-class Service; +-class DNSServer : public std::enable_shared_from_this { +- +- enum { DEFAULT_UP_STREAM_NS_SVR_PORT = 53 }; +- +- class DNSCache { +- std::string domain; +- int ttl; +- std::vector ips; +- bool proxyed; +- time_t cached_time{time(nullptr)}; +- std::string answer_data; +- +- public: +- DNSCache( +- std::string _domain, int _ttl, std::vector& _ips, bool _proxyed, const std::string_view& data) +- : domain(std::move(_domain)), ttl(_ttl), ips(move(_ips)), proxyed(_proxyed), answer_data(data) {} +- +- [[nodiscard]] inline bool expired(time_t curr) const { return int(curr - cached_time) >= ttl; } +- +- _define_getter_const(const std::string&, domain); +- _define_getter_const(int, ttl); +- _define_getter_const(const std::vector&, ips); +- _define_getter_const(time_t, cached_time); +- _define_is_const(proxyed); +- +- _define_getter(std::string&, answer_data); +- }; +- +- Service* m_service; +- +- std::vector m_dns_cache; +- boost::asio::ip::udp::socket m_serv_udp_socket; +- ReadBufWithGuard m_udp_read_buf; +- boost::asio::ip::udp::endpoint m_udp_recv_endpoint; +- +- std::list> m_proxy_forwarders; +- std::list> m_forwarders; +- +- void in_recved(std::istream& is, const trojan::dns_header& header, const std::string_view& former_data); +- void async_read_udp(); +- void recv_up_stream_data( +- const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data, bool proxyed); +- void send_to_local(const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data); +- bool find_in_dns_cache(const boost::asio::ip::udp::endpoint& local_src, const trojan::dns_header& header, +- const trojan::dns_question& question); +- void store_in_dns_cache(const std::string_view& data, bool proxyed); +- +- [[nodiscard]] bool is_in_gfwlist(const std::string& domain) const; +- +- [[nodiscard]] bool try_to_find_existed( +- const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data); +- +- [[nodiscard]] static bool is_proxy_dns_msg(const trojan::dns_header& hdr); +- +- [[nodiscard]] static bool is_proxy_dns_msg(const trojan::dns_question& question); +- +- static FILE_LOCK_HANDLE s_dns_file_lock; +- +- public: +- DNSServer(Service* _service); +- ~DNSServer(); +- +- [[nodiscard]] bool start(); +- [[nodiscard]] bool is_ip_in_gfwlist(uint32_t ip) const; +- +- [[nodiscard]] static bool get_dns_lock(); +-}; +- +-#endif //_TROJAN_DNS_SERVER_HPP +diff --git a/src/tun/lwip_custom/arch/cc.h b/src/tun/lwip_custom/arch/cc.h +deleted file mode 100644 +index 6554989..0000000 +--- a/src/tun/lwip_custom/arch/cc.h ++++ /dev/null +@@ -1,79 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef LWIP_CUSTOM_CC_H +-#define LWIP_CUSTOM_CC_H +- +-#include +-#include +-#include +-#include +- +-#include +- +-#ifndef _WIN32 +- #define PACK_STRUCT_BEGIN +- #define PACK_STRUCT_END +- #if defined(__GNUC__) && defined(__MINGW32__) +- // Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 +- #define PACK_STRUCT_STRUCT __attribute__((packed)) __attribute__((gcc_struct)) +- #else +- #define PACK_STRUCT_STRUCT __attribute__((packed)) +- #endif +-#else +- #define PACK_STRUCT_BEGIN +- #define PACK_STRUCT_END +- #define PACK_STRUCT_STRUCT +-#endif //_WIN32 +- +- +-#define LWIP_PLATFORM_DIAG(x) { fprintf(stdout, "%s: lwip diag failure: %s\n", __FUNCTION__, (x)); } +-#define LWIP_PLATFORM_ASSERT(x) { fprintf(stderr, "%s: lwip assertion failure: %s\n", __FUNCTION__, (x)); abort(); } +- +-#define lwip_htons(x) hton16(x) +-#define lwip_htonl(x) hton32(x) +- +-#define LWIP_RAND() ( \ +- (((uint32_t)(rand() & 0xFF)) << 24) | \ +- (((uint32_t)(rand() & 0xFF)) << 16) | \ +- (((uint32_t)(rand() & 0xFF)) << 8) | \ +- (((uint32_t)(rand() & 0xFF)) << 0) \ +-) +- +-// for BYTE_ORDER +-#if defined(BADVPN_USE_WINAPI) && !defined(_MSC_VER) +- #include +-#elif defined(BADVPN_LINUX) +- #include +-#elif defined(BADVPN_FREEBSD) +- #include +-#else +- #define LITTLE_ENDIAN 1234 +- #define BIG_ENDIAN 4321 +- #if defined(BADVPN_LITTLE_ENDIAN) +- #define BYTE_ORDER LITTLE_ENDIAN +- #else +- #define BYTE_ORDER BIG_ENDIAN +- #endif +-#endif +- +- +-#endif +diff --git a/src/tun/lwip_custom/lwipopts.h b/src/tun/lwip_custom/lwipopts.h +deleted file mode 100644 +index dd83db7..0000000 +--- a/src/tun/lwip_custom/lwipopts.h ++++ /dev/null +@@ -1,84 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef LWIP_CUSTOM_LWIPOPTS_H +-#define LWIP_CUSTOM_LWIPOPTS_H +- +-#define NO_SYS 1 +-#define LWIP_TIMERS 0 +-#define MEM_ALIGNMENT 4 +- +-#define LWIP_ARP 0 +-#define ARP_QUEUEING 0 +-#define IP_FORWARD 0 +-#define LWIP_ICMP 1 +-#define LWIP_RAW 0 +-#define LWIP_DHCP 0 +-#define LWIP_AUTOIP 0 +-#define LWIP_SNMP 0 +-#define LWIP_IGMP 0 +-#define LWIP_DNS 0 +-#define LWIP_UDP 0 +-#define LWIP_UDPLITE 0 +-#define LWIP_TCP 1 +-#define LWIP_CALLBACK_API 1 +-#define LWIP_NETIF_API 0 +-#define LWIP_NETIF_LOOPBACK 0 +-#define LWIP_HAVE_LOOPIF 0 +-#define LWIP_HAVE_SLIPIF 0 +-#define LWIP_NETCONN 0 +-#define LWIP_SOCKET 0 +-#define PPP_SUPPORT 0 +-#define LWIP_IPV6 1 +-#define LWIP_IPV6_MLD 0 +-#define LWIP_IPV6_AUTOCONFIG 0 +-#define LWIP_WND_SCALE 1 +-#define TCP_RCV_SCALE 5 +- +-#define MEMP_NUM_TCP_PCB_LISTEN 16 +-#define MEMP_NUM_TCP_PCB 1024 +-#ifndef TCP_MSS +-#define TCP_MSS 1460 +-#endif //TCP_MSS +-#define TCP_SND_BUF 16384 +-#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS)) +- +-#define MEM_LIBC_MALLOC 1 +-#define MEMP_MEM_MALLOC 1 +- +-#define LWIP_PERF 0 +-#define SYS_LIGHTWEIGHT_PROT 0 +-#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +- +-// needed on 64-bit systems, enable it always so that the same configuration +-// is used regardless of the platform +-#define IPV6_FRAG_COPYHEADER 1 +- +-/* +-#define LWIP_DEBUG 1 +-#define IP_DEBUG LWIP_DBG_ON +-#define NETIF_DEBUG LWIP_DBG_ON +-#define TCP_DEBUG LWIP_DBG_ON +-#define TCP_INPUT_DEBUG LWIP_DBG_ON +-#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +-*/ +- +-#endif +diff --git a/src/tun/lwip_custom/sys.c b/src/tun/lwip_custom/sys.c +deleted file mode 100644 +index d32febd..0000000 +--- a/src/tun/lwip_custom/sys.c ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2017-2020 The Trojan Authors. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include +-#include +- +-u32_t sys_now (void) +-{ +- return (u32_t)time(NULL); +-} +diff --git a/src/tun/lwip_tcp_client.cpp b/src/tun/lwip_tcp_client.cpp +deleted file mode 100644 +index b63a46d..0000000 +--- a/src/tun/lwip_tcp_client.cpp ++++ /dev/null +@@ -1,273 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2017-2020 The Trojan Authors. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "lwip_tcp_client.h" +- +-#include +-#include +-#include +- +-#include "core/log.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-lwip_tcp_client::lwip_tcp_client(struct tcp_pcb* _pcb, shared_ptr _session, CloseCallback&& _close_cb) +- : m_pcb(_pcb), m_closed(false), m_aborted(false), m_tun_session(move(_session)), m_close_cb(move(_close_cb)) { +- +- // special for reverse local to remote +- m_remote_addr = +- tcp::endpoint(make_address_v4((address_v4::uint_type)ntoh32(_pcb->local_ip.u_addr.ip4.addr)), _pcb->local_port); +- m_local_addr = +- tcp::endpoint(make_address_v4((address_v4::uint_type)ntoh32(_pcb->remote_ip.u_addr.ip4.addr)), _pcb->remote_port); +- +- m_tun_session->set_tcp_connect(m_local_addr, m_remote_addr); +- m_tun_session->set_write_to_lwip( +- [this](const TUNSession*, const std::string_view*) { return client_socks_recv_send_out(); }); +- +- m_tun_session->set_close_callback([this](TUNSession* session) { +- if (session->recv_buf_ack_length() == 0) { // need to wait send remain buff +- output_debug_info(); +- close_client(false); +- } +- }); +- +- tcp_arg(m_pcb, this); +- +- // setup handlers +- tcp_err(m_pcb, static_client_err_func); +- tcp_recv(m_pcb, static_client_recv_func); +- tcp_sent(m_pcb, static_client_sent_func); +- +- client_log("accepted"); +-} +- +-void lwip_tcp_client::client_log(const char* fmt, ...) { +- const auto logout_level = Log::INFO; +- +- if (Log::level <= logout_level) { +- const int buf_size = 256; +- char buf[buf_size]; +- int n = snprintf((char*)buf, buf_size, "[lwip] [%s:%d->%s:%d] [pcb:0x%llx session_id: %d] ", +- m_local_addr.address().to_string().c_str(), m_local_addr.port(), m_remote_addr.address().to_string().c_str(), +- m_remote_addr.port(), (unsigned long long)m_pcb, (int)m_tun_session->get_session_id()); +- +- va_list vl; +- va_start(vl, fmt); +- vsnprintf(buf + n, buf_size - n, fmt, vl); +- va_end(vl); +- +- _log_with_date_time(buf, logout_level); +- } +-} +- +-void lwip_tcp_client::client_err_func(err_t err) { +- client_log("client_err_func (%d)", (int)err); +- +- // do NOT call close_client with tcp_close/tcp_abort, otherwise it will assert to free double +- // this client_err_func will be called by lwip and then lwip system will be free pcb +- close_session(); +- release_client(false); +-} +- +-err_t lwip_tcp_client::client_recv_func(struct tcp_pcb*, struct pbuf* p, err_t err) { +- +- if (m_aborted) { +- return ERR_ABRT; +- } +- +- if (p == nullptr || err != ERR_OK) { +- client_log("client_recv_func closed (%d)", (int)err); +- close_client(false); +- } else { +- +- if (m_tun_session->is_destroyed()) { +- client_log("m_tun_session->is_destroyed closed"); +- output_debug_info(); +- close_client(true); +- return ERR_ABRT; +- } +- +- assert(p->tot_len > 0); +- if (p->tot_len > sizeof(send_buf)) { +- return ERR_MEM; +- } +- +- // copy data to buffer +- auto length = pbuf_copy_partial(p, (void*)send_buf, p->tot_len, 0); +- assert(length == p->tot_len); +- pbuf_free(p); +- m_sending_len += length; +- m_tun_session->out_async_send((const uint8_t*)send_buf, length, [this, length](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- close_client(true); +- } else { +- if (!m_closed) { +- tcp_recved(m_pcb, length); +- m_sent_len += length; +- } +- } +- }); +- } +- +- return ERR_OK; +-} +- +-err_t lwip_tcp_client::client_sent_func(struct tcp_pcb*, u16_t len) { +- +- if (m_aborted) { +- return ERR_ABRT; +- } +- +- m_recved_len += len; +- m_tun_session->recv_buf_ack_sent(len); +- +- if (m_tun_session->is_destroyed()) { +- if (m_tun_session->recv_buf_ack_length() > 0) { +- if (client_socks_recv_send_out() < 0) { +- return ERR_ABRT; +- } +- +- return ERR_OK; +- } +- output_debug_info(); +- close_client(false); +- return ERR_OK; +- } +- +- if (client_socks_recv_send_out() < 0) { +- return ERR_ABRT; +- } +- +- return ERR_OK; +-} +- +-int lwip_tcp_client::client_socks_recv_send_out() { +- if (m_aborted) { +- return -1; +- } +- +- if (m_closed) { +- return 0; +- } +- +- auto recv_size = m_tun_session->recv_buf_size(); +- if (recv_size == 0) { +- return 0; +- } +- +- const auto* recv_data = m_tun_session->recv_buf(); +- size_t wrote_size = 0; +- do { +- +- auto to_write = min(recv_size, (size_t)tcp_sndbuf(m_pcb)); +- if (to_write == 0) { +- break; +- } +- +- err_t err = tcp_write(m_pcb, (const void*)(recv_data + wrote_size), (uint16_t)to_write, TCP_WRITE_FLAG_COPY); +- if (err != ERR_OK) { +- if (err == ERR_MEM) { +- break; +- } +- +- client_log("tcp_write failed (%d)", (int)err); +- close_client(true); +- return -1; +- } +- +- recv_size -= to_write; +- wrote_size += to_write; +- } while (recv_size > 0); +- +- // start sending now +- err_t err = tcp_output(m_pcb); +- if (err != ERR_OK) { +- client_log("tcp_output failed (%d)", (int)err); +- close_client(true); +- return -1; +- } +- +- m_output_len += wrote_size; +- m_tun_session->recv_buf_consume((uint16_t)wrote_size); +- return 0; +-} +- +-void lwip_tcp_client::close_session() { +- if (m_closed || m_aborted) { +- return; +- } +- +- m_closed = true; +- +- // remove callbacks +- tcp_err(m_pcb, nullptr); +- tcp_recv(m_pcb, nullptr); +- tcp_sent(m_pcb, nullptr); +- +- if (!m_tun_session->is_destroyed()) { +- output_debug_info(); +- m_tun_session->destroy(true); +- } +- +- client_log("close_session (output: %u, recved: %u), (sending: %u, sent: %u)", m_output_len, m_recved_len, +- m_sending_len, m_sent_len); +-} +- +-void lwip_tcp_client::close_client(bool _abort, bool _owner_call /*= false*/) { +- if (m_closed || m_aborted) { +- return; +- } +- +- close_session(); +- +- if (_abort) { +- client_log("close_client abort"); +- m_aborted = true; +- tcp_abort(m_pcb); +- } else { +- // free m_pcb +- err_t err = tcp_close(m_pcb); +- client_log("close_client"); +- if (err != ERR_OK) { +- client_log("tcp_close failed (%d)", err); +- m_aborted = true; +- // abort the PCB +- tcp_abort(m_pcb); +- } +- } +- +- release_client(_owner_call); +-} +- +-void lwip_tcp_client::release_client(bool _owner_call /*=false*/) { +- if (m_pcb != nullptr) { +- tcp_arg(m_pcb, nullptr); +- m_pcb = nullptr; +- +- if (!_owner_call && m_close_cb) { +- // this callback will trigger decontructor +- m_close_cb(this); +- } +- } +-} +diff --git a/src/tun/lwip_tcp_client.h b/src/tun/lwip_tcp_client.h +deleted file mode 100644 +index f10c32f..0000000 +--- a/src/tun/lwip_tcp_client.h ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_LWIP_TCP_CLIENT_HPP +-#define _TROJAN_LWIP_TCP_CLIENT_HPP +- +-#include +- +-#include +-#include +-#include +-#include +- +-#include "core/service.h" +-#include "tun/tunsession.h" +- +-class lwip_tcp_client : public std::enable_shared_from_this { +- +- static void static_client_err_func(void* arg, err_t err) { ((lwip_tcp_client*)arg)->client_err_func(err); } +- +- static err_t static_client_recv_func(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err) { +- return ((lwip_tcp_client*)arg)->client_recv_func(tpcb, p, err); +- } +- +- static err_t static_client_sent_func(void* arg, struct tcp_pcb* tpcb, uint16_t len) { +- return ((lwip_tcp_client*)arg)->client_sent_func(tpcb, len); +- } +- +- public: +- typedef std::function CloseCallback; +- +- private: +- boost::asio::ip::tcp::endpoint m_local_addr; +- boost::asio::ip::tcp::endpoint m_remote_addr; +- +- struct tcp_pcb* m_pcb; +- bool m_closed; +- bool m_aborted; +- +- size_t m_recved_len{}; +- size_t m_output_len{}; +- +- size_t m_sending_len{}; +- size_t m_sent_len{}; +- +- uint8_t send_buf[TCP_WND]{}; +- std::shared_ptr m_tun_session; +- CloseCallback m_close_cb; +- +- void close_session(); +- void release_client(bool _owner_call = false); +- void client_log(const char* fmt, ...); +- int client_socks_recv_send_out(); +- +- void client_err_func(err_t err); +- err_t client_recv_func(struct tcp_pcb* tpcb, struct pbuf* p, err_t err); +- err_t client_sent_func(struct tcp_pcb* tpcb, u16_t len); +- +- public: +- lwip_tcp_client(struct tcp_pcb* _pcb, std::shared_ptr _session, CloseCallback&& _close_cb); +- void close_client(bool _abort, bool _owner_call = false); +-}; +-#endif //_TROJAN_LWIP_TCP_CLIENT_HPP +\ No newline at end of file +diff --git a/src/tun/tundev.cpp b/src/tun/tundev.cpp +deleted file mode 100644 +index 116f0b8..0000000 +--- a/src/tun/tundev.cpp ++++ /dev/null +@@ -1,644 +0,0 @@ +- +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tundev.h" +- +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include "proto/ipv4_header.h" +-#include "proto/ipv6_header.h" +- +-#include "core/log.h" +-#include "core/service.h" +-#include "tun/dnsserver.h" +-#include "tun/lwip_tcp_client.h" +-#include "tun/tunlocalsession.h" +-#include "tun/tunproxysession.h" +-#include "tun/tunsession.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-// clang-format off +-static const uint32_t mask_values[] = { +- 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, +- 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, +- 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, +- 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, +- 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, +- 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, +- 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, +- 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, +-}; +-// clang-format on +- +-static void tcp_remove(struct tcp_pcb* pcb_list) { +- struct tcp_pcb* pcb = pcb_list; +- struct tcp_pcb* pcb2 = nullptr; +- +- while (pcb != nullptr) { +- pcb2 = pcb; +- pcb = pcb->next; +- tcp_abort(pcb2); +- } +-} +- +-TUNDev* TUNDev::sm_tundev = nullptr; +- +-TUNDev::TUNDev(Service* _service, const std::string& _tun_name, const std::string& _ipaddr, const std::string& _netmask, +- uint16_t _mtu, int _outside_tun_fd) +- : m_netif_configured(false), +- m_tcp_listener(nullptr), +- m_service(_service), +- m_tun_fd(_outside_tun_fd), +- m_is_outside_tun_fd(_outside_tun_fd != -1), +- m_mtu(_mtu), +- m_quitting(false), +- m_boost_sd(_service->get_io_context()) { +- +- assert(sm_tundev == nullptr); +- sm_tundev = this; +- +- if (m_tun_fd == -1) { +-#ifdef __linux__ +- // open TUN device, check detail information: +- // https://www.kernel.org/doc/Documentation/networking/tuntap.txt +- if ((m_tun_fd = open("/dev/net/tun", O_RDWR)) < 0) { +- throw runtime_error("[tun] error opening device"); +- } +- +- struct ifreq ifr {}; +- ifr.ifr_flags = IFF_NO_PI | IFF_TUN; +- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", _tun_name.c_str()); +- +- if (ioctl(m_tun_fd, TUNSETIFF, (void*)&ifr) < 0) { +- throw runtime_error("[tun] error configuring device"); +- } +- +- _log_with_date_time("[tun] /dev/net/tun ifr.ifr_mtu: " + to_string(ifr.ifr_mtu), Log::WARN); +-#else +- throw logic_error("[tun] cannot enable tun run type in NON-linux system ! " + _tun_name); +-#endif //__linux__ +- } +- +- m_boost_sd.assign(m_tun_fd); +- +- // init lwip +- lwip_init(); +- +- // make addresses for netif +- ip4_addr_t addr; +- addr.addr = make_address_v4(_ipaddr).to_uint(); +- +- ip4_addr_t netmask; +- netmask.addr = make_address_v4(_netmask).to_uint(); +- +- ip4_addr_t gw; +- ip4_addr_set_any(&gw); +- +- // init netif +- if (netif_add(&m_netif, &addr, &netmask, &gw, nullptr, (netif_init_fn)static_netif_init_func, +- (netif_input_fn)static_netif_input_func) == nullptr) { +- throw runtime_error("[tun] netif_add failed"); +- } +- +- // set netif up +- netif_set_up(&m_netif); +- +- // set netif link up, otherwise ip route will refuse to route +- netif_set_link_up(&m_netif); +- +- // set netif pretend TCP +- netif_set_pretend_tcp(&m_netif, 1); +- +- // set netif default +- netif_set_default(&m_netif); +- +- m_netif_configured = true; +- +- // init listener +- struct tcp_pcb* l = tcp_new_ip_type(IPADDR_TYPE_V4); +- if (l == nullptr) { +- throw runtime_error("[tun] tcp_new_ip_type failed"); +- } +- +- // bind listener +- if (tcp_bind_to_netif(l, "ho0") != ERR_OK) { +- tcp_close(l); +- throw runtime_error("[tun] tcp_bind_to_netif failed"); +- } +- +- tcp_bind_netif(l, &m_netif); +- +- // listen listener +- m_tcp_listener = tcp_listen(l); +- if (m_tcp_listener == nullptr) { +- tcp_close(l); +- throw runtime_error("[tun] tcp_listen failed"); +- } +- +- tcp_arg(m_tcp_listener, this); +- +- // setup listener accept handler +- tcp_accept(m_tcp_listener, static_listener_accept_func); +- +- async_read(); +-} +- +-TUNDev::~TUNDev() { +- if (m_quitting) { +- return; +- } +- +- m_quitting = true; +- +- _log_with_date_time("[tun] destoryed, clear all tcp_clients: " + to_string(m_tcp_clients.size()) + +- " udp_clients: " + to_string(m_udp_clients.size()), +- Log::INFO); +- +- for (auto& it : m_tcp_clients) { +- it->close_client(true, true); +- } +- m_tcp_clients.clear(); +- +- for (auto& it : m_udp_clients) { +- it->set_close_from_tundev_flag(); +- it->destroy(); +- } +- m_udp_clients.clear(); +- +- // free listener +- if (m_tcp_listener != nullptr) { +- tcp_close(m_tcp_listener); +- } +- +- // free netif +- if (m_netif_configured) { +- netif_remove(&m_netif); +- m_netif_configured = false; +- } +- +- tcp_remove(tcp_bound_pcbs); +- tcp_remove(tcp_active_pcbs); +- tcp_remove(tcp_tw_pcbs); +- +- if (m_tun_fd != -1 && !m_is_outside_tun_fd) { +- m_boost_sd.close(); +- } else { +- m_boost_sd.release(); +- } +- +- sm_tundev = nullptr; +-} +- +-err_t TUNDev::netif_init_func(struct netif* netif) const { +- netif->name[0] = 'h'; +- netif->name[1] = 'o'; +- netif->mtu = m_mtu; +- netif->output = static_netif_output_func; +- return ERR_OK; +-} +- +-err_t TUNDev::netif_input_func(struct pbuf* p, struct netif* inp) { +- uint8_t ip_version = 0; +- if (p->len > 0) { +- ip_version = (((uint8_t*)p->payload)[0] >> half_byte_shift_4_bits); +- } +- +- switch (ip_version) { +- case IPV4: { +- return ip_input(p, inp); +- } break; +- case IPV6: { +- // throw runtime_error("haven't supported ipv6"); +- } break; +- } +- +- pbuf_free(p); +- return ERR_OK; +-} +- +-err_t TUNDev::netif_output_func(struct netif*, struct pbuf* p, const ip4_addr_t*) { +- if (m_quitting) { +- return ERR_OK; +- } +- +- if (p != nullptr) { +- if (p->next == nullptr && p->len <= m_mtu) { +- boost::system::error_code ec; +- m_boost_sd.write_some(boost::asio::buffer(p->payload, p->len), ec); +- if (ec) { +- output_debug_info_ec(ec); +- } +- } else { +- do { +- if (p->len > 0) { +- auto* write_buff = boost::asio::buffer_cast(m_write_fill_buf.prepare(p->len)); +- memcpy(write_buff, (uint8_t*)p->payload, p->len); +- m_write_fill_buf.commit(p->len); +- } +- } while ((p = p->next) != nullptr); +- +- write_to_tun(); +- } +- } +- +- return ERR_OK; +-} +- +-bool TUNDev::is_in_ips(uint32_t ip, const Config::IPList& ips, const Config::IPSubnetList& subnet) { +- if (!ips.empty() && binary_search(ips.cbegin(), ips.cend(), ip)) { +- return true; +- } +- +- for (const auto& sub : subnet) { +- uint32_t net = ip & gsl::at(mask_values, sub.first); +- if (binary_search(sub.second.cbegin(), sub.second.cend(), net)) { +- return true; +- } +- } +- +- return false; +-} +- +-bool TUNDev::proxy_by_route(uint32_t ip) const { +- auto route = m_service->get_config().get_route(); +- if (is_in_ips(ip, route._proxy_ips, route._proxy_ips_subnet)) { +- return true; +- } +- +- if (is_in_ips(ip, route._white_ips, route._white_ips_subnet)) { +- return false; +- } +- +- switch (route.proxy_type) { +- case Config::route_all: // Controlled by route tables +- case Config::route_bypass_local: // Controlled by route tables +- return true; +- case Config::route_bypass_cn_mainland: +- case Config::route_bypass_local_and_cn_mainland: // Local ips Controlled by route tables +- return !is_in_ips(ip, route._cn_mainland_ips, route._cn_mainland_ips_subnet); +- case Config::route_gfwlist: +- return m_dns_server != nullptr && m_dns_server->is_ip_in_gfwlist(ip); +- case Config::route_cn_mainland: +- return is_in_ips(ip, route._cn_mainland_ips, route._cn_mainland_ips_subnet); +- default: +- throw logic_error("[dns] error proxy type: " + to_string((int)route.proxy_type)); +- } +-} +- +-err_t TUNDev::listener_accept_func(struct tcp_pcb* newpcb, err_t err) { +- +- if (err != ERR_OK) { +- return err; +- } +- +- shared_ptr session = nullptr; +- if (proxy_by_route(ntoh32(newpcb->local_ip.u_addr.ip4.addr))) { +- session = make_shared(m_service, false); +- } else { +- session = make_shared(m_service, false); +- } +- auto tcp_client = make_shared(newpcb, session, [this](lwip_tcp_client* client) { +- for (auto it = m_tcp_clients.begin(); it != m_tcp_clients.end(); it++) { +- if (it->get() == client) { +- m_tcp_clients.erase(it); +- break; +- } +- } +- }); +- +- m_service->start_session(session, [this, session, tcp_client](boost::system::error_code ec) { +- if (!ec) { +- session->start(); +- m_tcp_clients.emplace_back(tcp_client); +- } else { +- session->destroy(); +- tcp_client->close_client(true); +- } +- }); +- +- // start_session callback immediately and destory the session +- return session->is_destroyed() ? ERR_ABRT : ERR_OK; +-} +- +-void TUNDev::input_netif_packet(const uint8_t* data, uint16_t packet_len) { +- struct pbuf* p = pbuf_alloc(PBUF_RAW, packet_len, PBUF_POOL); +- if (p == nullptr) { +- _log_with_date_time("[tun] device read: pbuf_alloc failed", Log::ERROR); +- return; +- } +- +- // write packet to pbuf +- if (pbuf_take(p, (void*)data, packet_len) != ERR_OK) { +- _log_with_date_time("[tun] device read: pbuf_take failed", Log::ERROR); +- pbuf_free(p); +- return; +- } +- +- // pass pbuf to input +- if (m_netif.input(p, &m_netif) != ERR_OK) { +- _log_with_date_time("[tun] device read: input failed", Log::ERROR); +- pbuf_free(p); +- return; +- } +-} +- +-void TUNDev::parse_packet() { +- if (m_packet_parse_buff.empty()) { +- // need more byte for version +- return; +- } +- +- auto* data = (uint8_t*)m_packet_parse_buff.c_str(); +- auto data_len = m_packet_parse_buff.length(); +- auto ip_version = (data[0] >> half_byte_shift_4_bits) & half_byte_mask_0xF; +- +- if (ip_version == IPV4 || ip_version == IPV6) { +- +- uint16_t total_length = 0; +- +- if (ip_version == IPV4) { +- if (data_len < sizeof(struct ipv4_header)) { +- return; +- } +- struct ipv4_header ipv4_hdr; +- memcpy(&ipv4_hdr, data, sizeof(ipv4_hdr)); +- total_length = ntoh16(ipv4_hdr.total_length); +- +- //_log_with_date_time("parse_packet length:" + to_string(data_len) + " ipv4 protocol: " +- //+ +- // to_string((int)ipv4_hdr.protocol) + " total_length: " + to_string(total_length)); +- +- } else { +- if (data_len < sizeof(struct ipv6_header)) { +- return; +- } +- struct ipv6_header ipv6_hdr; +- memcpy(&ipv6_hdr, data, sizeof(ipv6_hdr)); +- total_length = ntoh16(ipv6_hdr.payload_length) + sizeof(ipv6_hdr); +- +- //_log_with_date_time("parse_packet length:" + to_string(data_len) + " ipv6 next header: +- //" + +- // to_string((int)ipv6_hdr.next_header) + " total_length: " + to_string(total_length)); +- } +- +- if (total_length <= data_len) { +- auto result = try_to_process_udp_packet(data, (int)total_length); +- if (result == 0) { +- input_netif_packet(data, total_length); +- } +- +- if (data_len == total_length) { +- //_log_with_date_time("full packet process"); +- m_packet_parse_buff.clear(); +- } else { +- //_log_with_date_time("split packet process--------------"); +- m_packet_parse_buff = m_packet_parse_buff.substr(total_length); +- parse_packet(); +- } +- } +- +- } else { +- m_packet_parse_buff.clear(); +- } +-} +- +-int TUNDev::handle_write_upd_data(const TUNSession* _session, string_view& data_str) { +- assert(_session->is_udp_forward_session()); +- +- auto data_len = data_str.length(); +- if (data_len == 0) { +- return 0; +- } +- const auto* data = (const uint8_t*)data_str.data(); +- auto header_length = (uint16_t)(sizeof(struct ipv4_header) + sizeof(struct udp_header)); +- auto max_len = min(numeric_limits::max(), m_mtu); +- max_len = max_len - header_length; +- if (data_len > max_len) { +- data_len = max_len; +- } +- +- auto local_endpoint = _session->get_udp_local_endpoint(); +- auto remote_endpoint = _session->get_udp_remote_endpoint(); +- +- auto* local_addr = (struct sockaddr_in*)local_endpoint.data(); +- auto* remote_addr = (struct sockaddr_in*)remote_endpoint.data(); +- +- // build IP header +- struct ipv4_header ipv4_hdr; +- ipv4_hdr.version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(ipv4_hdr)); +- ipv4_hdr.ds = hton8(0); +- ipv4_hdr.total_length = hton16(uint16_t(sizeof(ipv4_hdr) + sizeof(struct udp_header) + data_len)); +- ipv4_hdr.identification = hton16(0); +- ipv4_hdr.flags3_fragmentoffset13 = hton16(0); +- ipv4_hdr.ttl = hton8(Default_UDP_TTL); +- ipv4_hdr.protocol = hton8(IPV4_PROTOCOL_UDP); +- ipv4_hdr.checksum = hton16(0); +- ipv4_hdr.source_address = (remote_addr->sin_addr.s_addr); +- ipv4_hdr.destination_address = (local_addr->sin_addr.s_addr); +- ipv4_hdr.checksum = ipv4_checksum(&ipv4_hdr, nullptr, 0); +- +- // build UDP header +- struct udp_header udp_hdr; +- udp_hdr.source_port = hton16(remote_endpoint.port()); +- udp_hdr.dest_port = hton16(local_endpoint.port()); +- udp_hdr.length = hton16(uint16_t(sizeof(udp_hdr) + data_len)); +- udp_hdr.checksum = hton16(0); +- udp_hdr.checksum = +- udp_checksum(&udp_hdr, data, (uint16_t)data_len, ipv4_hdr.source_address, ipv4_hdr.destination_address); +- +- // compose packet +- auto packat_length = header_length + data_len; +- auto* write_buf = boost::asio::buffer_cast(m_write_fill_buf.prepare(packat_length)); +- +- memcpy(write_buf, &ipv4_hdr, sizeof(ipv4_hdr)); +- memcpy(write_buf + sizeof(ipv4_hdr), &udp_hdr, sizeof(udp_hdr)); +- memcpy(write_buf + sizeof(ipv4_hdr) + sizeof(udp_hdr), data, data_len); +- +- m_write_fill_buf.commit(packat_length); +- +- _log_with_endpoint_ALL(local_endpoint, "<- " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()) + " length:" + to_string(data_len)); +- +- write_to_tun(); +- +- data_str = data_str.substr(data_len); +- if (data_str.length() > 0) { +- handle_write_upd_data(_session, data_str); +- } +- +- return 0; +-} +- +-int TUNDev::try_to_process_udp_packet(uint8_t* data, int data_len) { +- uint8_t ip_version = 0; +- if (data_len > 0) { +- ip_version = (data[0] >> half_byte_shift_4_bits) & half_byte_mask_0xF; +- } +- +- if (ip_version == IPV4) { +- // ignore non-UDP packets +- if (data_len < (int)sizeof(struct ipv4_header) || +- data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) { +- return 0; +- } +- +- // parse IPv4 header +- struct ipv4_header ipv4_hdr; +- if (ipv4_check(data, data_len, &ipv4_hdr, &data, &data_len) == 0) { +- return 1; +- } +- +- // parse UDP +- struct udp_header udp_hdr; +- if (udp_check(data, data_len, &udp_hdr, &data, &data_len) == 0) { +- return 1; +- } +- +- // verify UDP checksum +- uint16_t checksum_in_packet = udp_hdr.checksum; +- udp_hdr.checksum = 0; +- uint16_t checksum_computed = +- udp_checksum(&udp_hdr, data, data_len, ipv4_hdr.source_address, ipv4_hdr.destination_address); +- if (checksum_in_packet != checksum_computed) { +- return 1; +- } +- +- auto local_endpoint = udp::endpoint( +- make_address_v4((address_v4::uint_type)ntoh32(ipv4_hdr.source_address)), ntoh16(udp_hdr.source_port)); +- +- auto remote_endpoint = udp::endpoint( +- make_address_v4((address_v4::uint_type)ntoh32(ipv4_hdr.destination_address)), ntoh16(udp_hdr.dest_port)); +- +- _log_with_endpoint_ALL(local_endpoint, " -> " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()) + +- " [tun] length:" + to_string(data_len)); +- +- for (auto& it : m_udp_clients) { +- if (it->try_to_process_udp(local_endpoint, remote_endpoint, data, data_len)) { +- return 1; +- } +- } +- +- shared_ptr session = nullptr; +- if (proxy_by_route(ntoh32(ipv4_hdr.destination_address))) { +- session = make_shared(m_service, true); +- } else { +- session = make_shared(m_service, true); +- } +- session->set_udp_connect(local_endpoint, remote_endpoint); +- session->set_write_to_lwip([this](const TUNSession* _se, string_view* _data) { +- assert(_data != nullptr); +- return handle_write_upd_data(_se, *_data); +- }); +- +- session->set_close_callback([this](TUNSession* _session) { +- for (auto it = m_udp_clients.begin(); it != m_udp_clients.end(); it++) { +- if (it->get() == _session) { +- m_udp_clients.erase(it); +- break; +- } +- } +- }); +- +- session->out_async_send(data, data_len, [](boost::system::error_code) {}); // send as buf +- m_udp_clients.emplace_back(session); +- +- _log_with_endpoint(local_endpoint, +- "TUNDev start to connected " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()), +- Log::INFO); +- +- m_service->start_session(session, [session, local_endpoint, remote_endpoint](boost::system::error_code ec) { +- if (!ec) { +- session->start(); +- } else { +- output_debug_info_ec(ec); +- session->destroy(); +- } +- }); +- +- return 1; +- } +- +- if (ip_version == IPV6) { +- // TODO +- } +- +- return 0; +-} +- +-void TUNDev::write_to_tun() { +- if (m_quitting) { +- return; +- } +- +- while (m_write_fill_buf.size() > 0) { +- boost::system::error_code ec; +- size_t wrote = 0; +- if (m_write_fill_buf.size() > m_mtu) { +- auto copied = boost::asio::buffer_copy(m_writing_buf.prepare(m_mtu), m_write_fill_buf.data(), m_mtu); +- m_writing_buf.commit(copied); +- +- wrote = m_boost_sd.write_some(m_writing_buf.data(), ec); +- m_writing_buf.consume(m_writing_buf.size()); +- } else { +- wrote = m_boost_sd.write_some(m_write_fill_buf.data(), ec); +- } +- +- if (!ec && wrote > 0) { +- m_write_fill_buf.consume(wrote); +- } else { +- m_write_fill_buf.consume(m_write_fill_buf.size()); +- } +- } +-} +- +-void TUNDev::async_read() { +- m_sd_read_buffer.consume(m_sd_read_buffer.size()); +- m_boost_sd.async_read_some(m_sd_read_buffer.prepare(m_mtu), [this](boost::system::error_code ec, size_t data_len) { +- if (m_quitting) { +- return; +- } +- +- if (!ec) { +- m_sd_read_buffer.commit(data_len); +- +- const auto* data = boost::asio::buffer_cast(m_sd_read_buffer.data()); +- m_packet_parse_buff.append(data, data_len); +- +- parse_packet(); +- } +- +- async_read(); +- }); +- +- // sleep for test +- //::sleep(1); +-} +\ No newline at end of file +diff --git a/src/tun/tundev.h b/src/tun/tundev.h +deleted file mode 100644 +index 83ca4ec..0000000 +--- a/src/tun/tundev.h ++++ /dev/null +@@ -1,146 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_TUNDEV_HPP +-#define _TROJAN_TUNDEV_HPP +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef __linux__ +-#include +-#include +-#endif +- +-#include +-#include +-#include +- +-#include "core/config.h" +- +-#ifndef _WIN32 +-using BoostStreamDescriptor = boost::asio::posix::stream_descriptor; +-#else +-class BoostStreamDescriptor { +- public: +- BoostStreamDescriptor(boost::asio::io_context&) {} +- void assign(int) {} +- +- template +- std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { +- return 0; +- } +- +- template +- void async_read_some(const ConstBufferSequence&, Handler&&) {} +- +- void close() {} +- void release() {} +-}; +-#endif +- +-class Service; +-class lwip_tcp_client; +-class TUNSession; +-class DNSServer; +-// this class canot support ipv6 +-class TUNDev { +- +- enum IPVersion { IPV4 = 4, IPV6 = 6 }; +- enum DefaultVar { Default_UDP_TTL = 60 }; +- +- static TUNDev* sm_tundev; +- static err_t static_netif_init_func(struct netif* netif) { return sm_tundev->netif_init_func(netif); } +- +- static err_t static_netif_input_func(struct pbuf* p, struct netif* inp) { +- return sm_tundev->netif_input_func(p, inp); +- } +- +- static err_t static_netif_output_func(struct netif* netif, struct pbuf* p, const ip4_addr_t* ipaddr) { +- return sm_tundev->netif_output_func(netif, p, ipaddr); +- } +- +- static err_t static_listener_accept_func(void* arg, struct tcp_pcb* newpcb, err_t err) { +- return ((TUNDev*)arg)->listener_accept_func(newpcb, err); +- } +- +- // lwip TUN netif device handler +- struct netif m_netif {}; +- bool m_netif_configured; +- +- // lwip TCP listener +- struct tcp_pcb* m_tcp_listener; +- +- err_t netif_init_func(struct netif* netif) const; +- err_t netif_input_func(struct pbuf* p, struct netif* inp); +- err_t netif_output_func(struct netif* netif, struct pbuf* p, const ip4_addr_t* ipaddr); +- +- err_t listener_accept_func(struct tcp_pcb* newpcb, err_t err); +- +- private: +- std::list> m_tcp_clients; +- std::list> m_udp_clients; +- +- Service* m_service; +- std::shared_ptr m_dns_server; +- int m_tun_fd; +- const bool m_is_outside_tun_fd; +- uint16_t m_mtu; +- +- bool m_quitting; +- boost::asio::streambuf m_write_fill_buf; +- boost::asio::streambuf m_writing_buf; +- +- boost::asio::streambuf m_sd_read_buffer; +- BoostStreamDescriptor m_boost_sd; +- +- std::string m_packet_parse_buff; +- +- void async_read(); +- void write_to_tun(); +- +- int try_to_process_udp_packet(uint8_t* data, int data_len); +- void parse_packet(); +- void input_netif_packet(const uint8_t* data, uint16_t packet_len); +- int handle_write_upd_data(const TUNSession* _session, std::string_view& data); +- +- [[nodiscard]] static bool is_in_ips(uint32_t ip, const Config::IPList& ips, const Config::IPSubnetList& subnet); +- [[nodiscard]] bool proxy_by_route(uint32_t ip) const; +- +- public: +- TUNDev(Service* _service, const std::string& _tun_name, const std::string& _ipaddr, const std::string& _netmask, +- uint16_t _mtu, int _outside_tun_fd = -1); +- ~TUNDev(); +- +- void set_dns_server(std::shared_ptr dns) { m_dns_server = std::move(dns); } +- [[nodiscard]] int get_tun_fd() const { return m_tun_fd; } +-}; +-#endif //_TROJAN_TUNDEV_HPP +diff --git a/src/tun/tunlocalsession.cpp b/src/tun/tunlocalsession.cpp +deleted file mode 100644 +index 04a2f02..0000000 +--- a/src/tun/tunlocalsession.cpp ++++ /dev/null +@@ -1,215 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/tunlocalsession.h" +-#include "core/service.h" +-#include "core/utils.h" +-#include "tun/udplocalforwarder.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-TUNLocalSession::TUNLocalSession(Service* _service, bool is_udp) +- : TUNSession(_service, is_udp), m_resolver(_service->get_io_context()), m_tcp_socket(_service->get_io_context()) { +- if (!is_udp) { +- m_sending_data_cache.set_is_connected_func([this]() { return !m_destroyed && m_connected; }); +- m_sending_data_cache.set_async_writer([this](const boost::asio::streambuf& data, SentHandler&& handler) { +- auto self = shared_from_this(); +- boost::asio::async_write( +- m_tcp_socket, data.data(), [this, self, handler](const boost::system::error_code error, size_t length) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } +- +- get_stat().inc_sent_len(length); +- handler(error); +- }); +- }); +- } +-} +- +-void TUNLocalSession::start() { +- if (is_udp_forward_session()) { +- auto remote_addr = get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp; +- m_udp_forwarder = make_shared( +- get_service(), m_local_addr_udp, remote_addr, +- [this](const udp::endpoint&, const string_view& data) { +- if (m_write_to_lwip(this, (string_view*)&data) < 0) { +- output_debug_info(); +- destroy(); +- } +- }, +- false); +- +- m_udp_forwarder->set_destroy_callback([this]() { +- output_debug_info(); +- destroy(); +- }); +- +- m_udp_forwarder->start(); +- +- if (m_send_buf.size() != 0) { +- if (m_udp_forwarder->process(m_local_addr_udp, streambuf_to_string_view(m_send_buf))) { +- m_connected = true; +- } +- } else if (!m_udp_forwarder->is_destroyed()) { +- m_connected = true; +- } +- +- } else { +- auto remote_addr = +- get_config().get_tun().redirect_local ? LOCALHOST_IP_ADDRESS : m_remote_addr.address().to_string(); +- auto self = shared_from_this(); +- connect_out_socket(this, remote_addr, to_string(m_remote_addr.port()), m_resolver, m_tcp_socket, +- m_local_addr_udp, [this, self]() { +- m_connected = true; +- +- if (m_send_buf.size() != 0) { +- out_async_send_impl(streambuf_to_string_view(m_send_buf), [this, self](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- if (!m_wait_connected_handler.empty()) { +- for (auto& h : m_wait_connected_handler) { +- h(boost::system::error_code()); +- } +- m_wait_connected_handler.clear(); +- } +- out_async_read(); +- }); +- } else { +- out_async_read(); +- } +- }); +- } +-} +- +-void TUNLocalSession::recv_buf_consume(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf.consume(_length); +- +- if (m_recv_buf.size() == 0) { +- out_async_read(); +- } +-} +- +-void TUNLocalSession::recv_buf_ack_sent(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf_ack_length -= _length; +-} +- +-void TUNLocalSession::out_async_read() { +- if (!is_udp_forward_session()) { +- m_recv_buf.begin_read(__FILE__, __LINE__); +- auto self = shared_from_this(); +- m_tcp_socket.async_read_some(m_recv_buf.prepare(Session::MAX_BUF_LENGTH), +- [this, self](const boost::system::error_code error, size_t length) { +- m_recv_buf.end_read(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- m_recv_buf.commit(length); +- get_stat().inc_recv_len(length); +- +- m_recv_buf_ack_length += length; +- +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- }); +- } +-} +- +-void TUNLocalSession::out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler) { +- if (is_udp_forward_session()) { +- if (m_udp_forwarder->process(m_local_addr_udp, data_to_send)) { +- _handler(boost::system::error_code()); +- } else { +- _handler(boost::asio::error::broken_pipe); +- } +- } else { +- m_sending_data_cache.push_data( +- [&](boost::asio::streambuf& buf) { streambuf_append(buf, data_to_send); }, move(_handler)); +- } +-} +- +-void TUNLocalSession::out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) { +- if (!m_connected) { +- if (m_send_buf.size() < numeric_limits::max()) { +- streambuf_append(m_send_buf, _data, _length); +- m_wait_connected_handler.emplace_back(_handler); +- } else { +- output_debug_info(); +- destroy(); +- } +- } else { +- out_async_send_impl(string_view((const char*)_data, _length), move(_handler)); +- } +-} +- +-void TUNLocalSession::destroy(bool /*= false*/) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- auto note_str = "TUNLocalSession disconnected, " + get_stat().to_string(); +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- +- m_wait_ack_handler.clear(); +- +- if (m_udp_forwarder && !m_udp_forwarder->is_destroyed()) { +- m_udp_forwarder->destroy(); +- } +- +- if (m_tcp_socket.is_open()) { +- boost::system::error_code ec; +- m_tcp_socket.cancel(ec); +- m_tcp_socket.shutdown(tcp::socket::shutdown_both, ec); +- m_tcp_socket.close(ec); +- } +- +- if (!m_close_from_tundev_flag) { +- m_close_cb(this); +- } +-} +- +-bool TUNLocalSession::try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) { +- if (is_udp_forward_session()) { +- if (_local == m_local_addr_udp && _remote == m_remote_addr_udp) { +- return m_udp_forwarder->process(_local, string_view((const char*)payload, payload_length)); +- } +- } +- +- return false; +-} +\ No newline at end of file +diff --git a/src/tun/tunlocalsession.h b/src/tun/tunlocalsession.h +deleted file mode 100644 +index 4555ca1..0000000 +--- a/src/tun/tunlocalsession.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUN_LOCAL_SESSION_H_ +-#define _TUN_LOCAL_SESSION_H_ +- +-#include "tun/tunsession.h" +-#include "tun/udplocalforwarder.h" +- +-class TUNLocalSession : public TUNSession { +- +- std::shared_ptr m_udp_forwarder; +- +- boost::asio::ip::tcp::resolver m_resolver; +- boost::asio::ip::tcp::socket m_tcp_socket; +- +- void out_async_read(); +- void out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler); +- +- public: +- TUNLocalSession(Service* service, bool udp); +- +- // common interfaces +- void start() override; +- void destroy(bool pipeline_call = false) override; +- void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) override; +- +- // interfaces for TCP +- void recv_buf_consume(uint16_t _length) override; +- void recv_buf_ack_sent(uint16_t _length) override; +- +- // interfaces for UDP +- bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote, +- const uint8_t* payload, size_t payload_length) override; +-}; +- +-#endif //_TUN_LOCAL_SESSION_H_ +diff --git a/src/tun/tunproxysession.cpp b/src/tun/tunproxysession.cpp +deleted file mode 100644 +index 6f8d4a5..0000000 +--- a/src/tun/tunproxysession.cpp ++++ /dev/null +@@ -1,409 +0,0 @@ +- +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/tunproxysession.h" +- +-#include +-#include +-#include +- +-#include "core/service.h" +-#include "core/utils.h" +-#include "proto/trojanrequest.h" +-#include "proto/udppacket.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-TUNProxySession::TUNProxySession(Service* _service, bool _is_udp) +- : TUNSession(_service, _is_udp), +- m_out_socket(_service->get_io_context(), _service->get_ssl_context()), +- m_out_resolver(_service->get_io_context()) { +- +- get_pipeline_component().allocate_session_id(); +- +- m_sending_data_cache.set_is_connected_func([this]() { return !is_destroyed() && m_connected; }); +- m_sending_data_cache.set_async_writer([this](const boost::asio::streambuf& data, SentHandler&& handler) { +- auto self = shared_from_this(); +- boost::asio::async_write( +- m_out_socket, data.data(), [this, self, handler](const boost::system::error_code error, size_t length) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } +- +- get_stat().inc_sent_len(length); +- +- handler(error); +- }); +- }); +-} +- +-TUNProxySession::~TUNProxySession() { get_pipeline_component().free_session_id(); } +- +-void TUNProxySession::start() { +- udp_timer_async_wait(); +- auto self = shared_from_this(); +- auto cb = [this, self]() { +- m_connected = true; +- +- if (!get_service()->is_use_pipeline()) { +- boost::system::error_code ec; +- auto endpoint = m_out_socket.next_layer().local_endpoint(ec); +- _log_with_endpoint( +- endpoint, "TUNProxySession session_id: " + to_string(get_session_id()) + " started", Log::INFO); +- } else { +- auto note_str = "TUNProxySession session_id: " + to_string(get_session_id()) + " started in pipeline"; +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- } +- auto insert_pwd = [this]() { +- if (is_udp_forward_session()) { +- streambuf_append( +- m_send_buf, TrojanRequest::generate(get_config().get_password().cbegin()->first, +- get_config().get_tun().redirect_local ? LOCALHOST_IP_ADDRESS +- : m_remote_addr_udp.address().to_string().c_str(), +- m_remote_addr_udp.port(), false)); +- } else { +- auto remote_addr = m_remote_addr.address().to_string(); +- if (get_config().get_tun().redirect_local) { +- _log_with_date_time(remote_addr + " redirect to local for test"); +- remote_addr = LOCALHOST_IP_ADDRESS; +- } +- streambuf_append(m_send_buf, TrojanRequest::generate(get_config().get_password().cbegin()->first, +- remote_addr, m_remote_addr.port(), true)); +- } +- }; +- +- if (m_send_buf.size() > 0) { +- boost::asio::streambuf tmp_buf; +- streambuf_append(tmp_buf, m_send_buf); +- m_send_buf.consume(m_send_buf.size()); +- insert_pwd(); +- streambuf_append(m_send_buf, tmp_buf); +- } else { +- insert_pwd(); +- } +- +- out_async_send_impl(streambuf_to_string_view(m_send_buf), [this](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- if (!m_wait_connected_handler.empty()) { +- for (auto& h : m_wait_connected_handler) { +- h(boost::system::error_code()); +- } +- m_wait_connected_handler.clear(); +- } +- out_async_read(); +- }); +- m_send_buf.consume(m_send_buf.size()); +- }; +- +- if (get_service()->is_use_pipeline()) { +- cb(); +- } else { +- get_service()->get_config().prepare_ssl_reuse(m_out_socket); +- if (is_udp_forward_session()) { +- connect_remote_server_ssl(this, get_service()->get_config().get_remote_addr(), +- to_string(get_service()->get_config().get_remote_port()), m_out_resolver, m_out_socket, m_local_addr_udp, +- cb); +- } else { +- connect_remote_server_ssl(this, get_service()->get_config().get_remote_addr(), +- to_string(get_service()->get_config().get_remote_port()), m_out_resolver, m_out_socket, m_local_addr, cb); +- } +- } +-} +- +-void TUNProxySession::destroy(bool pipeline_call) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- auto note_str = +- "TUNProxySession session_id: " + to_string(get_session_id()) + " disconnected, " + get_stat().to_string(); +- +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- +- m_wait_ack_handler.clear(); +- m_out_resolver.cancel(); +- udp_timer_cancel(); +- shutdown_ssl_socket(this, m_out_socket); +- +- if (!pipeline_call && get_service()->is_use_pipeline()) { +- get_service()->session_destroy_in_pipeline(*this); +- } +- +- if (!m_close_from_tundev_flag && m_close_cb) { +- m_close_cb(this); +- } +-} +- +-void TUNProxySession::recv_ack_cmd(size_t ack_count) { +- Session::recv_ack_cmd(ack_count); +- +- while (ack_count-- > 0) { +- if (!m_wait_ack_handler.empty()) { +- m_wait_ack_handler.front()(boost::system::error_code()); +- m_wait_ack_handler.pop_front(); +- } else { +- break; +- } +- } +-} +- +-void TUNProxySession::out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler) { +- if (get_service()->is_use_pipeline()) { +- auto data_sending_len = data_to_send.length(); +- auto self = shared_from_this(); +- get_service()->session_async_send_to_pipeline(*this, PipelineRequest::DATA, data_to_send, +- [this, self, _handler, data_sending_len](const boost::system::error_code error) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } else { +- get_stat().inc_sent_len(data_sending_len); +- +- if (!is_udp_forward_session()) { +- if (!get_pipeline_component().pre_call_ack_func()) { +- m_wait_ack_handler.emplace_back(_handler); +- _log_with_endpoint_DEBUG( +- m_local_addr, "session_id: " + to_string(get_session_id()) + +- " cannot TUNProxySession::out_async_send ! Is waiting for ack"); +- return; +- } +- _log_with_endpoint_DEBUG( +- m_local_addr, "session_id: " + to_string(get_session_id()) + +- " permit to TUNProxySession::out_async_send ! ack:" + +- to_string(get_pipeline_component().pipeline_ack_counter)); +- } +- } +- _handler(error); +- }); +- } else { +- m_sending_data_cache.push_data( +- [&](boost::asio::streambuf& buf) { streambuf_append(buf, data_to_send); }, move(_handler)); +- } +-} +-void TUNProxySession::out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) { +- +- if (!m_connected) { +- if (m_send_buf.size() < numeric_limits::max()) { +- if (is_udp_forward_session()) { +- UDPPacket::generate(m_send_buf, +- get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp, +- string_view((const char*)_data, _length)); +- } else { +- streambuf_append(m_send_buf, _data, _length); +- } +- m_wait_connected_handler.emplace_back(_handler); +- } else { +- output_debug_info(); +- destroy(); +- } +- } else { +- if (is_udp_forward_session()) { +- m_send_buf.consume(m_send_buf.size()); +- UDPPacket::generate(m_send_buf, +- get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp, +- string_view((const char*)_data, _length)); +- out_async_send_impl(streambuf_to_string_view(m_send_buf), move(_handler)); +- } else { +- out_async_send_impl(string_view((const char*)_data, _length), move(_handler)); +- } +- } +-} +- +-void TUNProxySession::try_out_async_read() { +- if (is_destroyed()) { +- return; +- } +- +- if (get_service()->is_use_pipeline() && !is_udp_forward_session()) { +- auto self = shared_from_this(); +- get_service()->session_async_send_to_pipeline( +- *this, PipelineRequest::ACK, "", +- [this, self](const boost::system::error_code error) { +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- +- out_async_read(); +- }, +- m_read_ack_count); +- m_read_ack_count = 0; +- } else { +- out_async_read(); +- } +-} +-void TUNProxySession::recv_buf_ack_sent(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf_ack_length -= _length; +- +- if (get_service()->is_use_pipeline() && m_recv_buf_ack_length <= 0) { +- if (get_pipeline_component().is_write_close_future()) { +- output_debug_info(); +- destroy(); +- return; +- } +- +- get_pipeline_component().set_async_writing_data(false); +- } +-} +- +-void TUNProxySession::recv_buf_consume(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf.consume(_length); +- if (m_recv_buf.size() == 0) { +- try_out_async_read(); +- } +-} +- +-size_t TUNProxySession::parse_udp_packet_data(const string_view& data) { +- +- string_view parse_data(data); +- size_t parsed_size = 0; +- for (;;) { +- if (parse_data.empty()) { +- break; +- } +- +- // parse trojan protocol +- UDPPacket packet; +- size_t packet_len = 0; +- if (!packet.parse(parse_data, packet_len)) { +- if (parse_data.length() > numeric_limits::max()) { +- _log_with_endpoint(get_udp_local_endpoint(), "[tun] error UDPPacket.parse! destroy it.", Log::ERROR); +- destroy(); +- break; +- } +- +- _log_with_endpoint( +- get_udp_local_endpoint(), "[tun] UDPPacket.parse failed! Might need to read more...", Log::WARN); +- break; +- } +- +- if (m_write_to_lwip(this, &packet.payload) < 0) { +- output_debug_info(); +- destroy(); +- break; +- } +- +- parsed_size += packet_len; +- parse_data = parse_data.substr(packet_len); +- } +- +- return parsed_size; +-} +- +-void TUNProxySession::out_async_read() { +- if (get_service()->is_use_pipeline()) { +- get_pipeline_component().get_pipeline_data_cache().async_read( +- [this](const string_view& data, size_t ack_count) { +- get_stat().inc_recv_len(data.length()); +- +- if (is_udp_forward_session()) { +- +- udp_timer_async_wait(); +- +- if (m_recv_buf.size() == 0) { +- auto parsed = parse_udp_packet_data(data); +- if (parsed < data.length()) { +- streambuf_append(m_recv_buf, data.substr(parsed)); +- } +- } else { +- streambuf_append(m_recv_buf, data); +- auto parsed = parse_udp_packet_data(m_recv_buf); +- m_recv_buf.consume(parsed); +- } +- +- try_out_async_read(); +- } else { +- m_read_ack_count += ack_count; +- streambuf_append(m_recv_buf, data); +- m_recv_buf_ack_length += data.length(); +- +- get_pipeline_component().set_async_writing_data(true); +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- } +- }); +- } else { +- m_recv_buf.begin_read(__FILE__, __LINE__); +- auto self = shared_from_this(); +- m_out_socket.async_read_some(m_recv_buf.prepare(Session::MAX_BUF_LENGTH), +- [this, self](const boost::system::error_code error, size_t length) { +- m_recv_buf.end_read(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- m_recv_buf.commit(length); +- get_stat().inc_recv_len(length); +- +- if (is_udp_forward_session()) { +- udp_timer_async_wait(); +- auto parsed = parse_udp_packet_data(m_recv_buf); +- m_recv_buf.consume(parsed); +- +- try_out_async_read(); +- } else { +- m_recv_buf_ack_length += length; +- +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- } +- }); +- } +-} +- +-bool TUNProxySession::try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) { +- +- if (is_udp_forward_session()) { +- if (_local == m_local_addr_udp && _remote == m_remote_addr_udp) { +- out_async_send(payload, payload_length, [](boost::system::error_code) {}); +- return true; +- } +- } +- +- return false; +-} +\ No newline at end of file +diff --git a/src/tun/tunproxysession.h b/src/tun/tunproxysession.h +deleted file mode 100644 +index 4390a69..0000000 +--- a/src/tun/tunproxysession.h ++++ /dev/null +@@ -1,59 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUN_PROXY_SESSION_H_ +-#define _TUN_PROXY_SESSION_H_ +- +-#include "tun/tunsession.h" +- +-class TUNProxySession : public TUNSession { +- +- size_t m_read_ack_count{0}; +- +- boost::asio::ssl::stream m_out_socket; +- boost::asio::ip::tcp::resolver m_out_resolver; +- +- void out_async_read(); +- void try_out_async_read(); +- +- [[nodiscard]] size_t parse_udp_packet_data(const std::string_view& data); +- +- void out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler); +- +- public: +- TUNProxySession(Service* service, bool udp); +- ~TUNProxySession(); +- +- void start() override; +- void destroy(bool pipeline_call = false) override; +- void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) override; +- void recv_ack_cmd(size_t ack_count) override; +- +- // interfaces for TCP +- void recv_buf_consume(uint16_t _length) override; +- void recv_buf_ack_sent(uint16_t _length) override; +- +- // interfaces for UDP +- bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote, +- const uint8_t* payload, size_t payload_length) override; +-}; +- +-#endif //_TUN_PROXY_SESSION_H_ +\ No newline at end of file +diff --git a/src/tun/tunsession.cpp b/src/tun/tunsession.cpp +deleted file mode 100644 +index 0c465d9..0000000 +--- a/src/tun/tunsession.cpp ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tunsession.h" +-#include "core/service.h" +- +-using namespace boost::asio::ip; +-TUNSession::TUNSession(Service* _service, bool _is_udp) : Session(_service, _service->get_config()) { +- set_udp_forward_session(_is_udp); +-} +- +-TUNSession::~TUNSession() {} +- +-udp::endpoint TUNSession::get_redirect_local_remote_addr(bool output_log /*= false*/) const { +- auto remote_addr = m_remote_addr_udp; +- remote_addr.address(make_address_v4(LOCALHOST_IP_ADDRESS)); +- if (output_log) { +- _log_with_date_time(m_remote_addr_udp.address().to_string() + " redirect to local for test"); +- } +- +- return remote_addr; +-} +diff --git a/src/tun/tunsession.h b/src/tun/tunsession.h +deleted file mode 100644 +index ec7b8cb..0000000 +--- a/src/tun/tunsession.h ++++ /dev/null +@@ -1,108 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUNSESSION_H_ +-#define _TUNSESSION_H_ +- +-#include +-#include +-#include +-#include +- +-#include "core/pipeline.h" +-#include "core/utils.h" +-#include "session/session.h" +- +-#define LOCALHOST_IP_ADDRESS ("127.0.0.1") +- +-class Service; +-class TUNSession : public Session { +- +- public: +- using CloseCallback = std::function; +- using WriteToLwipCallback = std::function; +- +- protected: +- SendDataCache m_sending_data_cache; +- +- boost::asio::ip::tcp::endpoint m_local_addr; +- boost::asio::ip::tcp::endpoint m_remote_addr; +- +- boost::asio::ip::udp::endpoint m_local_addr_udp; +- boost::asio::ip::udp::endpoint m_remote_addr_udp; +- +- ReadBufWithGuard m_recv_buf; +- size_t m_recv_buf_ack_length{0}; +- bool m_destroyed{false}; +- +- CloseCallback m_close_cb; +- bool m_close_from_tundev_flag{false}; +- bool m_connected{false}; +- +- boost::asio::streambuf m_send_buf; +- WriteToLwipCallback m_write_to_lwip; +- std::list m_wait_ack_handler; +- std::list m_wait_connected_handler; +- +- [[nodiscard]] boost::asio::ip::udp::endpoint get_redirect_local_remote_addr(bool output_log = false) const; +- +- public: +- TUNSession(Service* _service, bool _is_udp); +- ~TUNSession(); +- +- // common interfaces for UDP and TCP +- void set_tcp_connect(const boost::asio::ip::tcp::endpoint& _local, const boost::asio::ip::tcp::endpoint& _remote) { +- m_local_addr = _local; +- m_remote_addr = _remote; +- } +- +- void set_udp_connect(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote) { +- m_local_addr_udp = _local; +- m_remote_addr_udp = _remote; +- } +- +- [[nodiscard]] const boost::asio::ip::udp::endpoint& get_udp_local_endpoint() const { return m_local_addr_udp; } +- [[nodiscard]] const boost::asio::ip::udp::endpoint& get_udp_remote_endpoint() const { return m_remote_addr_udp; } +- +- [[nodiscard]] bool is_destroyed() const { return m_destroyed; } +- +- void set_write_to_lwip(WriteToLwipCallback&& _handler) { m_write_to_lwip = std::move(_handler); } +- void set_close_callback(CloseCallback&& _cb) { m_close_cb = std::move(_cb); } +- void set_close_from_tundev_flag() { m_close_from_tundev_flag = true; } +- +- virtual void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) = 0; +- +- // interfaces for TCP +- [[nodiscard]] size_t recv_buf_ack_length() const { return m_recv_buf_ack_length; } +- [[nodiscard]] size_t recv_buf_size() const { return m_recv_buf.size(); } +- +- [[nodiscard]] const uint8_t* recv_buf() const { +- return boost::asio::buffer_cast(m_recv_buf.data()); +- } +- +- virtual void recv_buf_consume(uint16_t _length) = 0; +- virtual void recv_buf_ack_sent(uint16_t _length) = 0; +- +- // interface for UDP +- virtual bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) = 0; +-}; +-#endif //_TUNSESSION_H_ +\ No newline at end of file +diff --git a/src/tun/udplocalforwarder.cpp b/src/tun/udplocalforwarder.cpp +deleted file mode 100644 +index 1eefbdd..0000000 +--- a/src/tun/udplocalforwarder.cpp ++++ /dev/null +@@ -1,156 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/udplocalforwarder.h" +-#include "core/service.h" +-#include "session/session.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-UDPLocalForwarder::UDPLocalForwarder(Service* service, udp::endpoint local_src, udp::endpoint remote_dst, +- UDPForwardSession::UDPWriter&& writer, bool is_dns) +- : Session(service, service->get_config()), +- m_service(service), +- m_writer(move(writer)), +- m_local_src(move(local_src)), +- m_remote_dst(move(remote_dst)), +- m_gc_timer(service->get_io_context()), +- m_udp_socket(service->get_io_context()), +- m_is_dns(is_dns) { +- +- set_udp_forward_session(true); +-} +- +-UDPLocalForwarder::~UDPLocalForwarder() {} +-void UDPLocalForwarder::start() { +- auto protocol = m_remote_dst.protocol(); +- boost::system::error_code ec; +- m_udp_socket.open(protocol, ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- +- set_udp_send_recv_buf((int)m_udp_socket.native_handle(), +- m_is_dns ? m_service->get_config().get_dns().udp_socket_buf : m_service->get_config().get_udp_socket_buf()); +- +- android_protect_socket((int)m_udp_socket.native_handle()); +- +- m_udp_socket.bind(udp::endpoint(protocol, 0), ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- +- udp_timer_async_wait(); +- +- _log_with_endpoint(m_local_src, +- "UDP local forwarder to [" + m_remote_dst.address().to_string() + ":" + to_string(m_remote_dst.port()) + +- "] started", +- Log::INFO); +- +- async_read(); +-} +- +-bool UDPLocalForwarder::process(const udp::endpoint& endpoint, const string_view& data) { +- if (endpoint != m_local_src) { +- return false; +- } +- +- return write_to(data); +-} +- +-bool UDPLocalForwarder::write_to(const std::string_view& data) { +- if (is_destroyed()) { +- return false; +- } +- +- if (m_is_dns) { +- _log_with_endpoint_ALL(m_local_src, "[dns] --> [" + m_remote_dst.address().to_string() + ":" + +- to_string(m_remote_dst.port()) + "] length: " + to_string(data.length())); +- } +- +- boost::system::error_code ec; +- m_udp_socket.send_to(boost::asio::buffer(data), m_remote_dst, 0, ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return false; +- } +- +- m_stat.inc_sent_len(data.length()); +- return true; +-} +- +-void UDPLocalForwarder::async_read() { +- udp_timer_async_wait(); +- +- const auto prepare_size = +- m_is_dns ? m_service->get_config().get_dns().udp_recv_buf : m_service->get_config().get_udp_recv_buf(); +- +- m_read_buf.begin_read(__FILE__, __LINE__); +- m_read_buf.consume_all(); +- +- auto self = shared_from_this(); +- m_udp_socket.async_receive_from( +- m_read_buf.prepare(prepare_size), m_remote_dst, [this, self](boost::system::error_code ec, size_t length) { +- m_read_buf.end_read(); +- +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- } else { +- m_read_buf.commit(length); +- m_stat.inc_recv_len(length); +- m_writer(m_local_src, m_read_buf); +- +- async_read(); +- } +- }); +-} +- +-void UDPLocalForwarder::destroy(bool) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- _log_with_endpoint(m_local_src, +- "UDP local forwarder to [" + m_remote_dst.address().to_string() + ":" + to_string(m_remote_dst.port()) + +- "] disconnected, " + m_stat.to_string(), +- Log::INFO); +- +- udp_timer_cancel(); +- +- if (m_udp_socket.is_open()) { +- boost::system::error_code ec; +- m_udp_socket.cancel(ec); +- m_udp_socket.close(); +- } +- +- if (m_destroy_cb) { +- m_destroy_cb(); +- m_destroy_cb = nullptr; +- } +-} +diff --git a/src/tun/udplocalforwarder.h b/src/tun/udplocalforwarder.h +deleted file mode 100644 +index a2707cc..0000000 +--- a/src/tun/udplocalforwarder.h ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_UDP_LOCAL_FORWARDER_HPP +-#define _TROJAN_UDP_LOCAL_FORWARDER_HPP +- +-#include "session/session.h" +-#include "session/udpforwardsession.h" +- +-class Service; +-class UDPLocalForwarder : public Session { +- +- Service* m_service; +- UDPForwardSession::UDPWriter m_writer; +- boost::asio::ip::udp::endpoint m_local_src; +- boost::asio::ip::udp::endpoint m_remote_dst; +- boost::asio::steady_timer m_gc_timer; +- time_t m_gc_timer_checker{}; +- boost::asio::ip::udp::socket m_udp_socket; +- +- ReadBufWithGuard m_read_buf; +- bytes_stat m_stat; +- bool m_is_dns; +- +- bool m_destroyed{false}; +- std::function m_destroy_cb; +- +- bool write_to(const std::string_view& data); +- void async_read(); +- +- public: +- UDPLocalForwarder(Service* service, boost::asio::ip::udp::endpoint local_recv, +- boost::asio::ip::udp::endpoint remote_dst, UDPForwardSession::UDPWriter&& writer, bool is_dns); +- +- ~UDPLocalForwarder() override; +- +- void start() override; +- void destroy(bool pipeline_call = false) override; +- bool process(const boost::asio::ip::udp::endpoint& endpoint, const std::string_view& data); +- +- [[nodiscard]] bool is_destroyed() const { return m_destroyed; } +- void set_destroy_callback(std::function&& destroy_cb) { m_destroy_cb = std::move(destroy_cb); } +-}; +- +-#endif //_TROJAN_UDP_LOCAL_FORWARDER_HPP +\ No newline at end of file +diff --git a/trojan-plus-android-libs b/trojan-plus-android-libs +deleted file mode 160000 +index 8f04901..0000000 +--- a/trojan-plus-android-libs ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 8f04901af9d9ee7c7d51733f490f57ad12d25e90 +-- +2.20.1 + From 6d43481b8db840bee962aa0b700af072411a837d Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Fri, 17 Jul 2020 20:21:32 +0800 Subject: [PATCH 03/11] luci-app-passwall: sync with upstream source --- package/lienol/luci-app-passwall/Makefile | 12 +- .../luasrc/controller/passwall.lua | 441 +++++++++--------- .../luasrc/model/cbi/passwall/api/api.lua | 72 ++- .../luasrc/model/cbi/passwall/api/brook.lua | 53 +-- .../cbi/passwall/api/gen_shadowsocks.lua | 2 +- .../model/cbi/passwall/api/gen_trojan.lua | 43 +- .../model/cbi/passwall/api/gen_v2ray.lua | 110 ++--- .../model/cbi/passwall/api/trojan_go.lua | 149 ++++++ .../luasrc/model/cbi/passwall/api/v2ray.lua | 13 +- .../luasrc/model/cbi/passwall/auto_switch.lua | 4 +- .../luasrc/model/cbi/passwall/global.lua | 4 +- .../luasrc/model/cbi/passwall/node_config.lua | 422 ++++++++++------- .../luasrc/model/cbi/passwall/node_list.lua | 6 +- .../luasrc/model/cbi/passwall/other.lua | 4 +- .../luasrc/model/cbi/passwall/rule.lua | 21 +- .../model/cbi/passwall/server/api/ssr.lua | 2 +- .../model/cbi/passwall/server/api/trojan.lua | 46 +- .../model/cbi/passwall/server/api/v2ray.lua | 158 +++---- .../luasrc/model/cbi/passwall/server/user.lua | 306 +++++++----- .../luasrc/view/passwall/global/status.htm | 355 +++++++------- .../luasrc/view/passwall/global/status2.htm | 3 +- .../luasrc/view/passwall/haproxy/status.htm | 6 +- .../luasrc/view/passwall/log/log.htm | 8 +- .../luasrc/view/passwall/other/footer.htm | 6 +- .../view/passwall/rule/brook_version.htm | 11 +- .../view/passwall/rule/kcptun_version.htm | 11 +- .../view/passwall/rule/rule_version.htm | 5 +- .../view/passwall/rule/trojan_go_version.htm | 171 +++++++ .../view/passwall/rule/v2ray_version.htm | 11 +- .../luasrc/view/passwall/server/log.htm | 2 +- .../passwall/server/users_list_status.htm | 4 - .../luci-app-passwall/po/zh-cn/passwall.po | 33 +- .../root/etc/config/passwall | 1 + .../root/usr/share/passwall/app.sh | 29 +- .../root/usr/share/passwall/iptables.sh | 4 +- .../root/usr/share/passwall/rule_update.lua | 14 +- .../root/usr/share/passwall/subscribe.lua | 324 ++++++++----- 37 files changed, 1767 insertions(+), 1099 deletions(-) mode change 100755 => 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua mode change 100755 => 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua mode change 100755 => 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua create mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua create mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/rule/trojan_go_version.htm diff --git a/package/lienol/luci-app-passwall/Makefile b/package/lienol/luci-app-passwall/Makefile index 92680f5640..ec1b37d34f 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:=3.9 -PKG_RELEASE:=4 -PKG_DATE:=20200705 +PKG_RELEASE:=18 +PKG_DATE:=20200717 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) @@ -41,6 +41,10 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan bool "Include Trojan" default n +config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO + bool "Include Trojan_GO" + default n + config PACKAGE_$(PKG_NAME)_INCLUDE_Brook bool "Include Brook" default n @@ -90,8 +94,8 @@ define Package/$(PKG_NAME) +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \ +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \ +PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan-plus \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \ +PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \ +PACKAGE_$(PKG_NAME)_INCLUDE_kcptun:kcptun-client \ +PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \ diff --git a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua index 301f8c71ea..c37c07e3e4 100644 --- a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua +++ b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua @@ -6,181 +6,184 @@ local http = require "luci.http" local kcptun = require "luci.model.cbi.passwall.api.kcptun" local brook = require "luci.model.cbi.passwall.api.brook" local v2ray = require "luci.model.cbi.passwall.api.v2ray" +local trojan_go = require "luci.model.cbi.passwall.api.trojan_go" function index() - if not nixio.fs.access("/etc/config/passwall") then return end - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "passwall", "reset_config"}, call("reset_config")).leaf = true - entry({"admin", "vpn", "passwall", "show"}, call("show_menu")).leaf = true - entry({"admin", "vpn", "passwall", "hide"}, call("hide_menu")).leaf = true - if nixio.fs.access("/etc/config/passwall") and - nixio.fs.access("/etc/config/passwall_show") then - entry({"admin", "vpn", "passwall"}, alias("admin", "vpn", "passwall", "settings"), _("Pass Wall"), 1).dependent = true - end - entry({"admin", "vpn", "passwall", "settings"}, cbi("passwall/global"), _("Basic Settings"), 1).dependent = true - entry({"admin", "vpn", "passwall", "node_list"}, cbi("passwall/node_list"), _("Node List"), 2).dependent = true - entry({"admin", "vpn", "passwall", "auto_switch"}, cbi("passwall/auto_switch"), _("Auto Switch"), 3).leaf = true - entry({"admin", "vpn", "passwall", "other"}, cbi("passwall/other", {autoapply = true}), _("Other Settings"), 93).leaf = true - if nixio.fs.access("/usr/sbin/haproxy") then - entry({"admin", "vpn", "passwall", "haproxy"}, cbi("passwall/haproxy"), _("Load Balancing"), 94).leaf = true - end - entry({"admin", "vpn", "passwall", "node_subscribe"}, cbi("passwall/node_subscribe"), _("Node Subscribe"), 95).dependent = true - entry({"admin", "vpn", "passwall", "rule"}, cbi("passwall/rule"), _("Rule Update"), 96).leaf = true - entry({"admin", "vpn", "passwall", "node_config"}, cbi("passwall/node_config")).leaf = true - entry({"admin", "vpn", "passwall", "shunt_rules"}, cbi("passwall/shunt_rules")).leaf = true - entry({"admin", "vpn", "passwall", "acl"}, cbi("passwall/acl"), _("Access control"), 97).leaf = true - entry({"admin", "vpn", "passwall", "log"}, form("passwall/log"), _("Watch Logs"), 999).leaf = true - entry({"admin", "vpn", "passwall", "server"}, cbi("passwall/server/index"), _("Server-Side"), 99).leaf = true - entry({"admin", "vpn", "passwall", "server_user"}, cbi("passwall/server/user")).leaf = true + if not nixio.fs.access("/etc/config/passwall") then return end + entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false + entry({"admin", "vpn", "passwall", "reset_config"}, call("reset_config")).leaf = true + entry({"admin", "vpn", "passwall", "show"}, call("show_menu")).leaf = true + entry({"admin", "vpn", "passwall", "hide"}, call("hide_menu")).leaf = true + if nixio.fs.access("/etc/config/passwall") and + nixio.fs.access("/etc/config/passwall_show") then + entry({"admin", "vpn", "passwall"}, alias("admin", "vpn", "passwall", "settings"), _("Pass Wall"), 1).dependent = true + end + entry({"admin", "vpn", "passwall", "settings"}, cbi("passwall/global"), _("Basic Settings"), 1).dependent = true + entry({"admin", "vpn", "passwall", "node_list"}, cbi("passwall/node_list"), _("Node List"), 2).dependent = true + entry({"admin", "vpn", "passwall", "auto_switch"}, cbi("passwall/auto_switch"), _("Auto Switch"), 3).leaf = true + entry({"admin", "vpn", "passwall", "other"}, cbi("passwall/other", {autoapply = true}), _("Other Settings"), 93).leaf = true + if nixio.fs.access("/usr/sbin/haproxy") then + entry({"admin", "vpn", "passwall", "haproxy"}, cbi("passwall/haproxy"), _("Load Balancing"), 94).leaf = true + end + entry({"admin", "vpn", "passwall", "node_subscribe"}, cbi("passwall/node_subscribe"), _("Node Subscribe"), 95).dependent = true + entry({"admin", "vpn", "passwall", "rule"}, cbi("passwall/rule"), _("Rule Update"), 96).leaf = true + entry({"admin", "vpn", "passwall", "node_config"}, cbi("passwall/node_config")).leaf = true + entry({"admin", "vpn", "passwall", "shunt_rules"}, cbi("passwall/shunt_rules")).leaf = true + entry({"admin", "vpn", "passwall", "acl"}, cbi("passwall/acl"), _("Access control"), 97).leaf = true + entry({"admin", "vpn", "passwall", "log"}, form("passwall/log"), _("Watch Logs"), 999).leaf = true + entry({"admin", "vpn", "passwall", "server"}, cbi("passwall/server/index"), _("Server-Side"), 99).leaf = true + entry({"admin", "vpn", "passwall", "server_user"}, cbi("passwall/server/user")).leaf = true - entry({"admin", "vpn", "passwall", "server_user_status"}, call("server_user_status")).leaf = true - entry({"admin", "vpn", "passwall", "server_get_log"}, call("server_get_log")).leaf = true - entry({"admin", "vpn", "passwall", "server_clear_log"}, call("server_clear_log")).leaf = true - entry({"admin", "vpn", "passwall", "link_add_node"}, call("link_add_node")).leaf = true - entry({"admin", "vpn", "passwall", "get_log"}, call("get_log")).leaf = true - entry({"admin", "vpn", "passwall", "clear_log"}, call("clear_log")).leaf = true - entry({"admin", "vpn", "passwall", "status"}, call("status")).leaf = true - entry({"admin", "vpn", "passwall", "socks_status"}, call("socks_status")).leaf = true - entry({"admin", "vpn", "passwall", "connect_status"}, call("connect_status")).leaf = true - entry({"admin", "vpn", "passwall", "check_port"}, call("check_port")).leaf = true - entry({"admin", "vpn", "passwall", "ping_node"}, call("ping_node")).leaf = true - entry({"admin", "vpn", "passwall", "set_node"}, call("set_node")).leaf = true - entry({"admin", "vpn", "passwall", "copy_node"}, call("copy_node")).leaf = true - entry({"admin", "vpn", "passwall", "clear_all_nodes"}, call("clear_all_nodes")).leaf = true - entry({"admin", "vpn", "passwall", "delete_select_nodes"}, call("delete_select_nodes")).leaf = true - entry({"admin", "vpn", "passwall", "update_rules"}, call("update_rules")).leaf = true - entry({"admin", "vpn", "passwall", "luci_check"}, call("luci_check")).leaf = true - entry({"admin", "vpn", "passwall", "luci_update"}, call("luci_update")).leaf = true - entry({"admin", "vpn", "passwall", "kcptun_check"}, call("kcptun_check")).leaf = true - entry({"admin", "vpn", "passwall", "kcptun_update"}, call("kcptun_update")).leaf = true - entry({"admin", "vpn", "passwall", "brook_check"}, call("brook_check")).leaf = true - entry({"admin", "vpn", "passwall", "brook_update"}, call("brook_update")).leaf = true - entry({"admin", "vpn", "passwall", "v2ray_check"}, call("v2ray_check")).leaf = true - entry({"admin", "vpn", "passwall", "v2ray_update"}, call("v2ray_update")).leaf = true + entry({"admin", "vpn", "passwall", "server_user_status"}, call("server_user_status")).leaf = true + entry({"admin", "vpn", "passwall", "server_get_log"}, call("server_get_log")).leaf = true + entry({"admin", "vpn", "passwall", "server_clear_log"}, call("server_clear_log")).leaf = true + entry({"admin", "vpn", "passwall", "link_add_node"}, call("link_add_node")).leaf = true + entry({"admin", "vpn", "passwall", "get_log"}, call("get_log")).leaf = true + entry({"admin", "vpn", "passwall", "clear_log"}, call("clear_log")).leaf = true + entry({"admin", "vpn", "passwall", "status"}, call("status")).leaf = true + entry({"admin", "vpn", "passwall", "socks_status"}, call("socks_status")).leaf = true + entry({"admin", "vpn", "passwall", "connect_status"}, call("connect_status")).leaf = true + entry({"admin", "vpn", "passwall", "check_port"}, call("check_port")).leaf = true + entry({"admin", "vpn", "passwall", "ping_node"}, call("ping_node")).leaf = true + entry({"admin", "vpn", "passwall", "set_node"}, call("set_node")).leaf = true + entry({"admin", "vpn", "passwall", "copy_node"}, call("copy_node")).leaf = true + entry({"admin", "vpn", "passwall", "clear_all_nodes"}, call("clear_all_nodes")).leaf = true + entry({"admin", "vpn", "passwall", "delete_select_nodes"}, call("delete_select_nodes")).leaf = true + entry({"admin", "vpn", "passwall", "update_rules"}, call("update_rules")).leaf = true + entry({"admin", "vpn", "passwall", "luci_check"}, call("luci_check")).leaf = true + entry({"admin", "vpn", "passwall", "luci_update"}, call("luci_update")).leaf = true + entry({"admin", "vpn", "passwall", "kcptun_check"}, call("kcptun_check")).leaf = true + entry({"admin", "vpn", "passwall", "kcptun_update"}, call("kcptun_update")).leaf = true + entry({"admin", "vpn", "passwall", "brook_check"}, call("brook_check")).leaf = true + entry({"admin", "vpn", "passwall", "brook_update"}, call("brook_update")).leaf = true + entry({"admin", "vpn", "passwall", "v2ray_check"}, call("v2ray_check")).leaf = true + entry({"admin", "vpn", "passwall", "v2ray_update"}, call("v2ray_update")).leaf = true + entry({"admin", "vpn", "passwall", "trojan_go_check"}, call("trojan_go_check")).leaf = true + entry({"admin", "vpn", "passwall", "trojan_go_update"}, call("trojan_go_update")).leaf = true end local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) + http.prepare_content("application/json") + http.write_json(content or {code = 1}) end function reset_config() - luci.sys.call('[ -f "/usr/share/passwall/config.default" ] && cp -f /usr/share/passwall/config.default /etc/config/passwall && /etc/init.d/passwall reload') - luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall")) + luci.sys.call('[ -f "/usr/share/passwall/config.default" ] && cp -f /usr/share/passwall/config.default /etc/config/passwall && /etc/init.d/passwall reload') + luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall")) end function show_menu() - luci.sys.call("touch /etc/config/passwall_show") - luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall")) + luci.sys.call("touch /etc/config/passwall_show") + luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall")) end function hide_menu() - luci.sys.call("rm -rf /etc/config/passwall_show") - luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview")) + luci.sys.call("rm -rf /etc/config/passwall_show") + luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview")) end function link_add_node() - local link = luci.http.formvalue("link") - luci.sys.call('rm -f /tmp/links.conf && echo "' .. link .. '" >> /tmp/links.conf') - luci.sys.call("lua /usr/share/passwall/subscribe.lua add log") + local link = luci.http.formvalue("link") + luci.sys.call('rm -f /tmp/links.conf && echo "' .. link .. '" >> /tmp/links.conf') + luci.sys.call("lua /usr/share/passwall/subscribe.lua add log") end function get_log() - -- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log") - luci.http.write(luci.sys.exec("[ -f '/var/log/passwall.log' ] && cat /var/log/passwall.log")) + -- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log") + luci.http.write(luci.sys.exec("[ -f '/var/log/passwall.log' ] && cat /var/log/passwall.log")) end function clear_log() - luci.sys.call("echo '' > /var/log/passwall.log") + luci.sys.call("echo '' > /var/log/passwall.log") end function status() - -- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode") - 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 + -- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode") + 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 - 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 - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) + 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 + end + luci.http.prepare_content("application/json") + luci.http.write_json(e) end function socks_status() - local e = {} - local index = luci.http.formvalue("index") - local id = luci.http.formvalue("id") - e.index = index - e.status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /dev/null", appname, id)) == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) + local e = {} + local index = luci.http.formvalue("index") + local id = luci.http.formvalue("id") + e.index = index + e.status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /dev/null", appname, id)) == 0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) end function connect_status() - local e = {} - e.use_time = "" - local url = luci.http.formvalue("url") - local result = luci.sys.exec('curl --connect-timeout 5 -o /dev/null -I -skL -w "%{http_code}:%{time_total}" ' .. url) - local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0") - if code ~= 0 then - local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'") - e.use_time = string.format("%.2f", use_time * 1000) - e.ping_type = "curl" - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) + local e = {} + e.use_time = "" + local url = luci.http.formvalue("url") + local result = luci.sys.exec('curl --connect-timeout 5 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" ' .. url) + local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0") + if code ~= 0 then + local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'") + e.use_time = string.format("%.2f", use_time * 1000) + e.ping_type = "curl" + end + luci.http.prepare_content("application/json") + luci.http.write_json(e) end function ping_node() - local index = luci.http.formvalue("index") - local address = luci.http.formvalue("address") - local port = luci.http.formvalue("port") - local e = {} - e.index = index - if (ucic:get(appname, "@global_other[0]", "use_tcping") or 1) == "1" and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then - e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 1 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address)) - end - if e.ping == nil or tonumber(e.ping) == 0 then - e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address) - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) + local index = luci.http.formvalue("index") + local address = luci.http.formvalue("address") + local port = luci.http.formvalue("port") + local e = {} + e.index = index + if (ucic:get(appname, "@global_other[0]", "use_tcping") or 1) == "1" and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then + e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address)) + end + if e.ping == nil or tonumber(e.ping) == 0 then + e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address) + end + luci.http.prepare_content("application/json") + luci.http.write_json(e) 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:commit(appname) - luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &") - luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log")) + 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:commit(appname) + luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &") + luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log")) end function copy_node() - local e = {} - local section = luci.http.formvalue("section") - luci.http.prepare_content("application/json") - luci.http.write_json(e) + local e = {} + local section = luci.http.formvalue("section") + luci.http.prepare_content("application/json") + luci.http.write_json(e) end function clear_all_nodes() - ucic:foreach(appname, "nodes", function(node) + ucic:foreach(appname, "nodes", function(node) ucic:delete(appname, node['.name']) - end) - - local function clear(type) + end) + + local function clear(type) local node_num = ucic:get(appname, "@global_other[0]", type .. "_node_num") or 1 for i = 1, node_num, 1 do local node = ucic:get(appname, "@global[0]", type .. "_node" .. i) @@ -192,128 +195,144 @@ function clear_all_nodes() clear("tcp") clear("udp") - ucic:commit(appname) - luci.sys.call("/etc/init.d/" .. appname .. " restart") + ucic:commit(appname) + luci.sys.call("/etc/init.d/" .. appname .. " restart") end function delete_select_nodes() - local ids = luci.http.formvalue("ids") - string.gsub(ids, '[^' .. "," .. ']+', function(w) - ucic:delete(appname, w) - end) - ucic:commit(appname) - luci.sys.call("/etc/init.d/" .. appname .. " restart") + local ids = luci.http.formvalue("ids") + string.gsub(ids, '[^' .. "," .. ']+', function(w) + ucic:delete(appname, w) + end) + ucic:commit(appname) + luci.sys.call("/etc/init.d/" .. appname .. " restart") end function check_port() - local node_name = "" + local node_name = "" - local retstring = "
" - -- retstring = retstring .. "暂时不支持UDP检测
" + local retstring = "
" + -- retstring = retstring .. "暂时不支持UDP检测
" - retstring = retstring .. "检测端口可用性
" - ucic:foreach("passwall", "nodes", function(s) - local ret = "" - local tcp_socket - if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or - (s.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then - else - local type = s.type - if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" and - s.address and s.port and s.remarks then - node_name = "%s:[%s] %s:%s" % - {s.type, s.remarks, s.address, s.port} - tcp_socket = nixio.socket("inet", "stream") - tcp_socket:setopt("socket", "rcvtimeo", 3) - tcp_socket:setopt("socket", "sndtimeo", 3) - ret = tcp_socket:connect(s.address, s.port) - if tostring(ret) == "true" then - retstring = retstring .. "" .. node_name .. " OK.
" - else - retstring = retstring .. "" .. node_name .. " Error.
" - end - ret = "" - end - end - if tcp_socket then tcp_socket:close() end - end) - luci.http.prepare_content("application/json") - luci.http.write_json({ret = retstring}) + retstring = retstring .. "检测端口可用性
" + ucic:foreach("passwall", "nodes", function(s) + local ret = "" + local tcp_socket + if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or + (s.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then + else + local type = s.type + if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" and + s.address and s.port and s.remarks then + node_name = "%s:[%s] %s:%s" % {s.type, s.remarks, s.address, s.port} + tcp_socket = nixio.socket("inet", "stream") + tcp_socket:setopt("socket", "rcvtimeo", 3) + tcp_socket:setopt("socket", "sndtimeo", 3) + ret = tcp_socket:connect(s.address, s.port) + if tostring(ret) == "true" then + retstring = retstring .. "" .. node_name .. " OK.
" + else + retstring = retstring .. "" .. node_name .. " Error.
" + end + ret = "" + end + end + if tcp_socket then tcp_socket:close() end + end) + luci.http.prepare_content("application/json") + luci.http.write_json({ret = retstring}) end function update_rules() - local update = luci.http.formvalue("update") - luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &") + local update = luci.http.formvalue("update") + luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &") end function server_user_status() - local e = {} - e.index = luci.http.formvalue("index") - e.status = luci.sys.call(string.format("ps -w | grep -v 'grep' | grep '%s/bin/' | grep -i '%s' >/dev/null", appname .. "_server", luci.http.formvalue("id"))) == 0 - http_write_json(e) + local e = {} + e.index = luci.http.formvalue("index") + e.status = luci.sys.call(string.format("ps -w | grep -v 'grep' | grep '%s/bin/' | grep -i '%s' >/dev/null", appname .. "_server", luci.http.formvalue("id"))) == 0 + http_write_json(e) end function server_get_log() - luci.http.write(luci.sys.exec("[ -f '/var/log/passwall_server.log' ] && cat /var/log/passwall_server.log")) + luci.http.write(luci.sys.exec("[ -f '/var/log/passwall_server.log' ] && cat /var/log/passwall_server.log")) end function server_clear_log() - luci.sys.call("echo '' > /var/log/passwall_server.log") + luci.sys.call("echo '' > /var/log/passwall_server.log") end function kcptun_check() - local json = kcptun.to_check("") - http_write_json(json) + local json = kcptun.to_check("") + http_write_json(json) end function kcptun_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = kcptun.to_extract(http.formvalue("file"), - http.formvalue("subfix")) - elseif task == "move" then - json = kcptun.to_move(http.formvalue("file")) - else - json = kcptun.to_download(http.formvalue("url")) - end + local json = nil + local task = http.formvalue("task") + if task == "extract" then + json = kcptun.to_extract(http.formvalue("file"), http.formvalue("subfix")) + elseif task == "move" then + json = kcptun.to_move(http.formvalue("file")) + else + json = kcptun.to_download(http.formvalue("url")) + end - http_write_json(json) + http_write_json(json) end function brook_check() - local json = brook.to_check("") - http_write_json(json) + local json = brook.to_check("") + http_write_json(json) end function brook_update() - local json = nil - local task = http.formvalue("task") - if task == "move" then - json = brook.to_move(http.formvalue("file")) - else - json = brook.to_download(http.formvalue("url")) - end + local json = nil + local task = http.formvalue("task") + if task == "move" then + json = brook.to_move(http.formvalue("file")) + else + json = brook.to_download(http.formvalue("url")) + end - http_write_json(json) + http_write_json(json) end function v2ray_check() - local json = v2ray.to_check("") - http_write_json(json) + local json = v2ray.to_check("") + http_write_json(json) end function v2ray_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = - v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix")) - elseif task == "move" then - json = v2ray.to_move(http.formvalue("file")) - else - json = v2ray.to_download(http.formvalue("url")) - end + local json = nil + local task = http.formvalue("task") + if task == "extract" then + json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix")) + elseif task == "move" then + json = v2ray.to_move(http.formvalue("file")) + else + json = v2ray.to_download(http.formvalue("url")) + end - http_write_json(json) + http_write_json(json) +end + +function trojan_go_check() + local json = trojan_go.to_check("") + http_write_json(json) +end + +function trojan_go_update() + local json = nil + local task = http.formvalue("task") + if task == "extract" then + json = trojan_go.to_extract(http.formvalue("file"), http.formvalue("subfix")) + elseif task == "move" then + json = trojan_go.to_move(http.formvalue("file")) + else + json = trojan_go.to_download(http.formvalue("url")) + end + + http_write_json(json) end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua index 8321f90101..3ecc304853 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua @@ -20,7 +20,7 @@ function gen_uuid() end function uci_get_type(type, config, default) - local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n `uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. "`") + local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")") if (value == nil or value == "") and (default and default ~= "") then value = default end @@ -28,22 +28,47 @@ function uci_get_type(type, config, default) end function uci_get_type_id(id, config, default) - local value = uci:get(appname, id, config, default) or sys.exec("echo -n `uci -q get " .. appname .. "." .. id .. "." .. config .. "`") + local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")") if (value == nil or value == "") and (default and default ~= "") then value = default end return value end +function chmod_755(file) + if file and file ~= "" then + if not fs.access(file, "rwx", "rx", "rx") then + fs.chmod(file, 755) + end + end +end + function get_v2ray_path() local path = uci_get_type("global_app", "v2ray_file") return path .. "/v2ray" end -function get_v2ray_version() - local path = get_v2ray_path() - local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -version | awk '{print $2}' | sed -n 1P") - return version +function get_v2ray_version(file) + if file == nil then file = get_v2ray_path() end + chmod_755(file) + if fs.access(file) then + return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) + end + return "" +end + +function get_trojan_go_path() + local path = uci_get_type("global_app", "trojan_go_file") + return path +end + +function get_trojan_go_version(file) + if file == nil then file = get_trojan_go_path() end + chmod_755(file) + if fs.access(file) then + return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) + end + return "" end function get_kcptun_path() @@ -51,10 +76,13 @@ function get_kcptun_path() return path end -function get_kcptun_version() - local path = get_kcptun_path() - local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -v | awk '{print $3}'") - return version +function get_kcptun_version(file) + if file == nil then file = get_kcptun_path() end + chmod_755(file) + if fs.access(file) then + return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) + end + return "" end function get_brook_path() @@ -62,10 +90,13 @@ function get_brook_path() return path end -function get_brook_version() - local path = get_brook_path() - local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -v | awk '{print $3}'") - return version +function get_brook_version(file) + if file == nil then file = get_brook_path() end + chmod_755(file) + if fs.access(file) then + return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) + end + return "" end function _unpack(t, i) @@ -144,12 +175,10 @@ end function auto_get_arch() local arch = nixio.uname().machine or "" if fs.access("/usr/lib/os-release") then - LEDE_BOARD = sys.exec( - "echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`") + LEDE_BOARD = sys.exec("echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`") end if fs.access("/etc/openwrt_release") then - DISTRIB_TARGET = sys.exec( - "echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`") + DISTRIB_TARGET = sys.exec("echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`") end if arch == "mips" then @@ -157,15 +186,13 @@ function auto_get_arch() if string.match(LEDE_BOARD, "ramips") == "ramips" then arch = "ramips" else - arch = sys.exec("echo '" .. LEDE_BOARD .. - "' | grep -oE 'ramips|ar71xx'") + arch = sys.exec("echo '" .. LEDE_BOARD .. "' | grep -oE 'ramips|ar71xx'") end elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then if string.match(DISTRIB_TARGET, "ramips") == "ramips" then arch = "ramips" else - arch = sys.exec("echo '" .. DISTRIB_TARGET .. - "' | grep -oE 'ramips|ar71xx'") + arch = sys.exec("echo '" .. DISTRIB_TARGET .. "' | grep -oE 'ramips|ar71xx'") end end end @@ -204,7 +231,6 @@ end function get_api_json(url) local jsonc = require "luci.jsonc" - local json_content = luci.sys.exec(curl .. " " .. _unpack(curl_args) .. " " .. url) if json_content == "" then return {} end return jsonc.parse(json_content) or {} diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua index ad8dcc6375..05f716470b 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua @@ -5,31 +5,7 @@ local util = require "luci.util" local i18n = require "luci.i18n" local api = require "luci.model.cbi.passwall.api.api" -local brook_api = - "https://api.github.com/repos/txthinking/brook/releases/latest" - -function get_brook_file_path() - return api.uci_get_type("global_app", "brook_file") -end - -function get_brook_version(file) - if file == nil then file = get_brook_file_path() end - - if file and file ~= "" then - if not fs.access(file, "rwx", "rx", "rx") then - fs.chmod(file, 755) - end - - local info = util.trim(sys.exec("%s -v 2>/dev/null" % file)) - - if info ~= "" then - local tb = util.split(info, "%s+", nil, true) - return tb[1] == "Brook" and tb[3] or "" - end - end - - return "" -end +local brook_api = "https://api.github.com/repos/txthinking/brook/releases/latest" function to_check(arch) if not arch or arch == "" then arch = api.auto_get_arch() end @@ -56,12 +32,9 @@ function to_check(arch) } end + local now_version = api.get_brook_version() local remote_version = json.tag_name:match("[^v]+") - - local client_file = get_brook_file_path() - - local needs_update = api.compare_versions(get_brook_version(client_file), - "<", remote_version) + local needs_update = api.compare_versions(now_version, "<", remote_version) local html_url, download_url if needs_update then @@ -77,18 +50,17 @@ function to_check(arch) if needs_update and not download_url then return { code = 1, - now_version = get_brook_version(client_file), + now_version = now_version, version = remote_version, html_url = html_url, - error = i18n.translate( - "New version found, but failed to get new version download url.") + error = i18n.translate("New version found, but failed to get new version download url.") } end return { code = 0, update = needs_update, - now_version = get_brook_version(client_file), + now_version = now_version, version = remote_version, url = {html = html_url, download = download_url} } @@ -122,17 +94,16 @@ function to_move(file) return {code = 1, error = i18n.translate("Client file is required.")} end - local version = get_brook_version(file) + local version = api.get_brook_version(file) if version == "" then sys.call("/bin/rm -rf /tmp/brook_download.*") return { code = 1, - error = i18n.translate( - "The client file is not suitable for current device.") + error = i18n.translate("The client file is not suitable for current device.") } end - local client_file = get_brook_file_path() + local client_file = api.get_brook_path() local client_file_bak if fs.access(client_file) then @@ -140,8 +111,7 @@ function to_move(file) api.exec("/bin/mv", {"-f", client_file, client_file_bak}) end - local result = api.exec("/bin/mv", {"-f", file, client_file}, nil, - api.command_timeout) == 0 + local result = api.exec("/bin/mv", {"-f", file, client_file}, nil, api.command_timeout) == 0 if not result or not fs.access(client_file) then sys.call("/bin/rm -rf /tmp/brook_download.*") @@ -150,8 +120,7 @@ function to_move(file) end return { code = 1, - error = i18n.translatef("Can't move new file to path: %s", - client_file) + error = i18n.translatef("Can't move new file to path: %s", client_file) } end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua old mode 100755 new mode 100644 index eb0210c1ba..f69fdc18da --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua @@ -25,7 +25,7 @@ if node.type == "SS" then end elseif node.type == "SSR" then config.method = node.ssr_encrypt_method - config.protocol = node.protocol + config.protocol = node.ssr_protocol config.protocol_param = node.protocol_param config.obfs = node.obfs config.obfs_param = node.obfs_param diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua old mode 100755 new mode 100644 index 6b73815af5..2ee08bd4c4 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua @@ -6,26 +6,34 @@ local local_addr = arg[3] local local_port = arg[4] local node = ucursor:get_all("passwall", node_section) +local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" +local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" local trojan = { run_type = run_type, local_addr = local_addr, - local_port = local_port, + local_port = tonumber(local_port), remote_addr = node.address, remote_port = tonumber(node.port), password = {node.password}, log_level = 1, ssl = { - verify = (node.trojan_verify_cert == "1") and true or false, + verify = (node.tls_allowInsecure ~= "1") and true or false, verify_hostname = true, cert = node.trojan_cert_path, - cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA", - cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", + cipher = cipher, + cipher_tls13 = cipher13, sni = node.tls_serverName, alpn = {"h2", "http/1.1"}, reuse_session = true, - session_ticket = false, + session_ticket = (node.tls_sessionTicket == "1") and true or false, curves = "" }, + udp_timeout = 60, + mux = (node.mux == "1") and { + enabled = true, + concurrency = tonumber(node.mux_concurrency), + idle_timeout = 60, + } or nil, tcp = { no_delay = true, keep_alive = true, @@ -34,4 +42,29 @@ local trojan = { fast_open_qlen = 20 } } +if node.type == "Trojan-Go" then + trojan.ssl.cipher = node.fingerprint == nil and cipher or (node.fingerprint == "disable" and cipher13 .. ":" .. cipher or "") + trojan.ssl.cipher_tls13 = node.fingerprint == nil and cipher13 or nil + trojan.ssl.fingerprint = (node.fingerprint ~= nil and node.fingerprint ~= "disable" ) and node.fingerprint or "" + trojan.ssl.alpn = node.trojan_transport == 'ws' and {} or {"h2", "http/1.1"} + if node.stream_security ~= "tls" and node.trojan_transport == "original" then trojan.ssl = nil end + trojan.transport_plugin = node.stream_security == "none" and node.trojan_transport == "original" and { + enabled = node.plugin_type ~= nil, + type = node.plugin_type or "plaintext", + command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, + plugin_option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, + arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, + env = {} + } or nil + trojan.websocket = node.trojan_transport and node.trojan_transport:find('ws') and { + enabled = true, + path = (node.ws_path ~= nil) and node.ws_path or "/", + host = (node.ws_host ~= nil) and node.ws_host or (node.tls_serverName ~= nil and node.tls_serverName or node.address) + } or nil + trojan.shadowsocks = (node.ss_aead == "1") and { + enabled = true, + method = (node.ss_aead_method ~= nil) and node.ss_aead_method or "aead_aes_128_gcm", + password = (node.ss_aead_pwd ~= nil) and node.ss_aead_pwd or "" + } or nil +end print(json.stringify(trojan, 1)) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua old mode 100755 new mode 100644 index fe4411fdbf..1da513ba53 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua @@ -21,8 +21,8 @@ local function gen_outbound(node, tag) end if node.type ~= "V2ray" then if node.type == "Socks" then - node.v2ray_protocol = "socks" - node.v2ray_transport = "tcp" + node.protocol = "socks" + node.transport = "tcp" else local node_type = (proto and proto ~= "nil") and proto or "socks" local new_port = sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname)) @@ -35,83 +35,87 @@ local function gen_outbound(node, tag) string.format("/var/etc/%s/v2_%s_%s.json", appname, node_type, node_id), "4") ) - node.v2ray_protocol = "socks" - node.v2ray_transport = "tcp" + node.protocol = "socks" + node.transport = "tcp" node.address = "127.0.0.1" end end result = { tag = tag, - protocol = node.v2ray_protocol or "vmess", + protocol = node.protocol or "vmess", mux = { - enabled = (node.v2ray_mux == "1") and true or false, - concurrency = (node.v2ray_mux_concurrency) and tonumber(node.v2ray_mux_concurrency) or 8 + enabled = (node.mux == "1") and true or false, + concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 }, -- 底层传输配置 - streamSettings = (node.v2ray_protocol == "vmess") and { - network = node.v2ray_transport, - security = node.v2ray_stream_security, - tlsSettings = (node.v2ray_stream_security == "tls") and { + streamSettings = (node.protocol == "vmess") and { + network = node.transport, + security = node.stream_security, + tlsSettings = (node.stream_security == "tls") and { + disableSessionResumption = node.sessionTicket ~= "1" and true or false, serverName = node.tls_serverName, allowInsecure = (node.tls_allowInsecure == "1") and true or false } or nil, - tcpSettings = (node.v2ray_transport == "tcp" and - node.v2ray_protocol ~= "socks") and { + tcpSettings = (node.transport == "tcp" and + node.protocol ~= "socks") and { header = { - type = node.v2ray_tcp_guise, + type = node.tcp_guise, request = { - path = node.v2ray_tcp_guise_http_path or {"/"}, + path = node.tcp_guise_http_path or {"/"}, headers = { - Host = node.v2ray_tcp_guise_http_host or {} + Host = node.tcp_guise_http_host or {} } } or {} } } or nil, - kcpSettings = (node.v2ray_transport == "mkcp") and { - mtu = tonumber(node.v2ray_mkcp_mtu), - tti = tonumber(node.v2ray_mkcp_tti), - uplinkCapacity = tonumber(node.v2ray_mkcp_uplinkCapacity), - downlinkCapacity = tonumber(node.v2ray_mkcp_downlinkCapacity), - congestion = (node.v2ray_mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(node.v2ray_mkcp_readBufferSize), - writeBufferSize = tonumber(node.v2ray_mkcp_writeBufferSize), - header = {type = node.v2ray_mkcp_guise} + kcpSettings = (node.transport == "mkcp") and { + mtu = tonumber(node.mkcp_mtu), + tti = tonumber(node.mkcp_tti), + uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), + downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), + congestion = (node.mkcp_congestion == "1") and true or false, + readBufferSize = tonumber(node.mkcp_readBufferSize), + writeBufferSize = tonumber(node.mkcp_writeBufferSize), + header = {type = node.mkcp_guise} } or nil, - wsSettings = (node.v2ray_transport == "ws") and { - path = node.v2ray_ws_path or "", - headers = (node.v2ray_ws_host ~= nil) and - {Host = node.v2ray_ws_host} or nil + wsSettings = (node.transport == "ws") and { + path = node.ws_path or "", + headers = (node.ws_host ~= nil) and + {Host = node.ws_host} or nil } or nil, - httpSettings = (node.v2ray_transport == "h2") and - {path = node.v2ray_h2_path, host = node.v2ray_h2_host} or + httpSettings = (node.transport == "h2") and + {path = node.h2_path, host = node.h2_host} or nil, - dsSettings = (node.v2ray_transport == "ds") and - {path = node.v2ray_ds_path} or nil, - quicSettings = (node.v2ray_transport == "quic") and { - security = node.v2ray_quic_security, - key = node.v2ray_quic_key, - header = {type = node.v2ray_quic_guise} + dsSettings = (node.transport == "ds") and + {path = node.ds_path} or nil, + quicSettings = (node.transport == "quic") and { + security = node.quic_security, + key = node.quic_key, + header = {type = node.quic_guise} } or nil } or nil, settings = { - vnext = (node.v2ray_protocol == "vmess") and { + vnext = (node.protocol == "vmess") and { { address = node.address, port = tonumber(node.port), users = { { - id = node.v2ray_VMess_id, - alterId = tonumber(node.v2ray_VMess_alterId), - level = tonumber(node.v2ray_VMess_level), - security = node.v2ray_security + id = node.vmess_id, + alterId = tonumber(node.alter_id), + level = tonumber(node.vmess_level), + security = node.security } } } } or nil, - servers = (node.v2ray_protocol == "socks") and { + servers = (node.protocol == "socks" or node.protocol == "http" or node.protocol == "shadowsocks") and { { address = node.address, port = tonumber(node.port), + method = node.v_ss_encrypt_method or nil, + password = node.password or "", + ota = node.ss_ota == '1' and true or false, users = (node.username and node.password) and {{user = node.username, pass = node.password}} or nil } @@ -139,17 +143,17 @@ if redir_port ~= "nil" then settings = {network = proto, followRedirect = true}, sniffing = {enabled = true, destOverride = {"http", "tls"}} }) - if proto == "tcp" and node.v2ray_tcp_socks == "1" then + if proto == "tcp" and node.tcp_socks == "1" then table.insert(inbounds, { listen = "0.0.0.0", - port = tonumber(node.v2ray_tcp_socks_port), + port = tonumber(node.tcp_socks_port), protocol = "socks", settings = { - auth = node.v2ray_tcp_socks_auth, - accounts = (node.v2ray_tcp_socks_auth == "password") and { + auth = node.tcp_socks_auth, + accounts = (node.tcp_socks_auth == "password") and { { - user = node.v2ray_tcp_socks_auth_username, - pass = node.v2ray_tcp_socks_auth_password + user = node.tcp_socks_auth_username, + pass = node.tcp_socks_auth_password } } or nil, udp = true @@ -158,7 +162,7 @@ if redir_port ~= "nil" then end end -if node.v2ray_protocol == "_shunt" then +if node.protocol == "_shunt" then local rules = {} ucursor:foreach(appname, "shunt_rules", function(e) @@ -211,9 +215,9 @@ if node.v2ray_protocol == "_shunt" then routing = {domainStrategy = "IPOnDemand", rules = rules} -elseif node.v2ray_protocol == "_balancing" then - if node.v2ray_balancing_node then - local nodes = node.v2ray_balancing_node +elseif node.protocol == "_balancing" then + if node.balancing_node then + local nodes = node.balancing_node local length = #nodes for i = 1, length do local node = ucursor:get_all(appname, nodes[i]) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua new file mode 100644 index 0000000000..0ea54d4e75 --- /dev/null +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua @@ -0,0 +1,149 @@ +module("luci.model.cbi.passwall.api.trojan_go", package.seeall) +local fs = require "nixio.fs" +local sys = require "luci.sys" +local util = require "luci.util" +local i18n = require "luci.i18n" +local ipkg = require("luci.model.ipkg") +local api = require "luci.model.cbi.passwall.api.api" + +local trojan_go_api = api.uci_get_type("global_app", "trojan_go_latest", "https://api.github.com/repos/trojan-gfw/trojan-go/releases/latest") + +function to_check(arch) + if not arch or arch == "" then arch = api.auto_get_arch() end + + local file_tree, sub_version = api.get_file_info(arch) + + if file_tree == "" then + return { + code = 1, + error = i18n.translate( + "Can't determine ARCH, or ARCH not supported.") + } + end + + if file_tree == "mips" then file_tree = "mips%-hardfloat" end + if file_tree == "mipsle" then file_tree = "mipsle%-hardfloat" end + if file_tree == "arm64" then + file_tree = "armv8" + else + if sub_version and sub_version:match("^[5-8]$") then file_tree = file_tree .. "v" .. sub_version end + end + + local json = api.get_api_json(trojan_go_api) + + if json == nil or json.tag_name == nil then + return { + code = 1, + error = i18n.translate("Get remote version info failed.") + } + end + + local now_version = api.get_trojan_go_version() + local remote_version = json.tag_name:match("[^v]+") + local needs_update = api.compare_versions(now_version, "<", remote_version) + local html_url, download_url + + if needs_update then + html_url = json.html_url + for _, v in ipairs(json.assets) do + if v.name and v.name:match("linux%-" .. file_tree .. "%.zip") then + download_url = v.browser_download_url + break + end + end + end + + if needs_update and not download_url then + return { + code = 1, + now_version = now_version, + version = remote_version, + html_url = html_url, + error = i18n.translate( + "New version found, but failed to get new version download url.") .. " [linux-" .. file_tree .. ".zip]" + } + end + + return { + code = 0, + update = needs_update, + now_version = now_version, + version = remote_version, + url = {html = html_url, download = download_url} + } +end + +function to_download(url) + if not url or url == "" then + return {code = 1, error = i18n.translate("Download url is required.")} + end + + sys.call("/bin/rm -f /tmp/trojan-go_download.*") + + local tmp_file = util.trim(util.exec("mktemp -u -t trojan-go_download.XXXXXX")) + + local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0 + + if not result then + api.exec("/bin/rm", {"-f", tmp_file}) + return { + code = 1, + error = i18n.translatef("File download failed or timed out: %s", url) + } + end + + return {code = 0, file = tmp_file} +end + +function to_extract(file, subfix) + local isinstall_unzip = ipkg.installed("unzip") + if isinstall_unzip == nil then + ipkg.update() + ipkg.install("unzip") + end + + if not file or file == "" or not fs.access(file) then + return {code = 1, error = i18n.translate("File path required.")} + end + + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + local tmp_dir = util.trim(util.exec("mktemp -d -t trojan-go_extract.XXXXXX")) + + local output = {} + api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir}, + function(chunk) output[#output + 1] = chunk end) + + local files = util.split(table.concat(output)) + + api.exec("/bin/rm", {"-f", file}) + + return {code = 0, file = tmp_dir} +end + +function to_move(file) + if not file or file == "" then + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + return {code = 1, error = i18n.translate("Client file is required.")} + end + + local client_file = api.get_trojan_go_path() + local client_file_bak + + if fs.access(client_file) then + client_file_bak = client_file .. ".bak" + api.exec("/bin/mv", {"-f", client_file, client_file_bak}) + end + + local result = api.exec("/bin/mv", { "-f", file .. "/trojan-go", client_file }, nil, api.command_timeout) == 0 + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + if not result or not fs.access(client_file) then + return { + code = 1, + error = i18n.translatef("Can't move new file to path: %s", client_file) + } + end + + api.exec("/bin/chmod", {"-R", "755", client_file}) + + return {code = 0} +end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua index 7ebbd39117..e5339acba2 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua @@ -6,8 +6,7 @@ local i18n = require "luci.i18n" local ipkg = require("luci.model.ipkg") local api = require "luci.model.cbi.passwall.api.api" -local v2ray_api = - "https://api.github.com/repos/v2ray/v2ray-core/releases/latest" +local v2ray_api = "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" local is_armv7 = false function get_v2ray_file_path() @@ -17,9 +16,7 @@ end function get_v2ray_version() if get_v2ray_file_path() and get_v2ray_file_path() ~= "" then if fs.access(get_v2ray_file_path() .. "/v2ray") then - return sys.exec("echo -n `" .. get_v2ray_file_path() .. - "/v2ray -version | awk '{print $2}' | sed -n 1P" .. - "`") + return sys.exec("echo -n $(" .. get_v2ray_file_path() .. "/v2ray -version | awk '{print $2}' | sed -n 1P" .. ")") end end return "" @@ -52,8 +49,7 @@ function to_check(arch) end local remote_version = json.tag_name:match("[^v]+") - local needs_update = api.compare_versions(get_v2ray_version(), "<", - remote_version) + local needs_update = api.compare_versions(get_v2ray_version(), "<", remote_version) local html_url, download_url if needs_update then @@ -160,8 +156,7 @@ function to_move(file) if not result or not fs.access(client_file) then return { code = 1, - error = i18n.translatef("Can't move new file to path: %s", - client_file) + error = i18n.translatef("Can't move new file to path: %s", client_file) } end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/auto_switch.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/auto_switch.lua index 5392ec5cfe..a98b01d2ac 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/auto_switch.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/auto_switch.lua @@ -5,8 +5,8 @@ local nodes_table = {} uci:foreach(appname, "nodes", function(e) if e.type and e.remarks then local remarks = "" - if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then - remarks = "%s:[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks} + if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then + remarks = "%s:[%s] " % {translatef(e.type .. e.protocol), e.remarks} else remarks = "%s:[%s] %s:%s" % {e.type, e.remarks, e.address, e.port} end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/global.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/global.lua index b199d13d9e..7bc3647e1a 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/global.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/global.lua @@ -16,8 +16,8 @@ local nodes_table = {} uci:foreach(appname, "nodes", function(e) if e.type and e.remarks then local remarks = "" - if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then - remarks = "%s:[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks} + if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then + remarks = "%s:[%s] " % {translatef(e.type .. e.protocol), e.remarks} else if e.use_kcp and e.use_kcp == "1" then remarks = "%s+%s:[%s] %s" % {e.type, "Kcptun", e.remarks, e.address} diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_config.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_config.lua index 2c9b5e4311..ab67b2bc26 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_config.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_config.lua @@ -44,15 +44,27 @@ local ssr_obfs_list = { "tls1.0_session_auth", "tls1.2_ticket_auth" } -local v2ray_ss_encrypt_method_list = { +local v_ss_encrypt_method_list = { "aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305" } -local v2ray_security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"} +local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"} -local v2ray_header_type_list = { +local header_type_list = { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" } +local force_fp = { + "disable", "firefox", "chrome", "ios" +} +local encrypt_methods_ss_aead = { + "dummy", + "aead_chacha20_poly1305", + "aead_aes_128_gcm", + "aead_aes_256_gcm", + "chacha20-ietf-poly1305", + "aes-128-gcm", + "aes-256-gcm", +} m = Map(appname, translate("Node Config")) m.redirect = d.build_url("admin", "vpn", appname) @@ -83,17 +95,20 @@ if is_installed("brook") or is_finded("brook") then type:value("Brook", translate("Brook")) end if is_installed("trojan") or is_finded("trojan") then - type:value("Trojan", translate("Trojan")) + type:value("Trojan", translate("Trojan-Plus")) +end +if is_installed("trojan-go") or is_finded("trojan-go") then + type:value("Trojan-Go", translate("Trojan-Go")) end -v2ray_protocol = s:option(ListValue, "v2ray_protocol", translate("Protocol")) -v2ray_protocol:value("vmess", translate("Vmess")) -v2ray_protocol:value("http", translate("HTTP")) -v2ray_protocol:value("socks", translate("Socks")) -v2ray_protocol:value("shadowsocks", translate("Shadowsocks")) -v2ray_protocol:value("_balancing", translate("Balancing")) -v2ray_protocol:value("_shunt", translate("Shunt")) -v2ray_protocol:depends("type", "V2ray") +protocol = s:option(ListValue, "protocol", translate("Protocol")) +protocol:value("vmess", translate("Vmess")) +protocol:value("http", translate("HTTP")) +protocol:value("socks", translate("Socks")) +protocol:value("shadowsocks", translate("Shadowsocks")) +protocol:value("_balancing", translate("Balancing")) +protocol:value("_shunt", translate("Shunt")) +protocol:depends("type", "V2ray") local nodes_table = {} uci:foreach(appname, "nodes", function(e) @@ -108,26 +123,26 @@ uci:foreach(appname, "nodes", function(e) end) -- 负载均衡列表 -v2ray_balancing_node = s:option(DynamicList, "v2ray_balancing_node", translate("Load balancing node list"), translate("Load balancing node list, document")) -for k, v in pairs(nodes_table) do v2ray_balancing_node:value(v.id, v.remarks) end -v2ray_balancing_node:depends("v2ray_protocol", "_balancing") +balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, document")) +for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end +balancing_node:depends("protocol", "_balancing") -- 分流 uci:foreach(appname, "shunt_rules", function(e) o = s:option(ListValue, e[".name"], translate(e.remarks)) o:value("nil", translate("Close")) for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end - o:depends("v2ray_protocol", "_shunt") + o:depends("protocol", "_shunt") o = s:option(Flag, e[".name"] .. "_proxy", translate(e.remarks) .. translate("Preproxy"), translate("Use the default node for the transit.")) o.default = 0 - o:depends("v2ray_protocol", "_shunt") + o:depends("protocol", "_shunt") end) default_node = s:option(ListValue, "default_node", translate("Default") .. " " .. translate("Node")) default_node:value("nil", translate("Close")) for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end -default_node:depends("v2ray_protocol", "_shunt") +default_node:depends("protocol", "_shunt") -- Brook协议 brook_protocol = s:option(ListValue, "brook_protocol", @@ -144,12 +159,13 @@ address.rmempty = false address:depends("type", "Socks") address:depends("type", "SS") address:depends("type", "SSR") -address:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -address:depends({ type = "V2ray", v2ray_protocol = "http" }) -address:depends({ type = "V2ray", v2ray_protocol = "socks" }) -address:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +address:depends({ type = "V2ray", protocol = "vmess" }) +address:depends({ type = "V2ray", protocol = "http" }) +address:depends({ type = "V2ray", protocol = "socks" }) +address:depends({ type = "V2ray", protocol = "shadowsocks" }) address:depends("type", "Brook") address:depends("type", "Trojan") +address:depends("type", "Trojan-Go") --[[ use_ipv6 = s:option(Flag, "use_ipv6", translate("Use IPv6")) @@ -157,12 +173,13 @@ use_ipv6.default = 0 use_ipv6:depends("type", "Socks") use_ipv6:depends("type", "SS") use_ipv6:depends("type", "SSR") -use_ipv6:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -use_ipv6:depends({ type = "V2ray", v2ray_protocol = "http" }) -use_ipv6:depends({ type = "V2ray", v2ray_protocol = "socks" }) -use_ipv6:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +use_ipv6:depends({ type = "V2ray", protocol = "vmess" }) +use_ipv6:depends({ type = "V2ray", protocol = "http" }) +use_ipv6:depends({ type = "V2ray", protocol = "socks" }) +use_ipv6:depends({ type = "V2ray", protocol = "shadowsocks" }) use_ipv6:depends("type", "Brook") use_ipv6:depends("type", "Trojan") +use_ipv6:depends("type", "Trojan-Go") --]] port = s:option(Value, "port", translate("Port")) @@ -171,17 +188,18 @@ port.rmempty = false port:depends("type", "Socks") port:depends("type", "SS") port:depends("type", "SSR") -port:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -port:depends({ type = "V2ray", v2ray_protocol = "http" }) -port:depends({ type = "V2ray", v2ray_protocol = "socks" }) -port:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +port:depends({ type = "V2ray", protocol = "vmess" }) +port:depends({ type = "V2ray", protocol = "http" }) +port:depends({ type = "V2ray", protocol = "socks" }) +port:depends({ type = "V2ray", protocol = "shadowsocks" }) port:depends("type", "Brook") port:depends("type", "Trojan") +port:depends("type", "Trojan-Go") username = s:option(Value, "username", translate("Username")) username:depends("type", "Socks") -username:depends("v2ray_protocol", "http") -username:depends("v2ray_protocol", "socks") +username:depends("protocol", "http") +username:depends("protocol", "socks") password = s:option(Value, "password", translate("Password")) password.password = true @@ -190,9 +208,10 @@ password:depends("type", "SS") password:depends("type", "SSR") password:depends("type", "Brook") password:depends("type", "Trojan") -password:depends("v2ray_protocol", "http") -password:depends("v2ray_protocol", "socks") -password:depends("v2ray_protocol", "shadowsocks") +password:depends("type", "Trojan-Go") +password:depends("protocol", "http") +password:depends("protocol", "socks") +password:depends("protocol", "shadowsocks") ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method")) @@ -204,24 +223,24 @@ ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method", for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end ssr_encrypt_method:depends("type", "SSR") -v2ray_security = s:option(ListValue, "v2ray_security", +security = s:option(ListValue, "security", translate("Encrypt Method")) -for a, t in ipairs(v2ray_security_list) do v2ray_security:value(t) end -v2ray_security:depends("v2ray_protocol", "vmess") +for a, t in ipairs(security_list) do security:value(t) end +security:depends("protocol", "vmess") -v2ray_ss_encrypt_method = s:option(ListValue, "v2ray_ss_encrypt_method", +v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(v2ray_ss_encrypt_method_list) do v2ray_ss_encrypt_method:value(t) end -v2ray_ss_encrypt_method:depends("v2ray_protocol", "shadowsocks") +for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end +v_ss_encrypt_method:depends("protocol", "shadowsocks") -v2ray_ss_ota = s:option(Flag, "v2ray_ss_ota", translate("OTA"), translate( +ss_ota = s:option(Flag, "ss_ota", translate("OTA"), translate( "When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption.")) -v2ray_ss_ota.default = "0" -v2ray_ss_ota:depends("v2ray_protocol", "shadowsocks") +ss_ota.default = "0" +ss_ota:depends("protocol", "shadowsocks") -protocol = s:option(ListValue, "protocol", translate("Protocol")) -for a, t in ipairs(ssr_protocol_list) do protocol:value(t) end -protocol:depends("type", "SSR") +ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol")) +for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end +ssr_protocol:depends("type", "SSR") protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) protocol_param:depends("type", "SSR") @@ -246,6 +265,7 @@ tcp_fast_open:value("true") tcp_fast_open:depends("type", "SS") tcp_fast_open:depends("type", "SSR") tcp_fast_open:depends("type", "Trojan") +tcp_fast_open:depends("type", "Trojan-Go") ss_plugin = s:option(ListValue, "ss_plugin", translate("plugin")) ss_plugin:value("none", translate("none")) @@ -281,205 +301,281 @@ kcp_opts.placeholder = "--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast" kcp_opts:depends("use_kcp", "1") -v2ray_VMess_id = s:option(Value, "v2ray_VMess_id", translate("ID")) -v2ray_VMess_id.password = true -v2ray_VMess_id:depends("v2ray_protocol", "vmess") +vmess_id = s:option(Value, "vmess_id", translate("ID")) +vmess_id.password = true +vmess_id:depends("protocol", "vmess") -v2ray_VMess_alterId = s:option(Value, "v2ray_VMess_alterId", +alter_id = s:option(Value, "alter_id", translate("Alter ID")) -v2ray_VMess_alterId:depends("v2ray_protocol", "vmess") +alter_id:depends("protocol", "vmess") -v2ray_VMess_level = - s:option(Value, "v2ray_VMess_level", translate("User Level")) -v2ray_VMess_level.default = 1 -v2ray_VMess_level:depends("v2ray_protocol", "vmess") +vmess_level = + s:option(Value, "vmess_level", translate("User Level")) +vmess_level.default = 1 +vmess_level:depends("protocol", "vmess") -v2ray_stream_security = s:option(ListValue, "v2ray_stream_security", +stream_security = s:option(ListValue, "stream_security", translate("Transport Layer Encryption"), translate( 'Whether or not transport layer encryption is enabled, the supported options are "none" for unencrypted (default) and "TLS" for using TLS.')) -v2ray_stream_security:value("none", "none") -v2ray_stream_security:value("tls", "tls") -v2ray_stream_security:depends("v2ray_protocol", "vmess") -v2ray_stream_security:depends("v2ray_protocol", "http") -v2ray_stream_security:depends("v2ray_protocol", "shadowsocks") +stream_security:value("none", "none") +stream_security:value("tls", "tls") +stream_security.default = "tls" +stream_security:depends("protocol", "vmess") +stream_security:depends("protocol", "shadowsocks") +stream_security:depends("type", "Trojan") +stream_security:depends("type", "Trojan-Go") +stream_security.validate = function(self, value) + if value == "none" and type:formvalue(arg[1]) == "Trojan" then + return nil, translate("'none' not supported for original Trojan.") + end + return value +end -- [[ TLS部分 ]] -- -tls_serverName = s:option(Value, "tls_serverName", translate("Domain")) -tls_serverName:depends("v2ray_stream_security", "tls") -tls_serverName:depends("trojan_verify_cert", "1") -tls_allowInsecure = s:option(Flag, "tls_allowInsecure", - translate("allowInsecure"), translate( +tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) +tls_sessionTicket.default = "0" +tls_sessionTicket:depends("stream_security", "tls") + +-- [[ Trojan TLS ]]-- + +trojan_force_fp = s:option(ListValue, "fingerprint", translate("Finger Print")) +for a, t in ipairs(force_fp) do trojan_force_fp:value(t) end +trojan_force_fp.default = "firefox" +trojan_force_fp:depends({ type = "Trojan-Go", stream_security = "tls" }) + +tls_serverName = s:option(Value, "tls_serverName", translate("Domain")) +tls_serverName:depends("stream_security", "tls") + +tls_allowInsecure = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate( "Whether unsafe connections are allowed. When checked, V2Ray does not check the validity of the TLS certificate provided by the remote host.")) tls_allowInsecure.default = "0" -tls_allowInsecure.rmempty = false -tls_allowInsecure:depends("v2ray_stream_security", "tls") +tls_allowInsecure:depends("stream_security", "tls") -v2ray_transport = s:option(ListValue, "v2ray_transport", translate("Transport")) -v2ray_transport:value("tcp", "TCP") -v2ray_transport:value("mkcp", "mKCP") -v2ray_transport:value("ws", "WebSocket") -v2ray_transport:value("h2", "HTTP/2") -v2ray_transport:value("ds", "DomainSocket") -v2ray_transport:value("quic", "QUIC") -v2ray_transport:depends("v2ray_protocol", "vmess") +-- [[ Trojan Cert ]]-- + +trojan_cert_path = s:option(Value, "trojan_cert_path", translate("Trojan Cert Path")) +trojan_cert_path.default = "" +trojan_cert_path:depends({ stream_security = "tls", tls_allowInsecure = false }) + +trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport")) +trojan_transport:value("original", "Original") +trojan_transport:value("ws", "WebSocket") +trojan_transport:value("h2", "HTTP/2") +trojan_transport:value("h2+ws", "HTTP/2 & WebSocket") +trojan_transport.default = "ws" +trojan_transport:depends("type", "Trojan-Go") + +trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type")) +trojan_plugin:value("plaintext", "Plain Text") +trojan_plugin:value("shadowsocks", "ShadowSocks") +trojan_plugin:value("other", "Other") +trojan_plugin.default = "plaintext" +trojan_plugin:depends({ stream_security = "none", trojan_transport = "original" }) + +trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary")) +trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin" +trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_cmd:depends({ plugin_type = "other" }) + +trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option")) +trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com" +trojan_plugin_op:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_op:depends({ plugin_type = "other" }) + +trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args")) +trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]" +trojan_plugin_arg:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_arg:depends({ plugin_type = "other" }) + +transport = s:option(ListValue, "transport", translate("Transport")) +transport:value("tcp", "TCP") +transport:value("mkcp", "mKCP") +transport:value("ws", "WebSocket") +transport:value("h2", "HTTP/2") +transport:value("ds", "DomainSocket") +transport:value("quic", "QUIC") +transport:depends("protocol", "vmess") --[[ -v2ray_ss_transport = s:option(ListValue, "v2ray_ss_transport", translate("Transport")) -v2ray_ss_transport:value("ws", "WebSocket") -v2ray_ss_transport:value("h2", "HTTP/2") -v2ray_ss_transport:depends("v2ray_protocol", "shadowsocks") +ss_transport = s:option(ListValue, "ss_transport", translate("Transport")) +ss_transport:value("ws", "WebSocket") +ss_transport:value("h2", "HTTP/2") +ss_transport:value("ws", "WebSocket") +ss_transport:value("h2+ws", "HTTP/2 & WebSocket") +ss_transport:depends("protocol", "shadowsocks") ]]-- -- [[ TCP部分 ]]-- -- TCP伪装 -v2ray_tcp_guise = s:option(ListValue, "v2ray_tcp_guise", +tcp_guise = s:option(ListValue, "tcp_guise", translate("Camouflage Type")) -v2ray_tcp_guise:value("none", "none") -v2ray_tcp_guise:value("http", "http") -v2ray_tcp_guise:depends("v2ray_transport", "tcp") +tcp_guise:value("none", "none") +tcp_guise:value("http", "http") +tcp_guise:depends("transport", "tcp") -- HTTP域名 -v2ray_tcp_guise_http_host = s:option(DynamicList, "v2ray_tcp_guise_http_host", +tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) -v2ray_tcp_guise_http_host:depends("v2ray_tcp_guise", "http") +tcp_guise_http_host:depends("tcp_guise", "http") -- HTTP路径 -v2ray_tcp_guise_http_path = s:option(DynamicList, "v2ray_tcp_guise_http_path", +tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) -v2ray_tcp_guise_http_path:depends("v2ray_tcp_guise", "http") +tcp_guise_http_path:depends("tcp_guise", "http") -- [[ mKCP部分 ]]-- -v2ray_mkcp_guise = s:option(ListValue, "v2ray_mkcp_guise", +mkcp_guise = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate( '
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) -for a, t in ipairs(v2ray_header_type_list) do v2ray_mkcp_guise:value(t) end -v2ray_mkcp_guise:depends("v2ray_transport", "mkcp") +for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end +mkcp_guise:depends("transport", "mkcp") -v2ray_mkcp_mtu = s:option(Value, "v2ray_mkcp_mtu", translate("KCP MTU")) -v2ray_mkcp_mtu:depends("v2ray_transport", "mkcp") +mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU")) +mkcp_mtu:depends("transport", "mkcp") -v2ray_mkcp_tti = s:option(Value, "v2ray_mkcp_tti", translate("KCP TTI")) -v2ray_mkcp_tti:depends("v2ray_transport", "mkcp") +mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI")) +mkcp_tti:depends("transport", "mkcp") -v2ray_mkcp_uplinkCapacity = s:option(Value, "v2ray_mkcp_uplinkCapacity", +mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity", translate("KCP uplinkCapacity")) -v2ray_mkcp_uplinkCapacity:depends("v2ray_transport", "mkcp") +mkcp_uplinkCapacity:depends("transport", "mkcp") -v2ray_mkcp_downlinkCapacity = s:option(Value, "v2ray_mkcp_downlinkCapacity", +mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity", translate("KCP downlinkCapacity")) -v2ray_mkcp_downlinkCapacity:depends("v2ray_transport", "mkcp") +mkcp_downlinkCapacity:depends("transport", "mkcp") -v2ray_mkcp_congestion = s:option(Flag, "v2ray_mkcp_congestion", +mkcp_congestion = s:option(Flag, "mkcp_congestion", translate("KCP Congestion")) -v2ray_mkcp_congestion:depends("v2ray_transport", "mkcp") +mkcp_congestion:depends("transport", "mkcp") -v2ray_mkcp_readBufferSize = s:option(Value, "v2ray_mkcp_readBufferSize", +mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize", translate("KCP readBufferSize")) -v2ray_mkcp_readBufferSize:depends("v2ray_transport", "mkcp") +mkcp_readBufferSize:depends("transport", "mkcp") -v2ray_mkcp_writeBufferSize = s:option(Value, "v2ray_mkcp_writeBufferSize", +mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize", translate("KCP writeBufferSize")) -v2ray_mkcp_writeBufferSize:depends("v2ray_transport", "mkcp") +mkcp_writeBufferSize:depends("transport", "mkcp") -- [[ WebSocket部分 ]]-- -v2ray_ws_host = s:option(Value, "v2ray_ws_host", translate("WebSocket Host")) -v2ray_ws_host:depends("v2ray_transport", "ws") -v2ray_ws_host:depends("v2ray_ss_transport", "ws") +ws_host = s:option(Value, "ws_host", translate("WebSocket Host")) +ws_host:depends("transport", "ws") +ws_host:depends("ss_transport", "ws") +ws_host:depends("trojan_transport", "h2+ws") +ws_host:depends("trojan_transport", "ws") -v2ray_ws_path = s:option(Value, "v2ray_ws_path", translate("WebSocket Path")) -v2ray_ws_path:depends("v2ray_transport", "ws") -v2ray_ws_path:depends("v2ray_ss_transport", "ws") +ws_path = s:option(Value, "ws_path", translate("WebSocket Path")) +ws_path:depends("transport", "ws") +ws_path:depends("ss_transport", "ws") +ws_path:depends("trojan_transport", "h2+ws") +ws_path:depends("trojan_transport", "ws") -- [[ HTTP/2部分 ]]-- -v2ray_h2_host = s:option(DynamicList, "v2ray_h2_host", translate("HTTP/2 Host")) -v2ray_h2_host:depends("v2ray_transport", "h2") -v2ray_h2_host:depends("v2ray_ss_transport", "h2") +h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host")) +h2_host:depends("transport", "h2") +h2_host:depends("ss_transport", "h2") +h2_host:depends("trojan_transport", "h2+ws") +h2_host:depends("trojan_transport", "h2") -v2ray_h2_path = s:option(Value, "v2ray_h2_path", translate("HTTP/2 Path")) -v2ray_h2_path:depends("v2ray_transport", "h2") -v2ray_h2_path:depends("v2ray_ss_transport", "h2") +h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path")) +h2_path:depends("transport", "h2") +h2_path:depends("ss_transport", "h2") +h2_path:depends("trojan_transport", "h2+ws") +h2_path:depends("trojan_transport", "h2") -- [[ DomainSocket部分 ]]-- -v2ray_ds_path = s:option(Value, "v2ray_ds_path", "Path", translate( +ds_path = s:option(Value, "ds_path", "Path", translate( "A legal file path. This file must not exist before running V2Ray.")) -v2ray_ds_path:depends("v2ray_transport", "ds") +ds_path:depends("transport", "ds") -- [[ QUIC部分 ]]-- -v2ray_quic_security = s:option(ListValue, "v2ray_quic_security", +quic_security = s:option(ListValue, "quic_security", translate("Encrypt Method")) -v2ray_quic_security:value("none") -v2ray_quic_security:value("aes-128-gcm") -v2ray_quic_security:value("chacha20-poly1305") -v2ray_quic_security:depends("v2ray_transport", "quic") +quic_security:value("none") +quic_security:value("aes-128-gcm") +quic_security:value("chacha20-poly1305") +quic_security:depends("transport", "quic") -v2ray_quic_key = s:option(Value, "v2ray_quic_key", +quic_key = s:option(Value, "quic_key", translate("Encrypt Method") .. translate("Key")) -v2ray_quic_key:depends("v2ray_transport", "quic") +quic_key:depends("transport", "quic") -v2ray_quic_guise = s:option(ListValue, "v2ray_quic_guise", +quic_guise = s:option(ListValue, "quic_guise", translate("Camouflage Type")) -for a, t in ipairs(v2ray_header_type_list) do v2ray_quic_guise:value(t) end -v2ray_quic_guise:depends("v2ray_transport", "quic") +for a, t in ipairs(header_type_list) do quic_guise:value(t) end +quic_guise:depends("transport", "quic") + +-- [[ Trojan-Go Shadowsocks2 ]] -- + +ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) +ss_aead:depends("type", "Trojan-Go") +ss_aead.default = "0" + +ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method")) +for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v:upper()) end +ss_aead_method.default = "aead_aes_128_gcm" +ss_aead_method:depends("ss_aead", "1") + +ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password")) +ss_aead_pwd.password = true +ss_aead_pwd:depends("ss_aead", "1") -- [[ Mux ]]-- -v2ray_mux = s:option(Flag, "v2ray_mux", translate("Mux")) -v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "http" }) -v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "socks" }) -v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +mux = s:option(Flag, "mux", translate("Mux")) +mux:depends({ type = "V2ray", protocol = "vmess" }) +mux:depends({ type = "V2ray", protocol = "http" }) +mux:depends({ type = "V2ray", protocol = "socks" }) +mux:depends({ type = "V2ray", protocol = "shadowsocks" }) +mux:depends("type", "Trojan-Go") -v2ray_mux_concurrency = s:option(Value, "v2ray_mux_concurrency", - translate("Mux Concurrency")) -v2ray_mux_concurrency.default = 8 -v2ray_mux_concurrency:depends("v2ray_mux", "1") +mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux Concurrency")) +mux_concurrency.default = 8 +mux_concurrency:depends("mux", "1") -- [[ 当作为TCP节点时,是否同时开启socks代理 ]]-- --[[ -v2ray_tcp_socks = s:option(Flag, "v2ray_tcp_socks", translate("TCP Open Socks"), +tcp_socks = s:option(Flag, "tcp_socks", translate("TCP Open Socks"), translate( "When using this TCP node, whether to open the socks proxy at the same time")) -v2ray_tcp_socks.default = 0 -v2ray_tcp_socks:depends("type", "V2ray") +tcp_socks.default = 0 +tcp_socks:depends("type", "V2ray") -v2ray_tcp_socks_port = s:option(Value, "v2ray_tcp_socks_port", +tcp_socks_port = s:option(Value, "tcp_socks_port", "Socks " .. translate("Port"), translate("Do not conflict with other ports")) -v2ray_tcp_socks_port.datatype = "port" -v2ray_tcp_socks_port.default = 1080 -v2ray_tcp_socks_port:depends("v2ray_tcp_socks", "1") +tcp_socks_port.datatype = "port" +tcp_socks_port.default = 1080 +tcp_socks_port:depends("tcp_socks", "1") -v2ray_tcp_socks_auth = s:option(ListValue, "v2ray_tcp_socks_auth", +tcp_socks_auth = s:option(ListValue, "tcp_socks_auth", translate("Socks for authentication"), translate( 'Socks protocol authentication, support anonymous and password.')) -v2ray_tcp_socks_auth:value("noauth", translate("anonymous")) -v2ray_tcp_socks_auth:value("password", translate("User Password")) -v2ray_tcp_socks_auth:depends("v2ray_tcp_socks", "1") +tcp_socks_auth:value("noauth", translate("anonymous")) +tcp_socks_auth:value("password", translate("User Password")) +tcp_socks_auth:depends("tcp_socks", "1") -v2ray_tcp_socks_auth_username = s:option(Value, "v2ray_tcp_socks_auth_username", +tcp_socks_auth_username = s:option(Value, "tcp_socks_auth_username", "Socks " .. translate("Username")) -v2ray_tcp_socks_auth_username:depends("v2ray_tcp_socks_auth", "password") +tcp_socks_auth_username:depends("tcp_socks_auth", "password") -v2ray_tcp_socks_auth_password = s:option(Value, "v2ray_tcp_socks_auth_password", +tcp_socks_auth_password = s:option(Value, "tcp_socks_auth_password", "Socks " .. translate("Password")) -v2ray_tcp_socks_auth_password:depends("v2ray_tcp_socks_auth", "password") +tcp_socks_auth_password:depends("tcp_socks_auth", "password") --]] --- [[ Trojan Cert ]]-- -trojan_verify_cert = s:option(Flag, "trojan_verify_cert", - translate("Trojan Verify Cert")) -trojan_verify_cert:depends("type", "Trojan") - -trojan_cert_path = s:option(Value, "trojan_cert_path", - translate("Trojan Cert Path")) -trojan_cert_path.default = "" -trojan_cert_path:depends("trojan_verify_cert", "1") +protocol.validate = function(self, value) + if value == "_shunt" or value == "_balancing" then + address.rmempty = true + port.rmempty = true + end + return value +end return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_list.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_list.lua index 30a80d41ad..b573e4b5d6 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_list.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/node_list.lua @@ -72,7 +72,7 @@ if m:get("@global_other[0]", "compact_display_nodes") == "1" then local remarks = m:get(n, "remarks") or "" local type = m:get(n, "type") or "" if type == "V2ray" then - local protocol = m:get(n, "v2ray_protocol") + local protocol = m:get(n, "protocol") if protocol == "_balancing" then type = type .. " 负载均衡" elseif protocol == "_shunt" then @@ -111,7 +111,7 @@ else if v then result = translate(v) if v == "V2ray" then - local protocol = m:get(n, "v2ray_protocol") + local protocol = m:get(n, "protocol") if protocol == "_balancing" then result = result .. " 负载均衡" elseif protocol == "_shunt" then @@ -149,7 +149,7 @@ end o.cfgvalue = function(t, n) local type = m:get(n, "type") or "" if type == "V2ray" then - local protocol = m:get(n, "v2ray_protocol","") + local protocol = m:get(n, "protocol","") if protocol == "_balancing" or protocol == "_shunt" then return "---" end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/other.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/other.lua index e13c578110..3fe56770cc 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/other.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/other.lua @@ -165,8 +165,8 @@ local nodes_table = {} uci:foreach(appname, "nodes", function(e) if e.type and e.remarks then local remarks = "" - if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then - remarks = "%s:[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks} + if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then + remarks = "%s:[%s] " % {translatef(e.type .. e.protocol), e.remarks} else if e.use_kcp and e.use_kcp == "1" then remarks = "%s+%s:[%s] %s" % {e.type, "Kcptun", e.remarks, e.address} diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua index 4334742134..ffac408df9 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua @@ -69,32 +69,37 @@ s = m:section(TypedSection, "global_app", translate("App Update"), "") s.anonymous = true s:append(Template(appname .. "/rule/v2ray_version")) +s:append(Template(appname .. "/rule/trojan_go_version")) s:append(Template(appname .. "/rule/kcptun_version")) s:append(Template(appname .. "/rule/brook_version")) ---- V2ray Path -o = s:option(Value, "v2ray_file", translate("V2ray Path"), translate( - "if you want to run from memory, change the path, such as /tmp/v2ray/, Then save the application and update it manually.")) +o = s:option(Value, "v2ray_file", translate("V2ray Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/v2ray/")) o.default = "/usr/bin/v2ray/" o.rmempty = false +---- Trojan-Go Path +o = s:option(Value, "trojan_go_file", translate("Trojan-Go Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/trojan-go")) +o.default = "/usr/bin/trojan-go" +o.rmempty = false + +o = s:option(Value, "trojan_go_latest", translate("Trojan-Go Version API"), translate("alternate API URL for version checking")) +o.default = "https://api.github.com/repos/peter-tank/trojan-go/releases/latest" + ---- Kcptun client Path -o = s:option(Value, "kcptun_client_file", translate("Kcptun Client Path"), - translate( - "if you want to run from memory, change the path, such as /tmp/kcptun-client, Then save the application and update it manually.")) +o = s:option(Value, "kcptun_client_file", translate("Kcptun Client Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/kcptun-client")) o.default = "/usr/bin/kcptun-client" o.rmempty = false --[[ -o = s:option(Button, "_check_kcptun", translate("Manually update"), translate("Make sure there is enough space to install Kcptun")) +o = s:option(Button, "_check_kcptun", translate("Manually update"), translatef("Make sure there is enough space to install %s", "kcptun")) o.template = appname .. "/kcptun" o.inputstyle = "apply" o.btnclick = "onBtnClick_kcptun(this);" o.id = "_kcptun-check_btn"]] -- ---- Brook Path -o = s:option(Value, "brook_file", translate("Brook Path"), translate( - "if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually.")) +o = s:option(Value, "brook_file", translate("Brook Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/brook")) o.default = "/usr/bin/brook" o.rmempty = false diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/ssr.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/ssr.lua index 2651f328c2..a00dd0fb23 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/ssr.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/ssr.lua @@ -7,7 +7,7 @@ function gen_config(user) config.timeout = tonumber(user.timeout) config.fast_open = (user.tcp_fast_open and user.tcp_fast_open == "true") and true or false config.method = user.ssr_encrypt_method - config.protocol = user.protocol + config.protocol = user.ssr_protocol config.protocol_param = user.protocol_param config.obfs = user.obfs config.obfs_param = user.obfs_param diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua index 077998c3f7..a32319fcf2 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua @@ -1,28 +1,58 @@ module("luci.model.cbi.passwall.server.api.trojan", package.seeall) function gen_config(user) + local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" + local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" local config = { run_type = "server", local_addr = "0.0.0.0", local_port = tonumber(user.port), remote_addr = (user.remote_enable == "1" and user.remote_address) and user.remote_address or nil, remote_port = (user.remote_enable == "1" and user.remote_port) and user.remote_port or nil, - password = user.password, + password = { user.password }, log_level = 1, - ssl = { + (user.stream_security == nil or user.stream_security == "tls") and ssl = { cert = user.tls_certificateFile, key = user.tls_keyFile, key_password = "", - cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA", - cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", - prefer_server_cipher = true, - alpn = {"http/1.1"}, + cipher = user.fingerprint == nil and cipher or (user.fingerprint == "disable" and cipher13 .. ":" .. cipher or ""), + cipher_tls13 = user.fingerprint == nil and cipher13 or nil, + sni = "", + verify = false, + verify_hostname = false, reuse_session = true, - session_ticket = false, + session_ticket = (user.tls_sessionTicket == "1") and true or false, + prefer_server_cipher = true, session_timeout = 600, plain_http_response = "", curves = "", dhparam = "" - }, + } or nil, + udp_timeout = 60, + disable_http_check = true, + tcp = { + mux = (user.mux == "1") and { + enabled = true, + concurrency = tonumber(user.mux_concurrency), + idle_timeout = 60, + } or nil, + transport_plugin = user.stream_security == "none" and user.trojan_transport == "original" and { + enabled = user.plugin_type ~= nil, + type = user.plugin_type or "plaintext", + command = user.plugin_type ~= "plaintext" and user.plugin_cmd or nil, + plugin_option = user.plugin_type ~= "plaintext" and user.plugin_option or nil, + arg = user.plugin_type ~= "plaintext" and { user.plugin_arg } or nil, + env = {} + } or nil, + websocket = user.trojan_transport and user.trojan_transport:find('ws') and { + enabled = true, + path = (user.ws_path ~= nil) and user.ws_path or "/", + hostname = (user.ws_host ~= nil) and user.ws_host or (user.tls_serverName ~= nil and user.tls_serverName or user.address) + } or nil, + shadowsocks = (user.ss_aead == "1") and { + enabled = true, + method = (user.ss_aead_method ~= nil) and user.ss_aead_method or "aead_aes_128_gcm", + password = (user.ss_aead_pwd ~= nil) and user.ss_aead_pwd or "" + } or nil, tcp = { prefer_ipv4 = false, no_delay = true, diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua index 5e0c11af86..bc6023565b 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua @@ -8,19 +8,19 @@ function gen_config(user) {protocol = "freedom"}, {protocol = "blackhole", tag = "blocked"} } - if user.v2ray_protocol == "vmess" then + if user.protocol == "vmess" then if user.vmess_id then local clients = {} for i = 1, #user.vmess_id do clients[i] = { id = user.vmess_id[i], level = tonumber(user.vmess_level), - alterId = tonumber(user.vmess_alterId) + alterId = tonumber(user.alter_id) } end settings = {clients = clients} end - elseif user.v2ray_protocol == "socks" then + elseif user.protocol == "socks" then settings = { auth = (user.username == nil and user.password == nil) and "noauth" or "password", accounts = { @@ -30,7 +30,7 @@ function gen_config(user) } } } - elseif user.v2ray_protocol == "http" then + elseif user.protocol == "http" then settings = { allowTransparent = false, accounts = { @@ -40,13 +40,13 @@ function gen_config(user) } } } - elseif user.v2ray_protocol == "shadowsocks" then + elseif user.protocol == "shadowsocks" then settings = { - method = user.v2ray_ss_encrypt_method, + method = user.ss_encrypt_method, password = user.password, level = tonumber(user.vmess_level) or 1, - network = user.v2ray_ss_network or "TCP,UDP", - ota = (user.v2ray_ss_ota == '1') and true or false + network = user.ss_network or "TCP,UDP", + ota = (user.ss_ota == '1') and true or false } end @@ -68,84 +68,83 @@ function gen_config(user) if node and node ~= "nil" and node.type and node.type == "V2ray" then local transit_node = { tag = "transit", - protocol = node.v2ray_protocol or "vmess", + protocol = node.protocol or "vmess", mux = { - enabled = (node.v2ray_mux == "1") and true or false, - concurrency = (node.v2ray_mux_concurrency) and - tonumber(node.v2ray_mux_concurrency) or 8 + enabled = (node.mux == "1") and true or false, + concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 }, -- 底层传输配置 - streamSettings = (node.v2ray_protocol == "vmess") and { - network = node.v2ray_transport, - security = node.v2ray_stream_security, - tlsSettings = (node.v2ray_stream_security == "tls") and { + streamSettings = (node.protocol == "vmess") and { + network = node.transport, + security = node.stream_security, + tlsSettings = (node.stream_security == "tls") and { + disableSessionResumption = node.sessionTicket ~= "1" and true or false, serverName = node.tls_serverName, allowInsecure = (node.tls_allowInsecure == "1") and true or false } or nil, - tcpSettings = (node.v2ray_transport == "tcp") and { + tcpSettings = (node.transport == "tcp") and { header = { - type = node.v2ray_tcp_guise, + type = node.tcp_guise, request = { - path = node.v2ray_tcp_guise_http_path or {"/"}, + path = node.tcp_guise_http_path or {"/"}, headers = { - Host = node.v2ray_tcp_guise_http_host or {} + Host = node.tcp_guise_http_host or {} } } or {} } } or nil, - kcpSettings = (node.v2ray_transport == "mkcp") and { - mtu = tonumber(node.v2ray_mkcp_mtu), - tti = tonumber(node.v2ray_mkcp_tti), - uplinkCapacity = tonumber(node.v2ray_mkcp_uplinkCapacity), + kcpSettings = (node.transport == "mkcp") and { + mtu = tonumber(node.mkcp_mtu), + tti = tonumber(node.mkcp_tti), + uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), downlinkCapacity = tonumber( - node.v2ray_mkcp_downlinkCapacity), - congestion = (node.v2ray_mkcp_congestion == "1") and + node.mkcp_downlinkCapacity), + congestion = (node.mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(node.v2ray_mkcp_readBufferSize), + readBufferSize = tonumber(node.mkcp_readBufferSize), writeBufferSize = tonumber( - node.v2ray_mkcp_writeBufferSize), - header = {type = node.v2ray_mkcp_guise} + node.mkcp_writeBufferSize), + header = {type = node.mkcp_guise} } or nil, - wsSettings = (node.v2ray_transport == "ws") and { - path = node.v2ray_ws_path or "", - headers = (node.v2ray_ws_host ~= nil) and - {Host = node.v2ray_ws_host} or nil + wsSettings = (node.transport == "ws") and { + path = node.ws_path or "", + headers = (node.ws_host ~= nil) and + {Host = node.ws_host} or nil } or nil, - httpSettings = (node.v2ray_transport == "h2") and - {path = node.v2ray_h2_path, host = node.v2ray_h2_host} or + httpSettings = (node.transport == "h2") and + {path = node.h2_path, host = node.h2_host} or nil, - dsSettings = (node.v2ray_transport == "ds") and - {path = node.v2ray_ds_path} or nil, - quicSettings = (node.v2ray_transport == "quic") and { - security = node.v2ray_quic_security, - key = node.v2ray_quic_key, - header = {type = node.v2ray_quic_guise} + dsSettings = (node.transport == "ds") and + {path = node.ds_path} or nil, + quicSettings = (node.transport == "quic") and { + security = node.quic_security, + key = node.quic_key, + header = {type = node.quic_guise} } or nil } or nil, settings = { - vnext = (node.v2ray_protocol == "vmess") and { + vnext = (node.protocol == "vmess") and { { address = node.address, port = tonumber(node.port), users = { { - id = node.v2ray_VMess_id, - alterId = tonumber(node.v2ray_VMess_alterId), - level = tonumber(node.v2ray_VMess_level), - security = node.v2ray_security + id = node.vmess_id, + alterId = tonumber(node.alter_id), + level = tonumber(node.vmess_level), + security = node.security } } } } or nil, - servers = (node.v2ray_protocol == "http" or - node.v2ray_protocol == "socks" or node.v2ray_protocol == "shadowsocks") and { + servers = (node.protocol == "http" or node.protocol == "socks" or node.protocol == "shadowsocks") and { { address = node.address, port = tonumber(node.port), - method = node.v2ray_ss_encrypt_method, + method = node.v_ss_encrypt_method, password = node.password or "", - ota = (node.v2ray_ss_ota == '1') and true or false, + ota = (node.ss_ota == '1') and true or false, users = (node.username and node.password) and { { @@ -171,13 +170,14 @@ function gen_config(user) { listen = (user.bind_local == "1") and "127.0.0.1" or nil, port = tonumber(user.port), - protocol = user.v2ray_protocol, + protocol = user.protocol, -- 底层传输配置 settings = settings, - streamSettings = (user.v2ray_protocol == "vmess") and { - network = user.v2ray_transport, - security = (user.tls_enable == '1') and "tls" or "none", - tlsSettings = (user.tls_enable == '1') and { + streamSettings = (user.protocol == "vmess") and { + network = user.transport, + security = (user.stream_security == 'tls') and "tls" or "none", + tlsSettings = (user.stream_security == 'tls') and { + disableSessionResumption = user.sessionTicket ~= "1" and true or false, -- serverName = (user.tls_serverName), allowInsecure = false, disableSystemRoot = false, @@ -188,41 +188,41 @@ function gen_config(user) } } } or nil, - tcpSettings = (user.v2ray_transport == "tcp") and { + tcpSettings = (user.transport == "tcp") and { header = { - type = user.v2ray_tcp_guise, + type = user.tcp_guise, request = { - path = user.v2ray_tcp_guise_http_path or {"/"}, + path = user.tcp_guise_http_path or {"/"}, headers = { - Host = user.v2ray_tcp_guise_http_host or {} + Host = user.tcp_guise_http_host or {} } } or {} } } or nil, - kcpSettings = (user.v2ray_transport == "mkcp") and { - mtu = tonumber(user.v2ray_mkcp_mtu), - tti = tonumber(user.v2ray_mkcp_tti), - uplinkCapacity = tonumber(user.v2ray_mkcp_uplinkCapacity), - downlinkCapacity = tonumber(user.v2ray_mkcp_downlinkCapacity), - congestion = (user.v2ray_mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(user.v2ray_mkcp_readBufferSize), - writeBufferSize = tonumber(user.v2ray_mkcp_writeBufferSize), - header = {type = user.v2ray_mkcp_guise} + kcpSettings = (user.transport == "mkcp") and { + mtu = tonumber(user.mkcp_mtu), + tti = tonumber(user.mkcp_tti), + uplinkCapacity = tonumber(user.mkcp_uplinkCapacity), + downlinkCapacity = tonumber(user.mkcp_downlinkCapacity), + congestion = (user.mkcp_congestion == "1") and true or false, + readBufferSize = tonumber(user.mkcp_readBufferSize), + writeBufferSize = tonumber(user.mkcp_writeBufferSize), + header = {type = user.mkcp_guise} } or nil, - wsSettings = (user.v2ray_transport == "ws") and + wsSettings = (user.transport == "ws") and { - headers = (user.v2ray_ws_host) and {Host = user.v2ray_ws_host} or + headers = (user.ws_host) and {Host = user.ws_host} or nil, - path = user.v2ray_ws_path + path = user.ws_path } or nil, - httpSettings = (user.v2ray_transport == "h2") and - {path = user.v2ray_h2_path, host = user.v2ray_h2_host} or nil, - dsSettings = (user.v2ray_transport == "ds") and - {path = user.v2ray_ds_path} or nil, - quicSettings = (user.v2ray_transport == "quic") and { - security = user.v2ray_quic_security, - key = user.v2ray_quic_key, - header = {type = user.v2ray_quic_guise} + httpSettings = (user.transport == "h2") and + {path = user.h2_path, host = user.h2_host} or nil, + dsSettings = (user.transport == "ds") and + {path = user.ds_path} or nil, + quicSettings = (user.transport == "quic") and { + security = user.quic_security, + key = user.quic_key, + header = {type = user.quic_guise} } or nil } 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 9f91afee87..c581af4afe 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 @@ -31,14 +31,24 @@ local ssr_obfs_list = { "tls1.0_session_auth", "tls1.2_ticket_auth" } -local v2ray_ss_encrypt_method_list = { +local v_ss_encrypt_method_list = { "aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305" } -local v2ray_header_type_list = { +local header_type_list = { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" } +local encrypt_methods_ss_aead = { + "dummy", + "aead_chacha20_poly1305", + "aead_aes_128_gcm", + "aead_aes_256_gcm", + "chacha20-ietf-poly1305", + "aes-128-gcm", + "aes-256-gcm", +} + map = Map("passwall_server", translate("Server Config")) map.redirect = d.build_url("admin", "vpn", "passwall", "server") @@ -65,15 +75,18 @@ if is_installed("brook") or is_finded("brook") then type:value("Brook", translate("Brook")) end if is_installed("trojan") or is_finded("trojan") then - type:value("Trojan", translate("Trojan")) + type:value("Trojan", translate("Trojan-Plus")) +end +if is_installed("trojan-go") or is_finded("trojan-go") then + type:value("Trojan-Go", translate("Trojan-Go")) end -v2ray_protocol = s:option(ListValue, "v2ray_protocol", translate("Protocol")) -v2ray_protocol:value("vmess", translate("Vmess")) -v2ray_protocol:value("http", translate("HTTP")) -v2ray_protocol:value("socks", translate("Socks")) -v2ray_protocol:value("shadowsocks", translate("Shadowsocks")) -v2ray_protocol:depends("type", "V2ray") +protocol = s:option(ListValue, "protocol", translate("Protocol")) +protocol:value("vmess", translate("Vmess")) +protocol:value("http", translate("HTTP")) +protocol:value("socks", translate("Socks")) +protocol:value("shadowsocks", translate("Shadowsocks")) +protocol:depends("type", "V2ray") -- Brook协议 brook_protocol = s:option(ListValue, "brook_protocol", @@ -89,51 +102,53 @@ port = s:option(Value, "port", translate("Port")) port.datatype = "port" port.rmempty = false port:depends("type", "SSR") -port:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -port:depends({ type = "V2ray", v2ray_protocol = "http" }) -port:depends({ type = "V2ray", v2ray_protocol = "socks" }) -port:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +port:depends({ type = "V2ray", protocol = "vmess" }) +port:depends({ type = "V2ray", protocol = "http" }) +port:depends({ type = "V2ray", protocol = "socks" }) +port:depends({ type = "V2ray", protocol = "shadowsocks" }) port:depends("type", "Brook") port:depends("type", "Trojan") +port:depends("type", "Trojan-Go") username = s:option(Value, "username", translate("Username")) -username:depends("v2ray_protocol", "http") -username:depends("v2ray_protocol", "socks") +username:depends("protocol", "http") +username:depends("protocol", "socks") password = s:option(Value, "password", translate("Password")) password.password = true password:depends("type", "SSR") password:depends("type", "Brook") password:depends("type", "Trojan") -password:depends({ type = "V2ray", v2ray_protocol = "http" }) -password:depends({ type = "V2ray", v2ray_protocol = "socks" }) -password:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +password:depends("type", "Trojan-Go") +password:depends({ type = "V2ray", protocol = "http" }) +password:depends({ type = "V2ray", protocol = "socks" }) +password:depends({ type = "V2ray", protocol = "shadowsocks" }) ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method", translate("Encrypt Method")) for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end ssr_encrypt_method:depends("type", "SSR") -v2ray_ss_encrypt_method = s:option(ListValue, "v2ray_ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(v2ray_ss_encrypt_method_list) do v2ray_ss_encrypt_method:value(t) end -v2ray_ss_encrypt_method:depends("v2ray_protocol", "shadowsocks") +v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method")) +for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end +v_ss_encrypt_method:depends("protocol", "shadowsocks") -v2ray_ss_network = s:option(ListValue, "v2ray_ss_network", translate("Transport")) -v2ray_ss_network.default = "tcp,udp" -v2ray_ss_network:value("tcp", "TCP") -v2ray_ss_network:value("udp", "UDP") -v2ray_ss_network:value("tcp,udp", "TCP,UDP") -v2ray_ss_network:depends("v2ray_protocol", "shadowsocks") +ss_network = s:option(ListValue, "ss_network", translate("Transport")) +ss_network.default = "tcp,udp" +ss_network:value("tcp", "TCP") +ss_network:value("udp", "UDP") +ss_network:value("tcp,udp", "TCP,UDP") +ss_network:depends("protocol", "shadowsocks") -v2ray_ss_ota = s:option(Flag, "v2ray_ss_ota", translate("OTA"), translate("When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption.")) -v2ray_ss_ota.default = "0" -v2ray_ss_ota:depends("v2ray_protocol", "shadowsocks") +ss_ota = s:option(Flag, "ss_ota", translate("OTA"), translate("When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption.")) +ss_ota.default = "0" +ss_ota:depends("protocol", "shadowsocks") -protocol = s:option(ListValue, "protocol", translate("Protocol")) -for a, t in ipairs(ssr_protocol_list) do protocol:value(t) end -protocol:depends("type", "SSR") +ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol")) +for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end +ssr_protocol:depends("type", "SSR") -protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) -protocol_param:depends("type", "SSR") +ssr_protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) +ssr_protocol_param:depends("type", "SSR") obfs = s:option(ListValue, "obfs", translate("Obfs")) for a, t in ipairs(ssr_obfs_list) do obfs:value(t) end @@ -152,6 +167,7 @@ tcp_fast_open:value("false") tcp_fast_open:value("true") tcp_fast_open:depends("type", "SSR") tcp_fast_open:depends("type", "Trojan") +tcp_fast_open:depends("type", "Trojan-Go") udp_forward = s:option(Flag, "udp_forward", translate("UDP Forward")) udp_forward.default = "1" @@ -163,107 +179,169 @@ for i = 1, 3 do local uuid = luci.sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)") vmess_id:value(uuid) end -vmess_id:depends({ type = "V2ray", v2ray_protocol = "vmess" }) +vmess_id:depends({ type = "V2ray", protocol = "vmess" }) -vmess_alterId = s:option(Value, "vmess_alterId", translate("Alter ID")) -vmess_alterId.default = 16 -vmess_alterId:depends({ type = "V2ray", v2ray_protocol = "vmess" }) +alter_id = s:option(Value, "alter_id", translate("Alter ID")) +alter_id.default = 16 +alter_id:depends({ type = "V2ray", protocol = "vmess" }) vmess_level = s:option(Value, "vmess_level", translate("User Level")) vmess_level.default = 1 -vmess_level:depends({ type = "V2ray", v2ray_protocol = "vmess" }) -vmess_level:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" }) +vmess_level:depends({ type = "V2ray", protocol = "vmess" }) +vmess_level:depends({ type = "V2ray", protocol = "shadowsocks" }) -v2ray_transport = s:option(ListValue, "v2ray_transport", translate("Transport")) -v2ray_transport:value("tcp", "TCP") -v2ray_transport:value("mkcp", "mKCP") -v2ray_transport:value("ws", "WebSocket") -v2ray_transport:value("h2", "HTTP/2") -v2ray_transport:value("ds", "DomainSocket") -v2ray_transport:value("quic", "QUIC") -v2ray_transport:depends("v2ray_protocol", "vmess") +stream_security = s:option(ListValue, "stream_security", + translate("Transport Layer Encryption"), + translate( + 'Whether or not transport layer encryption is enabled, the supported options are "none" for unencrypted (default) and "TLS" for using TLS.')) +stream_security:value("none", "none") +stream_security:value("tls", "tls") +stream_security.default = "tls" +stream_security:depends({ type = "V2ray", protocol = "vmess", transport = "ws" }) +stream_security:depends({ type = "V2ray", protocol = "vmess", transport = "h2" }) +stream_security:depends("protocol", "shadowsocks") +stream_security:depends("type", "Trojan-Go") + +-- [[ TLS部分 ]] -- + +tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) +tls_sessionTicket.default = "0" +tls_sessionTicket:depends("stream_security", "tls") + +tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") +tls_certificateFile:depends("stream_security", "tls") + +tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") +tls_keyFile:depends("stream_security", "tls") + +transport = s:option(ListValue, "transport", translate("Transport")) +transport:value("tcp", "TCP") +transport:value("mkcp", "mKCP") +transport:value("ws", "WebSocket") +transport:value("h2", "HTTP/2") +transport:value("ds", "DomainSocket") +transport:value("quic", "QUIC") +transport:depends("protocol", "vmess") + +trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport")) +trojan_transport:value("original", "Original") +trojan_transport:value("ws", "WebSocket") +trojan_transport:value("h2", "HTTP/2") +trojan_transport:value("h2+ws", "HTTP/2 & WebSocket") +trojan_transport.default = "ws" +trojan_transport:depends("type", "Trojan-Go") + +trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type")) +trojan_plugin:value("plaintext", "Plain Text") +trojan_plugin:value("shadowsocks", "ShadowSocks") +trojan_plugin:value("other", "Other") +trojan_plugin.default = "plaintext" +trojan_plugin:depends({ stream_security = "none", trojan_transport = "original" }) + +trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary")) +trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin" +trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_cmd:depends({ plugin_type = "other" }) + +trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option")) +trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com" +trojan_plugin_op:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_op:depends({ plugin_type = "other" }) + +trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args")) +trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]" +trojan_plugin_arg:depends({ plugin_type = "shadowsocks" }) +trojan_plugin_arg:depends({ plugin_type = "other" }) -- [[ TCP部分 ]]-- -- TCP伪装 -v2ray_tcp_guise = s:option(ListValue, "v2ray_tcp_guise", translate("Camouflage Type")) -v2ray_tcp_guise:value("none", "none") -v2ray_tcp_guise:value("http", "http") -v2ray_tcp_guise:depends("v2ray_transport", "tcp") +tcp_guise = s:option(ListValue, "tcp_guise", translate("Camouflage Type")) +tcp_guise:value("none", "none") +tcp_guise:value("http", "http") +tcp_guise:depends("transport", "tcp") -- HTTP域名 -v2ray_tcp_guise_http_host = s:option(DynamicList, "v2ray_tcp_guise_http_host", translate("HTTP Host")) -v2ray_tcp_guise_http_host:depends("v2ray_tcp_guise", "http") +tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) +tcp_guise_http_host:depends("tcp_guise", "http") -- HTTP路径 -v2ray_tcp_guise_http_path = s:option(DynamicList, "v2ray_tcp_guise_http_path", translate("HTTP Path")) -v2ray_tcp_guise_http_path:depends("v2ray_tcp_guise", "http") +tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) +tcp_guise_http_path:depends("tcp_guise", "http") -- [[ mKCP部分 ]]-- -v2ray_mkcp_guise = s:option(ListValue, "v2ray_mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) -for a, t in ipairs(v2ray_header_type_list) do v2ray_mkcp_guise:value(t) end -v2ray_mkcp_guise:depends("v2ray_transport", "mkcp") +mkcp_guise = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) +for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end +mkcp_guise:depends("transport", "mkcp") -v2ray_mkcp_mtu = s:option(Value, "v2ray_mkcp_mtu", translate("KCP MTU")) -v2ray_mkcp_mtu:depends("v2ray_transport", "mkcp") +mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU")) +mkcp_mtu:depends("transport", "mkcp") -v2ray_mkcp_tti = s:option(Value, "v2ray_mkcp_tti", translate("KCP TTI")) -v2ray_mkcp_tti:depends("v2ray_transport", "mkcp") +mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI")) +mkcp_tti:depends("transport", "mkcp") -v2ray_mkcp_uplinkCapacity = s:option(Value, "v2ray_mkcp_uplinkCapacity", translate("KCP uplinkCapacity")) -v2ray_mkcp_uplinkCapacity:depends("v2ray_transport", "mkcp") +mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity", translate("KCP uplinkCapacity")) +mkcp_uplinkCapacity:depends("transport", "mkcp") -v2ray_mkcp_downlinkCapacity = s:option(Value, "v2ray_mkcp_downlinkCapacity", translate("KCP downlinkCapacity")) -v2ray_mkcp_downlinkCapacity:depends("v2ray_transport", "mkcp") +mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity", translate("KCP downlinkCapacity")) +mkcp_downlinkCapacity:depends("transport", "mkcp") -v2ray_mkcp_congestion = s:option(Flag, "v2ray_mkcp_congestion", translate("KCP Congestion")) -v2ray_mkcp_congestion:depends("v2ray_transport", "mkcp") +mkcp_congestion = s:option(Flag, "mkcp_congestion", translate("KCP Congestion")) +mkcp_congestion:depends("transport", "mkcp") -v2ray_mkcp_readBufferSize = s:option(Value, "v2ray_mkcp_readBufferSize", translate("KCP readBufferSize")) -v2ray_mkcp_readBufferSize:depends("v2ray_transport", "mkcp") +mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize", translate("KCP readBufferSize")) +mkcp_readBufferSize:depends("transport", "mkcp") -v2ray_mkcp_writeBufferSize = s:option(Value, "v2ray_mkcp_writeBufferSize", translate("KCP writeBufferSize")) -v2ray_mkcp_writeBufferSize:depends("v2ray_transport", "mkcp") +mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize", translate("KCP writeBufferSize")) +mkcp_writeBufferSize:depends("transport", "mkcp") -- [[ WebSocket部分 ]]-- -v2ray_ws_host = s:option(Value, "v2ray_ws_host", translate("WebSocket Host")) -v2ray_ws_host:depends("v2ray_transport", "ws") -v2ray_ws_host:depends("v2ray_ss_transport", "ws") +ws_host = s:option(Value, "ws_host", translate("WebSocket Host")) +ws_host:depends("transport", "ws") +ws_host:depends("ss_transport", "ws") +ws_host:depends("trojan_transport", "h2+ws") +ws_host:depends("trojan_transport", "ws") -v2ray_ws_path = s:option(Value, "v2ray_ws_path", translate("WebSocket Path")) -v2ray_ws_path:depends("v2ray_transport", "ws") -v2ray_ws_path:depends("v2ray_ss_transport", "ws") +ws_path = s:option(Value, "ws_path", translate("WebSocket Path")) +ws_path:depends("transport", "ws") +ws_path:depends("ss_transport", "ws") +ws_path:depends("trojan_transport", "h2+ws") +ws_path:depends("trojan_transport", "ws") -- [[ HTTP/2部分 ]]-- -v2ray_h2_host = s:option(DynamicList, "v2ray_h2_host", translate("HTTP/2 Host")) -v2ray_h2_host:depends("v2ray_transport", "h2") -v2ray_h2_host:depends("v2ray_ss_transport", "h2") +h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host")) +h2_host:depends("transport", "h2") +h2_host:depends("ss_transport", "h2") +h2_host:depends("trojan_transport", "h2+ws") +h2_host:depends("trojan_transport", "h2") -v2ray_h2_path = s:option(Value, "v2ray_h2_path", translate("HTTP/2 Path")) -v2ray_h2_path:depends("v2ray_transport", "h2") -v2ray_h2_path:depends("v2ray_ss_transport", "h2") +h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path")) +h2_path:depends("transport", "h2") +h2_path:depends("ss_transport", "h2") +h2_path:depends("trojan_transport", "h2+ws") +h2_path:depends("trojan_transport", "h2") -- [[ DomainSocket部分 ]]-- -v2ray_ds_path = s:option(Value, "v2ray_ds_path", "Path", translate("A legal file path. This file must not exist before running V2Ray.")) -v2ray_ds_path:depends("v2ray_transport", "ds") +ds_path = s:option(Value, "ds_path", "Path", translate("A legal file path. This file must not exist before running V2Ray.")) +ds_path:depends("transport", "ds") -- [[ QUIC部分 ]]-- -v2ray_quic_security = s:option(ListValue, "v2ray_quic_security", translate("Encrypt Method")) -v2ray_quic_security:value("none") -v2ray_quic_security:value("aes-128-gcm") -v2ray_quic_security:value("chacha20-poly1305") -v2ray_quic_security:depends("v2ray_transport", "quic") +quic_security = s:option(ListValue, "quic_security", translate("Encrypt Method")) +quic_security:value("none") +quic_security:value("aes-128-gcm") +quic_security:value("chacha20-poly1305") +quic_security:depends("transport", "quic") -v2ray_quic_key = s:option(Value, "v2ray_quic_key", translate("Encrypt Method") .. translate("Key")) -v2ray_quic_key:depends("v2ray_transport", "quic") +quic_key = s:option(Value, "quic_key", translate("Encrypt Method") .. translate("Key")) +quic_key:depends("transport", "quic") -v2ray_quic_guise = s:option(ListValue, "v2ray_quic_guise", translate("Camouflage Type")) -for a, t in ipairs(v2ray_header_type_list) do v2ray_quic_guise:value(t) end -v2ray_quic_guise:depends("v2ray_transport", "quic") +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") remote_enable = s:option(Flag, "remote_enable", translate("Enable Remote"),translate("You can forward to Nginx/Caddy/V2ray WebSocket and more.")) remote_enable.default = "1" @@ -279,20 +357,28 @@ remote_port.datatype = "port" remote_port.default = "80" remote_port:depends("remote_enable", 1) --- [[ TLS部分 ]] -- -tls_enable = s:option(Flag, "tls_enable", "TLS/SSL") -tls_enable:depends({ type = "V2ray", v2ray_protocol = "vmess", v2ray_transport = "ws" }) -tls_enable:depends({ type = "V2ray", v2ray_protocol = "vmess", v2ray_transport = "h2" }) -tls_enable.default = "0" -tls_enable.rmempty = false +ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) +ss_aead:depends("type", "Trojan-Go") +ss_aead.default = "0" -tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") -tls_certificateFile:depends("tls_enable", 1) -tls_certificateFile:depends("type", "Trojan") +ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method")) +for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v:upper()) end +ss_aead_method.default = "aead_aes_128_gcm" +ss_aead_method.rmempty = false +ss_aead_method:depends("ss_aead", "1") -tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") -tls_keyFile:depends("tls_enable", 1) -tls_keyFile:depends("type", "Trojan") +ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password")) +ss_aead_pwd.password = true +ss_aead_pwd.rmempty = false +ss_aead_pwd:depends("ss_aead", "1") + +-- [[ Mux ]]-- +mux = s:option(Flag, "mux", translate("Mux")) + +mux_concurrency = s:option(Value, "mux_concurrency", + translate("Mux Concurrency")) +mux_concurrency.default = 8 +mux_concurrency:depends("mux", "1") local nodes_table = {} uci:foreach("passwall", "nodes", function(e) diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm index 79104d96f8..7dadda6b64 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm @@ -26,80 +26,80 @@ Licensed under the BSD License. https://github.com/pure-css/pure/blob/master/LICENSE.md */ .pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%} - .block{ - margin: 0.5rem; - padding: 0; - font-weight: normal; - font-style: normal; - line-height: 1; - font-family: inherit; - min-width: inherit; - overflow-x: auto; - overflow-y: hidden; - border: 1px solid rgba(0,0,0,.05); - border-radius: .375rem; - background-color: #fff; - box-shadow: 0 0 2rem 0 rgba(136,152,170,.15); - } - .img-con{ - margin: 1rem; + .block{ + margin: 0.5rem; + padding: 0; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + border: 1px solid rgba(0,0,0,.05); + border-radius: .375rem; + background-color: #fff; + box-shadow: 0 0 2rem 0 rgba(136,152,170,.15); + } + .img-con{ + margin: 1rem; - } - .green{ + } + .green{ font-size:.9rem; - color: #2dce89; - } - .red{ + color: #2dce89; + } + .red{ font-size:.9rem; - color: #fb6340; - } + color: #fb6340; + } .yellow{ font-size:.9rem; - color: #fb9a05; - } - .block img{ - width: 48px; - height: auto; + color: #fb9a05; + } + .block img{ + width: 48px; + height: auto; float:right; - } - .pure-u-5-8{ - display:flex; - align-items:center; - } + } + .pure-u-5-8{ + display:flex; + align-items:center; + } - .block h4{ - font-size: .8125rem; - font-weight: 600; - margin: 1rem; + .block h4{ + font-size: .8125rem; + font-weight: 600; + margin: 1rem; color:#8898aa!important; - line-height: 1.8em; + line-height: 1.8em; min-height: 48px; - } + } .check { cursor: pointer; } - @media screen and (max-width: 720px) { + @media screen and (max-width: 720px) { .block{ margin: 0.2rem; } - .pure-u-1-4{ - width: 50%; - } + .pure-u-1-4{ + width: 50%; + } .pure-u-1-2{ - width: 100%; - } - } + width: 100%; + } + } @media screen and (max-width: 480px) { - .img-con{ + .img-con{ margin: 1.5rem 0.5rem; - } + } .block img{ - width: 36px; - } - } + width: 36px; + } + } @@ -107,155 +107,144 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md <%:Running Status%> -
-
-
-
-

TCP
<%:NOT RUNNING%>

-
-
-
- -
-
-
-
-
-
-
-
-

UDP
<%:NOT RUNNING%>

-
-
-
- -
-
-
-
-
-
-
-

DNS
<%:NOT RUNNING%>

-
-
-
- -
-
-
-
+
-
-
-

<%:Load Balancing%>
<%:NOT RUNNING%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

TCP
<%:NOT RUNNING%>

+
+
+
-
-
-

Kcptun
<%:NOT RUNNING%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

UDP
<%:NOT RUNNING%>

+
+
+
+
+
+
+
+ +
+
+
+

DNS
<%:NOT RUNNING%>

+
+
+
+
+
+
+
+ +
+
+
+

<%:Load Balancing%>
<%:NOT RUNNING%>

+
+
+
+
+
+
+
+ +
+
+
+

Kcptun
<%:NOT RUNNING%>

+
+
+
-
-
-

<%:Baidu Connection%>
<%:Touch Check%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

<%:Baidu Connection%>
<%:Touch Check%>

+
+
+
-
-
-

<%:Google Connection%>
<%:Touch Check%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

<%:Google Connection%>
<%:Touch Check%>

+
+
+
-
-
-

<%:GitHub Connection%>
<%:Touch Check%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

<%:GitHub Connection%>
<%:Touch Check%>

+
+
+
<% if tonumber(status_show_check_port) == 1 then %>
-
-
-

<%:Node Check%>
<%:Touch Check%>

- -
-
-
- +
+
+
+
-
-
-
+
+
+

<%:Node Check%>
<%:Touch Check%>

+ +
+
+
<% end %> <% if tonumber(status_show_ip111) == 1 then %>
-
-
-

IP111.cn
<%:Touch Check%>

-
-
-
- +
+
+
+
-
-
-
+
+
+

IP111.cn
<%:Touch Check%>

+
+
+
<% end %> -
- + diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm index cb7802a1e6..61f169cb19 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm @@ -209,7 +209,8 @@ local status_show_ip111 = api.uci_get_type("global_other", "status_show_ip111", text += ' X'; } } - kcptun_tcp_node_status.innerHTML = text; + if(kcptun_tcp_node_status) + kcptun_tcp_node_status.innerHTML = text; } } diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm index 2149a06a0a..813749dc6e 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm @@ -1,11 +1,7 @@ -<% -local dsp = require "luci.dispatcher" --%> -

+ +
+ +
+
+ 【 <%=trojan_go_version%> 】 + + +
+
+
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/v2ray_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/v2ray_version.htm index e48cea991b..56baa70555 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/v2ray_version.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/v2ray_version.htm @@ -1,8 +1,5 @@ <% -local api = require "luci.model.cbi.passwall.api.api" -local dsp = require "luci.dispatcher" - -local v2ray_version = api.get_v2ray_version() +local v2ray_version = require "luci.model.cbi.passwall.api.api".get_v2ray_version() -%>