update 2026-01-19 14:27:35

This commit is contained in:
kenzok8
2026-01-19 14:27:35 +08:00
parent 1921f97204
commit a2898dfd72
12 changed files with 559 additions and 51 deletions

View File

@@ -1,7 +1,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
-include $(dir $(lastword $(MAKEFILE_LIST)))../version.mk
PKG_NAME:=easytier PKG_NAME:=easytier
PKG_VERSION:=2.5.0 PKG_VERSION:=$(or $(EASYTIER_VERSION),2.5.0)
ifeq ($(ARCH),mipsel) ifeq ($(ARCH),mipsel)
APP_ARCH:=mipsel APP_ARCH:=mipsel

View File

@@ -1,7 +1,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
-include $(dir $(lastword $(MAKEFILE_LIST)))../version.mk
PKG_NAME:=easytier PKG_NAME:=easytier
PKG_VERSION:=2.5.0 PKG_VERSION:=$(or $(EASYTIER_VERSION),2.5.0)
ifeq ($(ARCH),mipsel) ifeq ($(ARCH),mipsel)
APP_ARCH:=mipsel APP_ARCH:=mipsel

View File

@@ -5,8 +5,9 @@
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
-include $(dir $(lastword $(MAKEFILE_LIST)))../version.mk
PKG_VERSION:=2.5.0 PKG_VERSION:=$(or $(EASYTIER_VERSION),2.5.0)
PKG_RELEASE:=2 PKG_RELEASE:=2
LUCI_TITLE:=LuCI support for EasyTier LUCI_TITLE:=LuCI support for EasyTier
@@ -16,6 +17,7 @@ LUCI_PKGARCH:=all
PKG_NAME:=luci-app-easytier PKG_NAME:=luci-app-easytier
define Package/$(PKG_NAME)/conffiles define Package/$(PKG_NAME)/conffiles
/etc/config/easytier
/etc/easytier/ /etc/easytier/
endef endef

View File

