update 2025-02-20 23:46:51

This commit is contained in:
actions-user 2025-02-20 23:46:51 +08:00
parent 205593e5ef
commit 5d0e3868cc
18 changed files with 632 additions and 0 deletions

143
daed/Makefile Normal file
View File

@ -0,0 +1,143 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=daed
PKG_VERSION:=2025.02.20
DAED_VERSION:=daed-1750dbe
WING_VERSION:=wing-742e185
CORE_VERSION:=core-16825b5
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=1750dbeccbff7ce7ea0399ef509031e189d2e172
PKG_SOURCE_URL:=https://github.com/daeuniverse/daed.git
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=AGPL-3.0-only MIT
PKG_LICENSE_FILES:=LICENSE wing/LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/wing
PKG_BUILD_DEPENDS:=golang/host bpf-headers node/host
PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=no-mips16
GO_PKG:=github.com/daeuniverse/dae-wing
GO_PKG_LDFLAGS:= \
-s -w -X '$(GO_PKG)/db.AppDescription=$(PKG_NAME) is a integration solution of dae, API and UI.'
GO_PKG_LDFLAGS_X= \
$(GO_PKG)/db.AppName=$(PKG_NAME) \
$(GO_PKG)/db.AppVersion=$(DAED_VERSION)_$(WING_VERSION)_$(CORE_VERSION)
GO_PKG_TAGS:=embedallowed
GO_PKG_TARGET_VARS:=$(filter-out CGO_ENABLED=%,$(GO_PKG_TARGET_VARS)) CGO_ENABLED=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/bpf.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
TAR_CMD=$(HOST_TAR) -C $(BUILD_DIR)/ $(TAR_OPTIONS)
define Package/daed/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=Web Servers/Proxies
URL:=https://github.com/daeuniverse/daed
endef
define Package/daed
$(call Package/daed/Default)
TITLE:=A Modern Dashboard For dae
# You need enable KERNEL_DEBUG_INFO_BTF and KERNEL_BPF_EVENTS
DEPENDS:=$(GO_ARCH_DEPENDS) $(BPF_DEPENDS) \
+ca-bundle +kmod-sched-core +kmod-sched-bpf +kmod-xdp-sockets-diag \
+kmod-veth +v2ray-geoip +v2ray-geosite
endef
define Package/daed/description
daed is a backend of dae, provides a method to bundle arbitrary
frontend, dae and geodata into one binary.
endef
define Package/daed/conffiles
/etc/daed/wing.db
/etc/config/daed
endef
define Build/Prepare
( \
$(TAR) --strip-components=1 -C $(PKG_BUILD_DIR)/../ -xzf $(DL_DIR)/$(PKG_NAME)-$(PKG_VERSION).tar.gz ; \
rm -rf $(PKG_BUILD_DIR) && git clone https://github.com/daeuniverse/dae-wing $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/wing && git -C $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/wing checkout ${WING_VERSION: -7} ; \
rm -rf $(PKG_BUILD_DIR)/dae-core && git clone https://github.com/daeuniverse/dae $(PKG_BUILD_DIR)/dae-core && git -C $(PKG_BUILD_DIR)/dae-core checkout ${CORE_VERSION: -7} ; \
pushd $(PKG_BUILD_DIR)/dae-core ; \
git submodule update --init ; \
go mod tidy ; \
popd ; \
pushd $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/wing ; \
wget -qO - https://github.com/daeuniverse/dae-wing/commit/ca02961.patch | patch -p1 ; \
go mod tidy ; \
popd ; \
pushd $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) ; \
npm install -g pnpm ; \
pnpm install ; \
pnpm build ; \
popd ; \
mkdir -p $(PKG_BUILD_DIR)/webrender/web ; \
cp -rf $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/dist/* $(PKG_BUILD_DIR)/webrender/web ; \
find $(PKG_BUILD_DIR)/webrender/web -type f -size +4k ! -name "*.gz" ! -name "*.woff" ! -name "*.woff2" -exec sh -c '\
gzip -9 -k "{}"; \
if [ "$$$$(stat -c %s {})" -lt "$$$$(stat -c %s {}.gz)" ]; then \
rm {}.gz; \
else \
rm {}; \
fi' \
";" ; \
)
endef
DAE_CFLAGS:= \
-O2 -Wall -Werror \
-DMAX_MATCH_SET_LEN=1024 \
-I$(BPF_HEADERS_DIR)/tools/lib \
-I$(BPF_HEADERS_DIR)/arch/$(BPF_KARCH)/include/asm/mach-generic
ifneq ($(CONFIG_USE_MUSL),)
TARGET_CFLAGS += -D_LARGEFILE64_SOURCE
endif
define Build/Compile
( \
pushd $(PKG_BUILD_DIR) ; \
$(MAKE) deps ; \
$(GO_GENERAL_BUILD_CONFIG_VARS) \
$(GO_PKG_BUILD_CONFIG_VARS) \
$(GO_PKG_BUILD_VARS); \
go generate ./... ; \
cd dae-core ; \
BPF_CLANG="$(CLANG)" \
BPF_STRIP_FLAG="-strip=$(LLVM_STRIP)" \
BPF_CFLAGS="$(DAE_CFLAGS)" \
BPF_TARGET="bpfel,bpfeb" \
go generate control/control.go ; \
popd ; \
$(call GoPackage/Build/Compile) ; \
)
endef
define Package/daed/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dae-wing $(1)/usr/bin/daed
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) $(CURDIR)/files/daed.config $(1)/etc/config/daed
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(CURDIR)/files/daed.init $(1)/etc/init.d/daed
endef
$(eval $(call GoBinPackage,daed))
$(eval $(call BuildPackage,daed))

7
daed/files/daed.config Normal file
View File

@ -0,0 +1,7 @@
config daed 'config'
option enabled '0'
option listen_addr '0.0.0.0:2023'
option log_maxbackups '1'
option log_maxsize '5'

46
daed/files/daed.init Executable file
View File

@ -0,0 +1,46 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2023 Tianling Shen <cnsztl@immortalwrt.org>
USE_PROCD=1
START=99
CONF="daed"
PROG="/usr/bin/daed"
LOG="/var/log/daed/daed.log"
start_service() {
config_load "$CONF"
local enabled
config_get_bool enabled "config" "enabled" "0"
[ "$enabled" -eq "1" ] || return 1
local listen_addr log_maxbackups log_maxsize
config_get listen_addr "config" "listen_addr" "0.0.0.0:2023"
config_get log_maxbackups "config" "log_maxbackups" "1"
config_get log_maxsize "config" "log_maxsize" "5"
procd_open_instance "$CONF"
procd_set_param command "$PROG" run
procd_append_param command --config "/etc/daed/"
procd_append_param command --listen "$listen_addr"
procd_append_param command --logfile "$LOG"
procd_append_param command --logfile-maxbackups "$log_maxbackups"
procd_append_param command --logfile-maxsize "$log_maxsize"
procd_set_param limits core="unlimited"
procd_set_param limits nofile="1000000 1000000"
procd_set_param respawn
# procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}
stop_service() {
rm -f "$LOG"
}
service_triggers() {
procd_add_reload_trigger "$CONF"
}

BIN
luci-app-daed/PIC/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
luci-app-daed/PIC/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

58
luci-app-daed/README.md Normal file
View File

@ -0,0 +1,58 @@
<h1 align="center">luci-app-daed</h1>
<p align="center">
<img width="100" src="https://github.com/daeuniverse/dae/blob/main/logo.png?raw=true" />
</p>
<p align="center">
<b>A Linux high-performance transparent proxy solution based on eBPF.</b>
</p>
-----------
## Build on OpenWrt official 24.10/SnapShots
### 1. Get Source
```bash
git clone https://github.com/QiuSimons/luci-app-daed package/dae
```
- get the libcron
```bash
mkdir -p Package/libcron && wget -O Package/libcron/Makefile https://raw.githubusercontent.com/immortalwrt/packages/refs/heads/master/libs/libcron/Makefile
```
### 2. Install dependencies, refer to https://apt.llvm.org
```bash
apt-get update
apt-get install -y clang-15 llvm-15 npm
```
### 3. Change OpenWrt Source (Requirements for DAE to work)
- Enable eBPF support, add content to: `.config`
```
CONFIG_DEVEL=y
CONFIG_KERNEL_DEBUG_INFO=y
CONFIG_KERNEL_DEBUG_INFO_REDUCED=n
CONFIG_KERNEL_DEBUG_INFO_BTF=y
CONFIG_KERNEL_CGROUPS=y
CONFIG_KERNEL_CGROUP_BPF=y
CONFIG_KERNEL_BPF_EVENTS=y
CONFIG_BPF_TOOLCHAIN_HOST=y
CONFIG_KERNEL_XDP_SOCKETS=y
CONFIG_PACKAGE_kmod-xdp-sockets-diag=y
```
### 4. Build luci-app-daed
```bash
make menuconfig # choose LUCI -> Applications -> luci-app-daed
make package/dae/luci-app-daed/compile V=s # build luci-app-daed
```
## Preview
<p align="center">
<img width="800" src="https://github.com/QiuSimons/luci-app-daed/blob/master/PIC/1.jpg?raw=true" />
<img width="800" src="https://github.com/QiuSimons/luci-app-daed/blob/master/PIC/2.jpg?raw=true" />
</p>

View File

@ -0,0 +1,15 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-daed
PKG_VERSION:=1.2
PKG_RELEASE:=1
LUCI_TITLE:=LuCI Support for DAED
LUCI_DEPENDS:=+daed +curl +libcron +zoneinfo-asia +luci-compat
LUCI_PKGARCH:=all
define Package/$(PKG_NAME)/conffiles
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,34 @@
local sys = require "luci.sys"
local http = require "luci.http"
module("luci.controller.daed", package.seeall)
function index()
if not nixio.fs.access("/etc/config/daed") then
return
end
entry({"admin", "services", "daed"}, alias("admin", "services", "daed", "setting"),_("DAED"), 58).dependent = true
entry({"admin", "services", "daed", "setting"}, cbi("daed/basic"), _("Base Setting"), 1).leaf=true
entry({"admin", "services", "daed", "daed"}, template("daed/daed"), _("Dashboard"), 2).leaf = true
entry({"admin", "services", "daed", "log"}, cbi("daed/log"), _("Logs"), 3).leaf = true
entry({"admin", "services", "daed_status"}, call("act_status"))
entry({"admin", "services", "daed", "get_log"}, call("get_log")).leaf = true
entry({"admin", "services", "daed", "clear_log"}, call("clear_log")).leaf = true
end
function act_status()
local sys = require "luci.sys"
local e = { }
e.running = sys.call("pidof daed >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function get_log()
http.write(sys.exec("cat /var/log/daed/daed.log"))
end
function clear_log()
sys.call("true > /var/log/daed/daed.log")
end

View File

@ -0,0 +1,62 @@
local m, s ,o
m = Map("daed")
m.title = translate("DAED")
m.description = translate("DAE is a Linux high-performance transparent proxy solution based on eBPF, And DAED is a modern dashboard for dae.")
m:section(SimpleSection).template = "daed/daed_status"
s = m:section(TypedSection, "daed", translate("Global Settings"))
s.addremove = false
s.anonymous = true
o = s:option(Flag,"enabled",translate("Enable"))
o.default = 0
enable = s:option(Flag, "subscribe_auto_update", translate("Enable Auto Subscribe Update"))
enable.rmempty = false
o = s:option(Value, "daed_username", translate("Username"))
o.default = Username
o.password = true
o:depends('subscribe_auto_update', '1')
o = s:option(Value, "daed_password", translate("Password"))
o.default = Password
o.password = true
o:depends('subscribe_auto_update', '1')
o = s:option(ListValue, "subscribe_update_week_time", translate("Update Cycle"))
o:value("*", translate("Every Day"))
o:value("1", translate("Every Monday"))
o:value("2", translate("Every Tuesday"))
o:value("3", translate("Every Wednesday"))
o:value("4", translate("Every Thursday"))
o:value("5", translate("Every Friday"))
o:value("6", translate("Every Saturday"))
o:value("7", translate("Every Sunday"))
o.default = "*"
o:depends('subscribe_auto_update', '1')
update_time = s:option(ListValue, "subscribe_update_day_time", translate("Update Time (Every Day)"))
for t = 0, 23 do
update_time:value(t, t..":00")
end
update_time.default = 0
update_time:depends('subscribe_auto_update', '1')
o = s:option(Value, "log_maxbackups", translate("Logfile retention count"))
o.default = 1
o = s:option(Value, "log_maxsize", translate("Logfile Max Size (MB)"))
o.default = 5
o = s:option(Value, "listen_addr",translate("Set the DAED listen address"))
o.default = '0.0.0.0:2023'
m.apply_on_parse = true
m.on_after_apply = function(self,map)
luci.sys.exec("/etc/init.d/daed restart")
end
return m

View File

@ -0,0 +1,5 @@
m = Map("daed")
m:append(Template("daed/daed_log"))
return m

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
<script type="text/javascript">
//<![CDATA[
function clear_log(btn) {
XHR.get('<%=url([[admin]], [[services]], [[daed]], [[clear_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = "";
log_textarea.scrollTop = log_textarea.scrollHeight;
}
location.reload();
}
);
}
var scrolled = false;
XHR.poll(2, '<%=url([[admin]], [[services]], [[daed]], [[get_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = x.responseText;
if (!scrolled) {
log_textarea.scrollTop = log_textarea.scrollHeight;
scrolled = true;
}
}
}
);
//]]>
</script>
<fieldset class="cbi-section" id="_log_fieldset">
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>" style="margin-left: 10px; margin-top: 10px;">
<textarea id="log_textarea" class="cbi-input-textarea" style="width: calc(100% - 20px); height: 645px; margin: 10px;" data-update="change" rows="5" wrap="off" readonly="readonly"></textarea>
</fieldset>

View File

@ -0,0 +1,24 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[daed_status]])%>', null,
function(x, data) {
var tb = document.getElementById('daed_status');
if (data && tb)
{
if (data.running)
{
tb.innerHTML = '<em><b style=\"color:green\"><%:DAED%> <%:RUNNING%></b></em>';
}
else
{
tb.innerHTML = '<em><b style=\"color:red\"><%:DAED%> <%:NOT RUNNING%></b></em>';
}
}
}
);
//]]></script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="daed_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,59 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "DAED"
msgstr "DAED"
msgid "DAE is a Linux high-performance transparent proxy solution based on eBPF, And DAED is a modern dashboard for dae."
msgstr "DAE是一个基于eBPF的Linux高性能透明代理解决方案而DAED是DAE的管理面板。"
msgid "Base Setting"
msgstr "基本设置"
msgid "Dashboard"
msgstr "仪表板"
msgid "Logs"
msgstr "日志"
msgid "Clear logs"
msgstr "清空日志"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "Collecting data..."
msgstr "收集数据..."
msgid "Logfile retention count"
msgstr "日志文件保留数量"
msgid "Logfile Max Size (MB)"
msgstr "日志文件大小MB"
msgid "Set the DAED listen address"
msgstr "设置监听地址"
msgid "DAED is not running"
msgstr "DAED 未运行"
msgid "Please start the DAED service first and try again"
msgstr "请先启动 DAED 服务后重试"
msgid "Enable Auto Subscribe Update"
msgstr "启用订阅自动更新"
msgid "Update Cycle"
msgstr "更新周期"
msgid "Update Time (Every Day)"
msgstr "更新时间(每天)"
msgid "Username"
msgstr "用户名"
msgid "Password"
msgstr "密码"

View File

@ -0,0 +1,36 @@
#!/bin/sh
USERNAME=$(uci -q get daed.config.daed_username)
PASSWORD=$(uci -q get daed.config.daed_password)
PORT=$(echo "$(uci -q get daed.config.listen_addr)" | grep -oE '[0-9]+$' | sed -n '1p')
GRAPHQL_URL="http://127.0.0.1:"$PORT"/graphql"
CRON_FILE="/etc/crontabs/root"
RANDOM_SEED=$RANDOM
RANDOM_NUM=$((RANDOM_SEED % 10 + 1))
login() {
LOGIN=$(curl -s -X POST -H "Content-Type: application/json" -d '{"query":"query Token($username: String!, $password: String!) {\n token(username: $username, password: $password)\n}","variables":{"username":"'"$USERNAME"'","password":"'"$PASSWORD"'"}}' $GRAPHQL_URL)
JSON=${LOGIN#\"}
JSON=${LOGIN%\"}
TOKEN=$(echo $JSON | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
}
update_subscription() {
SUBSCRIPTION_ID_LIST=$(curl -s -X POST -H "Authorization: $TOKEN" -d '{"query": "query Subscriptions {\n subscriptions {\nid\ntag\nstatus\nlink\ninfo\nupdatedAt\nnodes {\nedges {\nid\nname\nprotocol\nlink\n}\n}\n}\n}", "operationName": "Subscriptions"}' $GRAPHQL_URL | grep -o '"id":"[^"]*","tag"' | grep -o 'id":"[^"]*' | grep -o '[^"]*$')
echo "$SUBSCRIPTION_ID_LIST" | while read -r id; do
curl -X POST -H "Authorization: $TOKEN" -d '{"query":"mutation UpdateSubscription($id: ID!) {\n updateSubscription(id: $id) {\n id\n }\n}","variables":{"id":"'"$id"'"},"operationName":"UpdateSubscription"}' $GRAPHQL_URL
done
}
reload() {
curl -X POST -H "Authorization: $TOKEN" -d '{"query":"mutation Run($dry: Boolean!) {\n run(dry: $dry)\n}","variables":{"dry":false},"operationName":"Run"}' $GRAPHQL_URL
}
resetcron() {
touch $CRON_FILE
sed -i '/daed_sub.sh/d' $CRON_FILE 2>/dev/null
[ "$(uci -q get daed.config.subscribe_auto_update)" -eq 1 ] && echo "${RANDOM_NUM} $(uci -q get daed.config.subscribe_update_day_time) * * $(uci -q get daed.config.subscribe_update_week_time) /etc/daed/daed_sub.sh >/dev/null 2>&1" >>$CRON_FILE
crontab $CRON_FILE
}
login && update_subscription && reload && resetcron

View File

@ -0,0 +1,22 @@
#!/bin/sh
[ "${ACTION}" = "ifup" ] || exit 0
DEVICE=$(logread | grep "link is up" | tail -n 1 | awk -F "'" '{print $2}')
DEVICE_TYPE=$(ip link show dev "$DEVICE")
case "$DEVICE_TYPE" in
*"link/ether"*)
(
LOCK_FILE="/tmp/lock/daed_hotplug_lock"
if [ -f "$LOCK_FILE" ]; then
exit 1
else
echo $$ > "$LOCK_FILE" 2>/dev/null
trap 'rm -f "$LOCK_FILE"' EXIT
sleep 60
/etc/init.d/daed restart 2>&1
fi
) &
;;
esac

View File

@ -0,0 +1,45 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2023 Tianling Shen <cnsztl@immortalwrt.org>
USE_PROCD=0
START=98
CONF="daed"
PROG="/usr/bin/daed"
LOG="/var/log/daed/daed.log"
CRON_FILE="/etc/crontabs/root"
RANDOM_SEED=$RANDOM
RANDOM_NUM=$((RANDOM_SEED % 10 + 1))
setcron() {
touch $CRON_FILE
sed -i '/daed_sub.sh/d' $CRON_FILE 2>/dev/null
[ "$(uci -q get daed.config.subscribe_auto_update)" -eq 1 ] && echo "${RANDOM_NUM} $(uci -q get daed.config.subscribe_update_day_time) * * $(uci -q get daed.config.subscribe_update_week_time) /etc/daed/daed_sub.sh >/dev/null 2>&1" >>$CRON_FILE
crontab $CRON_FILE
}
delcron() {
sed -i '/daed_sub.sh/d' $CRON_FILE 2>/dev/null
crontab $CRON_FILE
}
start_service() {
[ -f "/etc/init.d/daed" ] && grep -q "DAE_LOCATION_ASSET" "/etc/init.d/daed" || sed -i '/run/i\ procd_set_param env DAE_LOCATION_ASSET="/usr/share/v2ray"' "/etc/init.d/daed"
config_load "$CONF"
local enabled
config_get_bool enabled "config" "enabled" "0"
if [ "$enabled" -eq 0 ]; then
delcron
return 1
fi
setcron
}
stop_service() {
delcron
}
service_triggers() {
procd_add_reload_trigger "$CONF"
}

View File

@ -0,0 +1,11 @@
{
"luci-app-daed": {
"description": "Grant UCI access for luci-app-daed",
"read": {
"uci": [ "daed" ]
},
"write": {
"uci": [ "daed" ]
}
}
}