@@ -1,6 +1,46 @@
module("luci.controller.easytier", package.seeall) module("luci.controller.easytier", package.seeall)
-- 安全执行命令并返回结果
local function safe_exec(cmd)
local handle = io.popen(cmd)
if not handle then return "" end
local result = handle:read("*all") or ""
handle:close()
return result:gsub("[\r\n]+$", "")
end
-- 安全读取文件内容
local function safe_read_file(path)
local file = io.open(path, "r")
if not file then return nil end
local content = file:read("*all")
file:close()
return content
end
-- 计算运行时长
local function calc_uptime(start_time_file)
local content = safe_read_file(start_time_file)
if not content or content == "" then return "" end
local start_time = tonumber(content:match("%d+"))
if not start_time then return "" end
local now = os.time()
local elapsed = now - start_time
local days = math.floor(elapsed / 86400)
local hours = math.floor((elapsed % 86400) / 3600)
local mins = math.floor((elapsed % 3600) / 60)
local secs = elapsed % 60
local result = ""
if days > 0 then result = days .. "" end
result = result .. string.format("%02d小时%02d分%02d秒", hours, mins, secs)
return result
end
function index() function index()
if not nixio.fs.access("/etc/config/easytier") then if not nixio.fs.access("/etc/config/easytier") then
return return
@@ -27,62 +67,55 @@ function act_status()
e.wrunning = luci.sys.call("pgrep easytier-web >/dev/null") == 0 e.wrunning = luci.sys.call("pgrep easytier-web >/dev/null") == 0
e.port = (port or 0) e.port = (port or 0)
local tagfile = io.open("/tmp/easytier_time", "r") -- 使用 Lua 原生计算运行时长
if tagfile then e.etsta = calc_uptime("/tmp/easytier_time")
local tagcontent = tagfile:read("*all") e.etwebsta = calc_uptime("/tmp/easytierweb_time")
tagfile:close()
if tagcontent and tagcontent ~= "" then
os.execute("start_time=$(cat /tmp/easytier_time) && time=$(($(date +%s)-start_time)) && day=$((time/86400)) && [ $day -eq 0 ] && day='' || day=${day}天 && time=$(date -u -d @${time} +'%H小时%M分%S秒') && echo $day $time > /tmp/command_easytier 2>&1")
local command_output_file = io.open("/tmp/command_easytier", "r")
if command_output_file then
e.etsta = command_output_file:read("*all")
command_output_file:close()
end
end
end
local command2 = io.popen('test ! -z "`pidof easytier-core`" && (top -b -n1 | grep -E "$(pidof easytier-core)" 2>/dev/null | grep -v grep | awk \'{for (i=1;i<=NF;i++) {if ($i ~ /easytier-core/) break; else cpu=i}} END {print $cpu}\')') -- 获取 CPU 和内存使用率(使用原始命令)
local command2 = io.popen('test ! -z "`pidof easytier-core`" && (top -b -n1 | grep -E "$(pidof easytier-core)" 2>/dev/null | grep -v grep | awk \'{for (i=1;i<=NF;i++) {if ($i ~ /easytier-core/) break; else cpu=i}} END {print $cpu}\')')
e.etcpu = command2:read("*all") e.etcpu = command2:read("*all")
command2:close() command2:close()
local command3 = io.popen("test ! -z `pidof easytier-core` && (cat /proc/$(pidof easytier-core | awk '{print $NF}')/status | grep -w VmRSS | awk '{printf \"%.2f MB\", $2/1024}')") local command3 = io.popen("test ! -z `pidof easytier-core` && (cat /proc/$(pidof easytier-core | awk '{print $NF}')/status | grep -w VmRSS | awk '{printf \"%.2f MB\", $2/1024}')")
e.etram = command3:read("*all") e.etram = command3:read("*all")
command3:close() command3:close()
local wtagfile = io.open("/tmp/easytierweb_time", "r")
if wtagfile then
local wtagcontent = wtagfile:read("*all")
wtagfile:close()
if wtagcontent and wtagcontent ~= "" then
os.execute("start_time=$(cat /tmp/easytierweb_time) && time=$(($(date +%s)-start_time)) && day=$((time/86400)) && [ $day -eq 0 ] && day='' || day=${day}天 && time=$(date -u -d @${time} +'%H小时%M分%S秒') && echo $day $time > /tmp/command_easytierweb 2>&1")
local wcommand_output_file = io.open("/tmp/command_easytierweb", "r")
if wcommand_output_file then
e.etwebsta = wcommand_output_file:read("*all")
wcommand_output_file:close()
end
end
end
local command4 = io.popen('test ! -z "`pidof easytier-web`" && (top -b -n1 | grep -E "$(pidof easytier-web)" 2>/dev/null | grep -v grep | awk \'{for (i=1;i<=NF;i++) {if ($i ~ /easytier-web/) break; else cpu=i}} END {print $cpu}\')') local command4 = io.popen('test ! -z "`pidof easytier-web`" && (top -b -n1 | grep -E "$(pidof easytier-web)" 2>/dev/null | grep -v grep | awk \'{for (i=1;i<=NF;i++) {if ($i ~ /easytier-web/) break; else cpu=i}} END {print $cpu}\')')
e.etwebcpu = command4:read("*all") e.etwebcpu = command4:read("*all")
command4:close() command4:close()
local command5 = io.popen("test ! -z `pidof easytier-web` && (cat /proc/$(pidof easytier-web | awk '{print $NF}')/status | grep -w VmRSS | awk '{printf \"%.2f MB\", $2/1024}')") local command5 = io.popen("test ! -z `pidof easytier-web` && (cat /proc/$(pidof easytier-web | awk '{print $NF}')/status | grep -w VmRSS | awk '{printf \"%.2f MB\", $2/1024}')")
e.etwebram = command5:read("*all") e.etwebram = command5:read("*all")
command5:close() command5:close()
local command8 = io.popen("([ -s /tmp/easytiernew.tag ] && cat /tmp/easytiernew.tag ) || ( curl -L -k -s --connect-timeout 3 --user-agent 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36' https://api.github.com/repos/EasyTier/EasyTier/releases/latest | grep tag_name | sed 's/[^0-9.]*//g' >/tmp/easytiernew.tag && cat /tmp/easytiernew.tag )") -- 获取版本信息
e.etnewtag = command8:read("*all") local cached_newtag = safe_read_file("/tmp/easytiernew.tag")
command8:close() if cached_newtag and cached_newtag ~= "" then
e.etnewtag = cached_newtag:gsub("[\r\n]+", "")
else
e.etnewtag = safe_exec("curl -L -k -s --connect-timeout 3 --user-agent 'Mozilla/5.0' https://api.github.com/repos/EasyTier/EasyTier/releases/latest | grep tag_name | sed 's/[^0-9.]*//g'")
if e.etnewtag ~= "" then
local f = io.open("/tmp/easytiernew.tag", "w")
if f then f:write(e.etnewtag); f:close() end
end
end
local command9 = io.popen("([ -s /tmp/easytier.tag ] && cat /tmp/easytier.tag ) || ( echo `$(uci -q get easytier.@easytier[0].easytierbin) -V | sed 's/^[^0-9]*//'` > /tmp/easytier.tag && cat /tmp/easytier.tag && [ ! -s /tmp/easytier.tag ] && echo '' >> /tmp/easytier.tag && cat /tmp/easytier.tag )") local cached_tag = safe_read_file("/tmp/easytier.tag")
e.ettag = command9:read("*all") if cached_tag and cached_tag ~= "" then
command9:close() e.ettag = cached_tag:gsub("[\r\n]+", "")
else
local easytierbin = uci:get_first("easytier", "easytier", "easytierbin") or "/usr/bin/easytier-core"
e.ettag = safe_exec(easytierbin .. " -V | sed 's/^[^0-9]*//'")
if e.ettag == "" then e.ettag = "?" end
local f = io.open("/tmp/easytier.tag", "w")
if f then f:write(e.ettag); f:close() end
end
luci.http.prepare_content("application/json") luci.http.prepare_content("application/json")
luci.http.write_json(e) luci.http.write_json(e)
end end
function get_log() function get_log()
local log = "" local log = ""
local files = {"/tmp/easytier.log"} local files = {"/tmp/easytier.log"}

View File

@@ -74,12 +74,20 @@ network_name = s:taboption("general", Value, "network_name", translate("Network
translate("The network name used to identify this VPN network (--network-name parameter)")) translate("The network name used to identify this VPN network (--network-name parameter)"))
network_name.password = true network_name.password = true
network_name.placeholder = "easytier-name" network_name.placeholder = "easytier-name"
network_name.maxlength = 64
network_name.validate = function(self, value)
if value and value ~= "" and value:match("[^%w%-_]") then
return nil, translate("Only alphanumeric characters, hyphens and underscores allowed")
end
return value
end
network_name:depends("etcmd", "etcmd") network_name:depends("etcmd", "etcmd")
network_secret = s:taboption("general", Value, "network_secret", translate("Network Secret"), network_secret = s:taboption("general", Value, "network_secret", translate("Network Secret"),
translate("Network secret used to verify whether this node belongs to the VPN network (--network-secret parameter)")) translate("Network secret used to verify whether this node belongs to the VPN network (--network-secret parameter)"))
network_secret.password = true network_secret.password = true
network_secret.placeholder = "easytier-password" network_secret.placeholder = "easytier-password"
network_secret.maxlength = 128
network_secret:depends("etcmd", "etcmd") network_secret:depends("etcmd", "etcmd")
ip_dhcp = s:taboption("general", Flag, "ip_dhcp", translate("Enable DHCP"), ip_dhcp = s:taboption("general", Flag, "ip_dhcp", translate("Enable DHCP"),
@@ -192,14 +200,14 @@ local model = nixio.fs.readfile("/proc/device-tree/model") or ""
local hostname = nixio.fs.readfile("/proc/sys/kernel/hostname") or "" local hostname = nixio.fs.readfile("/proc/sys/kernel/hostname") or ""
model = model:gsub("\n", "") model = model:gsub("\n", "")
hostname = hostname:gsub("\n", "") hostname = hostname:gsub("\n", "")
local device_name = (model ~= "" and model) or (hostname ~= "" and hostname) or "OpenWrt" local device_name_default = (model ~= "" and model) or (hostname ~= "" and hostname) or "OpenWrt"
device_name = device_name:gsub(" ", "_") device_name_default = device_name_default:gsub(" ", "_")
desvice_name = s:taboption("general", Value, "desvice_name", translate("Hostname"), hostname_opt = s:taboption("general", Value, "desvice_name", translate("Hostname"),
translate("The hostname used to identify this device (--hostname parameter)")) translate("The hostname used to identify this device (--hostname parameter)"))
desvice_name.placeholder = device_name hostname_opt.placeholder = device_name_default
desvice_name.default = device_name hostname_opt.default = device_name_default
desvice_name:depends("etcmd", "etcmd") hostname_opt:depends("etcmd", "etcmd")
desvice_name:depends("etcmd", "web") hostname_opt:depends("etcmd", "web")
uuid = s:taboption("general", Value, "uuid", translate("UUID"), uuid = s:taboption("general", Value, "uuid", translate("UUID"),
translate("Unique identifier used to recognize this device when connecting to the web console, for issuing configuration files")) translate("Unique identifier used to recognize this device when connecting to the web console, for issuing configuration files"))
@@ -496,6 +504,16 @@ webbin = s:taboption("upload", Value, "webbin", translate("easytier-web Binary P
webbin.placeholder = "/usr/bin/easytier-web" webbin.placeholder = "/usr/bin/easytier-web"
webbin.default = "/usr/bin/easytier-web" webbin.default = "/usr/bin/easytier-web"
github_proxys = s:taboption("upload", Value, "github_proxys", translate("GitHub Proxy URLs"),
translate("Space-separated list of GitHub proxy URLs for downloading binaries. "
.. "Leave empty to use default proxies."))
github_proxys.placeholder = "https://ghproxy.net/ https://gh-proxy.com/"
fallback_version = s:taboption("upload", Value, "fallback_version", translate("Fallback Version"),
translate("Fallback version to use when unable to fetch the latest version from GitHub."))
fallback_version.placeholder = "v2.5.0"
fallback_version.default = "v2.5.0"
local upload = s:taboption("upload", FileUpload, "upload_file") local upload = s:taboption("upload", FileUpload, "upload_file")
upload.optional = true upload.optional = true
upload.default = "" upload.default = ""

View File

@@ -1,6 +1,4 @@
config easytier config easytier
option enabled '0' option enabled '0'
option easytierbin '/usr/bin/easytier-core' option easytierbin '/usr/bin/easytier-core'

View File

@@ -4,6 +4,12 @@
START=99 START=99
USE_PROCD=1 USE_PROCD=1
# 引入模块化脚本
EASYTIER_LIB_DIR="/usr/share/easytier"
[ -f "${EASYTIER_LIB_DIR}/utils.sh" ] && . "${EASYTIER_LIB_DIR}/utils.sh"
[ -f "${EASYTIER_LIB_DIR}/firewall.sh" ] && . "${EASYTIER_LIB_DIR}/firewall.sh"
[ -f "${EASYTIER_LIB_DIR}/download.sh" ] && . "${EASYTIER_LIB_DIR}/download.sh"
check() { check() {
if [ ! -z "$checkip" ]; then if [ ! -z "$checkip" ]; then
echo ' ' >/tmp/easytier_check echo ' ' >/tmp/easytier_check
@@ -49,6 +55,9 @@ EOF
fi fi
} }
# get_tz 函数已移至 utils.sh保留兼容性包装
# 如果 utils.sh 未加载,使用内联定义
if ! type get_tz >/dev/null 2>&1; then
get_tz() { get_tz() {
SET_TZ="" SET_TZ=""
[ -e "/etc/localtime" ] && return [ -e "/etc/localtime" ] && return
@@ -60,6 +69,7 @@ get_tz() {
[ -z "$tz" ] && return [ -z "$tz" ] && return
SET_TZ=$tz SET_TZ=$tz
} }
fi
check_bin() { check_bin() {
curltest=`which curl` curltest=`which curl`
@@ -78,7 +88,11 @@ check_bin() {
tag="$( curl -k --connect-timeout 3 --user-agent "$user_agent" https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4 )" tag="$( curl -k --connect-timeout 3 --user-agent "$user_agent" https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4 )"
[ -z "$tag" ] && tag="$( curl -Lk --connect-timeout 3 --user-agent "$user_agent" -s https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4 )" [ -z "$tag" ] && tag="$( curl -Lk --connect-timeout 3 --user-agent "$user_agent" -s https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4 )"
fi fi
[ -z "$tag"] && tag=v2.5.0 # 如果获取失败,从 UCI 配置或使用默认版本
if [ -z "$tag" ]; then
tag=$(uci -q get easytier.@easytier[0].fallback_version)
[ -z "$tag" ] && tag="v2.5.0"
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') easytier : 开始在线下载${tag}版本,${proxy}https://github.com/EasyTier/EasyTier/releases/download/${tag}/easytier-linux-${cpucore}-${tag}.zip下载较慢耐心等候" >>/tmp/easytier.log echo "$(date '+%Y-%m-%d %H:%M:%S') easytier : 开始在线下载${tag}版本,${proxy}https://github.com/EasyTier/EasyTier/releases/download/${tag}/easytier-linux-${cpucore}-${tag}.zip下载较慢耐心等候" >>/tmp/easytier.log
echo "$(date '+%Y-%m-%d %H:%M:%S') easytier : 开始在线下载${tag}版本,${proxy}https://github.com/EasyTier/EasyTier/releases/download/${tag}/easytier-linux-${cpucore}-${tag}.zip下载较慢耐心等候" >>/tmp/easytierweb.log echo "$(date '+%Y-%m-%d %H:%M:%S') easytier : 开始在线下载${tag}版本,${proxy}https://github.com/EasyTier/EasyTier/releases/download/${tag}/easytier-linux-${cpucore}-${tag}.zip下载较慢耐心等候" >>/tmp/easytierweb.log
mkdir -p "$path" mkdir -p "$path"

View File

@@ -6,6 +6,8 @@ uci -q batch <<-EOF >/dev/null
set ucitrack.@easytier[-1].init=easytier set ucitrack.@easytier[-1].init=easytier
commit ucitrack commit ucitrack
EOF EOF
chmod +x /etc/init.d/easytier chmod +x /etc/init.d/easytier
/etc/init.d/easytier enable
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
exit 0 exit 0

View File

@@ -0,0 +1,151 @@
#!/bin/sh
# EasyTier Download Management
# Handles binary downloads from GitHub with proxy support
# 引入工具函数
. /usr/share/easytier/utils.sh 2>/dev/null || true
# 默认 GitHub 加速代理列表
DEFAULT_PROXYS="
https://ghproxy.net/
https://gh-proxy.com/
https://cdn.gh-proxy.com/
https://ghfast.top/
"
# 获取代理列表
# 优先从 UCI 配置读取,否则使用默认值
get_proxy_list() {
local proxys=$(uci -q get easytier.@easytier[0].github_proxys)
[ -z "$proxys" ] && proxys="$DEFAULT_PROXYS"
echo "$proxys"
}
# 获取最新版本号
get_latest_version() {
local user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
local tag=""
local curltest=$(which curl)
if [ -z "$curltest" ] || [ ! -s "$(which curl)" ]; then
tag=$(wget --no-check-certificate -T 5 -t 3 --user-agent "$user_agent" --max-redirect=0 --output-document=- \
https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4)
[ -z "$tag" ] && tag=$(wget --no-check-certificate -T 5 -t 3 --user-agent "$user_agent" --quiet --output-document=- \
https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4)
else
tag=$(curl -k --connect-timeout 3 --user-agent "$user_agent" \
https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4)
[ -z "$tag" ] && tag=$(curl -Lk --connect-timeout 3 --user-agent "$user_agent" -s \
https://api.github.com/repos/EasyTier/EasyTier/releases/latest 2>&1 | grep 'tag_name' | cut -d\" -f4)
fi
# 如果获取失败,从 UCI 配置或使用默认版本
if [ -z "$tag" ]; then
tag=$(uci -q get easytier.@easytier[0].fallback_version)
[ -z "$tag" ] && tag="v2.5.0"
fi
echo "$tag"
}
# 下载二进制文件
# 参数: $1=版本号 $2=CPU架构 $3=目标路径
download_binary() {
local tag="$1"
local cpucore="$2"
local path="$3"
local proxys=$(get_proxy_list)
local download_url="https://github.com/EasyTier/EasyTier/releases/download/${tag}/easytier-linux-${cpucore}-${tag}.zip"
mkdir -p "$path"
for proxy in $proxys; do
log_message "INFO" "easytier" "尝试使用代理 ${proxy} 下载" "/tmp/easytier.log"
if curl -L -k -o /tmp/easytier.zip --connect-timeout 10 --retry 3 "${proxy}${download_url}" || \
wget --no-check-certificate --timeout=10 --tries=3 -O /tmp/easytier.zip "${proxy}${download_url}"; then
unzip -j -q -o /tmp/easytier.zip -d /tmp
chmod +x /tmp/easytier-core /tmp/easytier-cli /tmp/easytier-web /tmp/easytier-web-embed 2>/dev/null || true
rm -rf /tmp/easytier.zip
log_message "INFO" "easytier" "下载成功" "/tmp/easytier.log"
return 0
else
log_message "WARN" "easytier" "${proxy}${download_url} 下载失败" "/tmp/easytier.log"
fi
done
log_message "ERROR" "easytier" "所有代理下载均失败,请手动下载上传程序" "/tmp/easytier.log"
return 1
}
# 检查并下载程序
# 参数: $1=程序路径 $2=目标路径 $3=CPU架构
check_and_download() {
local easytierbin="$1"
local path="$2"
local cpucore="$3"
# 检查程序是否存在且完整
if [ ! -f "$easytierbin" ] || [ "$($easytierbin -h 2>&1 | wc -l)" -lt 3 ]; then
log_message "INFO" "easytier" "$easytierbin 不存在或程序不完整,开始在线下载..." "/tmp/easytier.log"
local tag=$(get_latest_version)
log_message "INFO" "easytier" "开始在线下载${tag}版本" "/tmp/easytier.log"
if download_binary "$tag" "$cpucore" "$path"; then
# 移动下载的文件到目标位置
if [ "$(uci -q get easytier.@easytier[0].enabled)" = "1" ]; then
mv -f /tmp/easytier-core "${path}/" 2>/dev/null
mv -f /tmp/easytier-cli "${path}/" 2>/dev/null
chmod +x "$easytierbin" 2>/dev/null
fi
if [ "$(uci -q get easytier.@easytier[0].web_enabled)" = "1" ]; then
local webbin=$(uci -q get easytier.@easytier[0].webbin)
[ -z "$webbin" ] && webbin="/usr/bin/easytier-web"
mv -f /tmp/easytier-web-embed "$webbin" 2>/dev/null || true
chmod +x "$webbin" 2>/dev/null
fi
return 0
fi
return 1
fi
return 0
}
# 处理上传的程序
# 参数: $1=目标路径 $2=程序路径
handle_uploaded_binary() {
local path="$1"
local easytierbin="$2"
local size=$(get_available_space "$path")
if [ -f /tmp/easytier-core ] || [ -f /tmp/easytier-cli ]; then
if [ "${path:0:4}" != "/tmp" ]; then
chmod +x /tmp/easytier-core 2>/dev/null
chmod +x /tmp/easytier-cli 2>/dev/null
mkdir -p "$path"
log_message "INFO" "easytier" "找到上传的程序/tmp/easytier-core替换为$easytierbin" "/tmp/easytier.log"
local upsize=$(du -k /tmp/easytier-core 2>/dev/null | cut -f1)
local result=$((size - upsize))
if [ "$(/tmp/easytier-core -h 2>&1 | wc -l)" -gt 3 ] && [ "$result" -gt 1000 ]; then
mv -f /tmp/easytier-core "$easytierbin" 2>/dev/null
mv -f /tmp/easytier-cli "${path}/easytier-cli" 2>/dev/null
return 0
else
log_message "WARN" "easytier" "无法替换,上传的程序不完整或自定义路径的可用空间不足,当前空间剩余${size}kb" "/tmp/easytier.log"
return 1
fi
fi
fi
return 1
}

View File

@@ -0,0 +1,194 @@
#!/bin/sh
# EasyTier Firewall Management
# Manages firewall rules and network interfaces for EasyTier
# 引入工具函数
. /usr/share/easytier/utils.sh 2>/dev/null || true
# 添加单条防火墙规则
# 参数: $1=规则名称 $2=协议 $3=端口 $4=描述
add_firewall_rule() {
local rule_name="$1"
local proto="$2"
local port="$3"
local desc="$4"
[ -z "$port" ] && return 1
log_message "INFO" "easytier" "添加防火墙规则 ${rule_name} 放行端口 ${port}" "/tmp/easytier.log"
uci -q delete "firewall.${rule_name}"
uci set "firewall.${rule_name}=rule"
uci set "firewall.${rule_name}.name=${rule_name}"
uci set "firewall.${rule_name}.target=ACCEPT"
uci set "firewall.${rule_name}.src=wan"
uci set "firewall.${rule_name}.proto=${proto}"
uci set "firewall.${rule_name}.dest_port=${port}"
uci set "firewall.${rule_name}.enabled=1"
}
# 设置所有 EasyTier 防火墙规则
# 需要设置的变量: tcp_port, udp_port, ws_port, wss_port, wg_port, quic_port, socks_port
set_firewall_rules() {
[ -n "$tcp_port" ] && add_firewall_rule "easytier_tcp_udp" "tcp udp" "$tcp_port" "EasyTier TCP/UDP"
[ -n "$udp_port" ] && add_firewall_rule "easytier_udp" "udp" "$udp_port" "EasyTier UDP"
[ -n "$ws_port" ] && add_firewall_rule "easytier_ws" "tcp" "$ws_port" "EasyTier WS"
[ -n "$wss_port" ] && add_firewall_rule "easytier_wss" "tcp" "$wss_port" "EasyTier WSS"
[ -n "$wg_port" ] && add_firewall_rule "easytier_wg" "udp" "$wg_port" "EasyTier WG"
[ -n "$quic_port" ] && add_firewall_rule "easytier_quic" "tcp udp" "$quic_port" "EasyTier QUIC"
[ -n "$socks_port" ] && add_firewall_rule "easytier_socks5" "tcp" "$socks_port" "EasyTier SOCKS5"
}
# 设置网络接口
# 参数: $1=接口名称 $2=IP地址(可选)
setup_network_interface() {
local tunname="${1:-tun0}"
local ipaddr="$2"
uci -q delete network.EasyTier >/dev/null 2>&1
if [ -z "$(uci -q get network.EasyTier)" ]; then
uci set network.EasyTier='interface'
if [ -z "$ipaddr" ]; then
uci set network.EasyTier.proto='none'
else
uci set network.EasyTier.proto='static'
uci set network.EasyTier.ipaddr="$ipaddr"
uci set network.EasyTier.netmask='255.0.0.0'
fi
log_message "INFO" "easytier" "添加网络接口 EasyTier 绑定虚拟接口 ${tunname}" "/tmp/easytier.log"
uci set network.EasyTier.device="$tunname"
uci set network.EasyTier.ifname="$tunname"
fi
}
# 设置防火墙区域
setup_firewall_zone() {
if [ -z "$(uci -q get firewall.easytierzone)" ]; then
log_message "INFO" "easytier" "添加防火墙规则,放行网络接口 EasyTier 允许出入转发开启IP动态伪装 MSS钳制" "/tmp/easytier.log"
uci set firewall.easytierzone='zone'
uci set firewall.easytierzone.input='ACCEPT'
uci set firewall.easytierzone.output='ACCEPT'
uci set firewall.easytierzone.forward='ACCEPT'
uci set firewall.easytierzone.masq='1'
uci set firewall.easytierzone.mtu_fix='1'
uci set firewall.easytierzone.name='EasyTier'
uci set firewall.easytierzone.network='EasyTier'
fi
}
# 设置转发规则
# 参数: $1=et_forward 配置值
setup_forwarding_rules() {
local et_forward="$1"
if [ "${et_forward#*etfwlan}" != "$et_forward" ]; then
log_message "INFO" "easytier" "允许从虚拟网络 EasyTier 到局域网 lan 的流量" "/tmp/easytier.log"
uci set firewall.easytierfwlan=forwarding
uci set firewall.easytierfwlan.dest='lan'
uci set firewall.easytierfwlan.src='EasyTier'
else
uci -q delete firewall.easytierfwlan
fi
if [ "${et_forward#*etfwwan}" != "$et_forward" ]; then
log_message "INFO" "easytier" "允许从虚拟网络 EasyTier 到广域网 wan 的流量" "/tmp/easytier.log"
uci set firewall.easytierfwwan=forwarding
uci set firewall.easytierfwwan.dest='wan'
uci set firewall.easytierfwwan.src='EasyTier'
else
uci -q delete firewall.easytierfwwan
fi
if [ "${et_forward#*lanfwet}" != "$et_forward" ]; then
log_message "INFO" "easytier" "允许从局域网 lan 到虚拟网络 EasyTier 的流量" "/tmp/easytier.log"
uci set firewall.lanfweasytier=forwarding
uci set firewall.lanfweasytier.dest='EasyTier'
uci set firewall.lanfweasytier.src='lan'
else
uci -q delete firewall.lanfweasytier
fi
if [ "${et_forward#*wanfwet}" != "$et_forward" ]; then
log_message "INFO" "easytier" "允许从广域网 wan 到虚拟网络 EasyTier 的流量" "/tmp/easytier.log"
uci set firewall.wanfweasytier=forwarding
uci set firewall.wanfweasytier.dest='EasyTier'
uci set firewall.wanfweasytier.src='wan'
else
uci -q delete firewall.wanfweasytier
fi
}
# 清理所有 EasyTier 防火墙规则
clean_firewall_rules() {
uci -q delete network.EasyTier >/dev/null 2>&1
uci -q delete firewall.easytierzone >/dev/null 2>&1
uci -q delete firewall.easytierfwlan >/dev/null 2>&1
uci -q delete firewall.easytierfwwan >/dev/null 2>&1
uci -q delete firewall.lanfweasytier >/dev/null 2>&1
uci -q delete firewall.wanfweasytier >/dev/null 2>&1
uci -q delete firewall.easytier_tcp >/dev/null 2>&1
uci -q delete firewall.easytier_udp >/dev/null 2>&1
uci -q delete firewall.easytier_tcp_udp >/dev/null 2>&1
uci -q delete firewall.easytier_wss >/dev/null 2>&1
uci -q delete firewall.easytier_ws >/dev/null 2>&1
uci -q delete firewall.easytier_wg >/dev/null 2>&1
uci -q delete firewall.easytier_quic >/dev/null 2>&1
uci -q delete firewall.easytier_wireguard >/dev/null 2>&1
uci -q delete firewall.easytier_socks5 >/dev/null 2>&1
uci -q delete firewall.easytier_webserver >/dev/null 2>&1
uci -q delete firewall.easytier_webapi >/dev/null 2>&1
uci -q delete firewall.easytier_webhtml >/dev/null 2>&1
}
# 设置 Web 控制台防火墙规则
# 参数: $1=web_port $2=api_port $3=html_port $4=fw_web $5=fw_api
setup_web_firewall() {
local web_port="$1"
local api_port="$2"
local html_port="$3"
local fw_web="$4"
local fw_api="$5"
if [ -n "$web_port" ] && [ "$fw_web" = "1" ]; then
log_message "INFO" "easytier" "添加防火墙规则 easytier_web 放行服务端口 ${web_port}" "/tmp/easytierweb.log"
uci -q delete firewall.easytier_webserver
uci set firewall.easytier_webserver=rule
uci set firewall.easytier_webserver.name="easytier_webserver"
uci set firewall.easytier_webserver.target="ACCEPT"
uci set firewall.easytier_webserver.src="wan"
uci set firewall.easytier_webserver.proto="tcp udp"
uci set firewall.easytier_webserver.dest_port="$web_port"
uci set firewall.easytier_webserver.enabled="1"
fi
if [ -n "$api_port" ] && [ "$fw_api" = "1" ]; then
log_message "INFO" "easytier" "添加防火墙规则 easytier_web 放行API端口 ${api_port}" "/tmp/easytierweb.log"
uci -q delete firewall.easytier_webapi
uci set firewall.easytier_webapi=rule
uci set firewall.easytier_webapi.name="easytier_webapi"
uci set firewall.easytier_webapi.target="ACCEPT"
uci set firewall.easytier_webapi.src="wan"
uci set firewall.easytier_webapi.proto="tcp"
uci set firewall.easytier_webapi.dest_port="$api_port"
uci set firewall.easytier_webapi.enabled="1"
fi
if [ -n "$html_port" ] && [ "$fw_api" = "1" ] && [ "$html_port" != "$api_port" ]; then
log_message "INFO" "easytier" "添加防火墙规则 easytier_web 放行html端口 ${html_port}" "/tmp/easytierweb.log"
uci -q delete firewall.easytier_webhtml
uci set firewall.easytier_webhtml=rule
uci set firewall.easytier_webhtml.name="easytier_webhtml"
uci set firewall.easytier_webhtml.target="ACCEPT"
uci set firewall.easytier_webhtml.src="wan"
uci set firewall.easytier_webhtml.proto="tcp"
uci set firewall.easytier_webhtml.dest_port="$html_port"
uci set firewall.easytier_webhtml.enabled="1"
fi
}
# 应用防火墙和网络配置更改
apply_network_changes() {
[ -n "$(uci changes network)" ] && uci commit network && /etc/init.d/network reload >/dev/null 2>&1
[ -n "$(uci changes firewall)" ] && uci commit firewall && /etc/init.d/firewall reload >/dev/null 2>&1
}

View File

@@ -0,0 +1,89 @@
#!/bin/sh
# EasyTier Utility Functions
# Common helper functions for EasyTier init scripts
# 获取时区设置
get_tz() {
SET_TZ=""
[ -e "/etc/localtime" ] && return
for tzfile in /etc/TZ /var/etc/TZ; do
[ -e "$tzfile" ] || continue
tz="$(cat $tzfile 2>/dev/null)"
done
[ -z "$tz" ] && return
SET_TZ=$tz
}
# 获取 CPU 架构
get_cpu_arch() {
local cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
local cpucore=""
[ -n "$(echo $cputype | grep -E 'linux.*armv.*')" ] && cpucore="arm"
[ -n "$(echo $cputype | grep -E 'linux.*armv7.*')" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && cpucore="armv7"
[ -n "$(echo $cputype | grep -E 'linux.*aarch64.*|linux.*armv8.*')" ] && cpucore="aarch64"
[ -n "$(echo $cputype | grep -E 'linux.*86.*')" ] && cpucore="i386"
[ -n "$(echo $cputype | grep -E 'linux.*86_64.*')" ] && cpucore="x86_64"
if [ -n "$(echo $cputype | grep -E 'linux.*mips.*')" ]; then
local mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}')
[ "$mipstype" = "0" ] && cpucore="mips" || cpucore="mipsel"
fi
echo "$cpucore"
}
# 统一日志记录
log_message() {
local level="$1"
local component="$2"
local message="$3"
local logfile="${4:-/tmp/easytier.log}"
echo "$(date '+%Y-%m-%d %H:%M:%S') ${component} : ${message}" >> "$logfile"
}
# 日志大小管理
manage_log_size() {
local logfile="$1"
local max_size_kb="${2:-5120}"
local keep_lines="${3:-500}"
while true; do
local log_size=$(ls -l "$logfile" 2>/dev/null | awk '{print int($5/1024)}')
if [ "${log_size:-0}" -gt "$max_size_kb" ]; then
tail -n "$keep_lines" "$logfile" > "${logfile}.tmp"
mv "${logfile}.tmp" "$logfile"
fi
sleep 300
done
}
# 获取可用磁盘空间 (KB)
get_available_space() {
local path="$1"
local size=$(df -k | awk '/\/overlay$/ {sub(/K$/, "", $4); print $4}')
[ -z "$size" ] && size=$(df -kP "$path" 2>/dev/null | awk 'NR==2 {print $(NF-2)}')
echo "${size:-0}"
}
# 安全执行命令并返回结果
safe_exec() {
local cmd="$1"
local result=$(eval "$cmd" 2>/dev/null)
echo "$result"
}
# 检查进程是否运行
is_process_running() {
local process_name="$1"
pgrep -f "$process_name" >/dev/null 2>&1
return $?
}
# 停止进程
stop_process() {
local process_name="$1"
ps | grep "$process_name" | grep -v grep | awk '{print $1}' | xargs kill >/dev/null 2>&1
ps | grep "$process_name" | grep -v grep | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1
}

View File

@@ -0,0 +1,5 @@
# EasyTier Version Configuration
# This file is the single source of truth for the EasyTier version
# Used by: easytier/Makefile, luci-app-easytier/Makefile, init.d/easytier
EASYTIER_VERSION=2.5.0