From 22202d10ca71e1bd52322262d67fc834c1056f18 Mon Sep 17 00:00:00 2001 From: action Date: Tue, 22 Sep 2026 18:42:30 +0800 Subject: [PATCH] update 2026-09-22 18:42:30 --- oxidns/.github/workflows/update-version.yml | 111 +++++++++++ oxidns/Makefile | 84 +++++++++ oxidns/README.md | 17 ++ oxidns/files/config.yaml | 196 ++++++++++++++++++++ oxidns/files/oxidns.init | 40 ++++ oxidns/files/oxidns.uci | 4 + oxidns/update.sh | 49 +++++ 7 files changed, 501 insertions(+) create mode 100644 oxidns/.github/workflows/update-version.yml create mode 100644 oxidns/Makefile create mode 100644 oxidns/README.md create mode 100644 oxidns/files/config.yaml create mode 100644 oxidns/files/oxidns.init create mode 100644 oxidns/files/oxidns.uci create mode 100644 oxidns/update.sh diff --git a/oxidns/.github/workflows/update-version.yml b/oxidns/.github/workflows/update-version.yml new file mode 100644 index 00000000..19c4f410 --- /dev/null +++ b/oxidns/.github/workflows/update-version.yml @@ -0,0 +1,111 @@ +name: Auto Update oxidns Version + +on: + schedule: + # 每天 UTC 02:00 检查(北京时间 10:00) + - cron: '0 2 * * *' + workflow_dispatch: # 允许手动触发 + +permissions: + contents: write + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + # 使用 GITHUB_TOKEN 推送;如果分支有保护规则需换成 PAT + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Get latest release tag from upstream + id: upstream + run: | + LATEST_TAG=$(curl -sL \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/svenshi/oxidns/releases/latest \ + | jq -r '.tag_name') + + if [[ -z "$LATEST_TAG" || "$LATEST_TAG" == "null" ]]; then + echo "::error::Failed to fetch latest release tag" + exit 1 + fi + + NEW_VERSION="${LATEST_TAG#v}" + echo "latest_tag=${LATEST_TAG}" >> "$GITHUB_OUTPUT" + echo "new_version=${NEW_VERSION}" >> "$GITHUB_OUTPUT" + echo "Latest tag: ${LATEST_TAG} (version: ${NEW_VERSION})" + + - name: Get current version from Makefile + id: current + run: | + CURRENT_VERSION=$(grep -oP '^PKG_VERSION:=\K.*' Makefile) + echo "current_version=${CURRENT_VERSION}" >> "$GITHUB_OUTPUT" + echo "Current version: ${CURRENT_VERSION}" + + - name: Compare versions + id: compare + run: | + if [ "${{ steps.current.outputs.current_version }}" = "${{ steps.upstream.outputs.new_version }}" ]; then + echo "update_needed=false" >> "$GITHUB_OUTPUT" + echo "Already up to date." + else + echo "update_needed=true" >> "$GITHUB_OUTPUT" + echo "Update needed: ${{ steps.current.outputs.current_version }} -> ${{ steps.upstream.outputs.new_version }}" + fi + + - name: Get commit hash for the release tag + if: steps.compare.outputs.update_needed == 'true' + id: tag_commit + run: | + TAG="${{ steps.upstream.outputs.latest_tag }}" + + REF_JSON=$(curl -sL \ + -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/svenshi/oxidns/git/ref/tags/${TAG}") + + OBJECT_TYPE=$(echo "$REF_JSON" | jq -r '.object.type') + COMMIT_SHA=$(echo "$REF_JSON" | jq -r '.object.sha') + + # annotated tag 需要再解析一层 + if [[ "$OBJECT_TYPE" == "tag" ]]; then + COMMIT_SHA=$(curl -sL \ + -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/svenshi/oxidns/git/tags/${COMMIT_SHA}" \ + | jq -r '.object.sha') + fi + + if [[ -z "$COMMIT_SHA" || "$COMMIT_SHA" == "null" ]]; then + echo "::error::Failed to fetch commit hash for tag ${TAG}" + exit 1 + fi + + echo "commit_hash=${COMMIT_SHA}" >> "$GITHUB_OUTPUT" + echo "Commit hash: ${COMMIT_SHA}" + + - name: Run update script + if: steps.compare.outputs.update_needed == 'true' + run: | + chmod +x update.sh + ./update.sh \ + "${{ steps.upstream.outputs.new_version }}" \ + "${{ steps.tag_commit.outputs.commit_hash }}" + + - name: Commit and push to current branch + if: steps.compare.outputs.update_needed == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git add Makefile + + if git diff --cached --quiet; then + echo "No changes to commit." + exit 0 + fi + + git commit -m "oxidns: update to ${{ steps.upstream.outputs.new_version }} [skip ci]" + git push origin "HEAD:${{ github.ref_name }}" \ No newline at end of file diff --git a/oxidns/Makefile b/oxidns/Makefile new file mode 100644 index 00000000..8a632a02 --- /dev/null +++ b/oxidns/Makefile @@ -0,0 +1,84 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=oxidns +PKG_VERSION:=1.5.2 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/svenshi/oxidns.git +PKG_SOURCE_DATE:=2026-09-22 +PKG_SOURCE_VERSION:=8183d0fc20192c7d713718ffdde1c6b8b6f3ec91 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.zst +PKG_MIRROR_HASH:=skip + +PKG_LICENSE:=GPL-3.0-or-later +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Sven Shi + +PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_oxidns-webui +PKG_BUILD_DEPENDS:=rust/host PACKAGE_oxidns-webui:node/host +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk + +define Package/oxidns + SECTION:=net + CATEGORY:=Network + SUBMENU:=DNS + TITLE:=OxiDNS - High-performance DNS Engine + DESCRIPTION:=A high-performance, programmable DNS engine in Rust with flexible pipeline-based routing + DEPENDS:= + URL:=https://github.com/svenshi/oxidns +endef + +define Package/oxidns-webui + $(call Package/oxidns/Default) + SECTION:=net + CATEGORY:=Network + SUBMENU:=DNS + TITLE+= oxidns webui + DESCRIPTION:=A webui for oxidns server. + DEPENDS:=+oxidns +endef + +define Package/oxidns/conffiles +/etc/oxidns/config.yaml +endef + +define Build/Prepare + $(call Build/Prepare/Default) + +ifneq ($(CONFIG_PACKAGE_oxidns-webui),) + (cd $(PKG_BUILD_DIR)/webui && \ + npx -y pnpm install --ignore-scripts && \ + npx -y pnpm build) +endif +endef + +define Build/Compile + $(call Build/Compile/Cargo,,--features full) +endef + +define Package/oxidns/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/target/$(RUSTC_TARGET_ARCH)/release/oxidns $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/etc/oxidns + $(INSTALL_CONF) ./files/config.yaml $(1)/etc/oxidns/config.yaml + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/oxidns.init $(1)/etc/init.d/oxidns + + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/oxidns.uci $(1)/etc/config/oxidns +endef + +define Package/oxidns-webui/install + $(INSTALL_DIR) $(1)/usr/share/oxidns + $(CP) $(PKG_BUILD_DIR)/webui/out $(1)/usr/share/oxidns/webui +endef + +$(eval $(call BuildPackage,oxidns)) +$(eval $(call BuildPackage,oxidns-webui)) diff --git a/oxidns/README.md b/oxidns/README.md new file mode 100644 index 00000000..98f27358 --- /dev/null +++ b/oxidns/README.md @@ -0,0 +1,17 @@ +# OxiDNS OpenWrt Package + +高性能 DNS 策略编排引擎的 OpenWrt 包。 + +## 功能 + +- UDP/TCP/DoT/DoQ/DoH DNS 服务 +- 灵活的策略路由和转发 +- DNS 缓存和 TTL 管理 +- 回退和负载均衡 +- 本地应答和域名改写 +- Prometheus 指标导出 +- WebUI 管理界面 + +## 链接 + +https://github.com/svenshi/oxidns.git diff --git a/oxidns/files/config.yaml b/oxidns/files/config.yaml new file mode 100644 index 00000000..a189e93c --- /dev/null +++ b/oxidns/files/config.yaml @@ -0,0 +1,196 @@ +log: + level: info + file: /tmp/run/oxidns/oxidns.log + rotation: + type: weekly + max_files: 1 +api: + http: + listen: 0.0.0.0:9199 + auth: + type: basic + username: admin + password: oxidns + webui: + root: /usr/share/oxidns/webui + index: index.html +plugins: + - tag: download_main + type: download + args: + downloads: + - url: https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/proxy-list.txt + dir: /etc/oxidns/rules + filename: proxy-list.txt + - url: https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt + dir: /etc/oxidns/rules + filename: gfw.txt + - url: https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/reject-list.txt + dir: /etc/oxidns/rules + filename: reject-list.txt + - url: https://anti-ad.net/easylist.txt + dir: /etc/oxidns/rules + filename: easylist.txt + timeout: 30s + startup_if_missing: true + + - tag: proxy_domains + type: domain_set + args: + files: + - /etc/oxidns/rules/proxy-list.txt + - /etc/oxidns/rules/gfw.txt + + - tag: ad_rules + type: adguard_rule + args: + files: + - /etc/oxidns/rules/reject-list.txt + - /etc/oxidns/rules/easylist.txt + + - tag: reload_download_rules + type: reload_provider + args: + - $proxy_domains + - $ad_rules + + - tag: subscription_refresh + type: sequence + args: + - exec: $download_main + - exec: $reload_download_rules + + - tag: subscription_cron + type: cron + args: + timezone: Asia/Shanghai + jobs: + - name: refresh_download_rules + interval: 168h + executors: + - $subscription_refresh + + - tag: local_hosts + type: hosts + args: + entries: + - translate.googleapis.com 120.26.207.106 + - translate-pa.googleapis.com 120.26.207.106 + - share.dmhy.org 172.67.98.15 + short_circuit: true + + - tag: blocked + type: sequence + args: + - exec: "black_hole 0.0.0.0 ::" + - exec: accept + + - tag: cache_main + type: cache + args: + size: 8192 + short_circuit: true + cache_negative: true + - tag: prefer_ipv4_main + type: prefer_ipv4 + args: + cache: true + cache_ttl: 3600 + - tag: forward_local + type: forward + args: + concurrent: 2 + upstreams: + - tag: alidns_dns + addr: https://223.5.5.5/dns-query + port: 443 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + timeout: 5s + enable_pipeline: false + enable_http3: true + - tag: dnspod_dns + addr: https://1.12.12.12/dns-query + port: 443 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + timeout: 5s + enable_pipeline: false + enable_http3: false + short_circuit: true + - tag: forward_remote + type: forward + args: + concurrent: 2 + upstreams: + - tag: google_dns + addr: https://8.8.8.8/dns-query + port: 443 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + timeout: 3s + enable_http3: false + - tag: cloudflare_dns + addr: https://1.1.1.1/dns-query + port: 443 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + enable_http3: false + short_circuit: true + - tag: forward_remote_proxy + type: forward + args: + concurrent: 2 + upstreams: + - tag: google_dns + addr: https://8.8.8.8/dns-query + port: 443 + socks5: 10.0.0.1:1080 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + timeout: 3s + enable_http3: false + - tag: cloudflare_dns + addr: https://1.1.1.1/dns-query + port: 443 + socks5: 10.0.0.1:1080 + idle_timeout: 30 + max_conns: 256 + insecure_skip_verify: false + enable_http3: false + short_circuit: true + - tag: forward_remote_fallback_main + type: fallback + args: + primary: forward_remote + secondary: forward_remote_proxy + threshold: 150 + always_standby: true + short_circuit: true + - tag: main_sequence + type: sequence + args: + - exec: $local_hosts + - matches: question $ad_rules + exec: goto blocked + - exec: $cache_main + - exec: $prefer_ipv4_main + - matches: qname $proxy_domains + exec: $forward_remote_fallback_main + - matches: "!has_resp" + exec: $forward_local + - tag: udp_server + type: udp_server + args: + entry: main_sequence + listen: :5353 + - tag: tcp_server + type: tcp_server + args: + entry: main_sequence + listen: :5353 diff --git a/oxidns/files/oxidns.init b/oxidns/files/oxidns.init new file mode 100644 index 00000000..ff263549 --- /dev/null +++ b/oxidns/files/oxidns.init @@ -0,0 +1,40 @@ +#!/bin/sh /etc/rc.common + +START=99 +STOP=10 +USE_PROCD=1 + +INSTALL_DIR=/etc/oxidns +CONF=/etc/oxidns/config.yaml +BIN=/usr/bin/oxidns +PID_FILE=/var/run/oxidns.pid + +start_service() { + local enabled + config_load oxidns + config_get_bool enabled main enabled 0 + + [ "$enabled" = "1" ] || return 0 + + procd_open_instance + procd_set_param command "$BIN" start -c "$CONF" -d "$INSTALL_DIR" + procd_set_param respawn 3600 5 0 + procd_set_param stdout 0 + procd_set_param stderr 0 + procd_set_param pidfile "$PID_FILE" + procd_close_instance +} + +stop_service() { + procd_send_signal oxidns +} + +reload_service() { + stop_service + sleep 1 + start_service +} + +service_triggers() { + procd_add_config_trigger "config.change" "oxidns" "$0" "reload" +} diff --git a/oxidns/files/oxidns.uci b/oxidns/files/oxidns.uci new file mode 100644 index 00000000..91a5c480 --- /dev/null +++ b/oxidns/files/oxidns.uci @@ -0,0 +1,4 @@ +config oxidns 'main' + option enabled '0' + option log_level 'info' + option config '/etc/oxidns/config.yaml' diff --git a/oxidns/update.sh b/oxidns/update.sh new file mode 100644 index 00000000..48cdba17 --- /dev/null +++ b/oxidns/update.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -euo pipefail + +# 用法: ./update.sh +# 示例: ./update.sh 1.5.2 abc123def456... + +VERSION="$1" +COMMIT_HASH="$2" +MAKEFILE="Makefile" + +if [[ -z "$VERSION" || -z "$COMMIT_HASH" ]]; then + echo "Usage: $0 " + exit 1 +fi + +# 计算新源文件的时间戳(取当前日期) +SOURCE_DATE=$(date +%Y-%m-%d) + +echo "Updating ${MAKEFILE}: version=${VERSION}, commit=${COMMIT_HASH}, date=${SOURCE_DATE}" + +# 备份原文件 +cp "${MAKEFILE}" "${MAKEFILE}.bak" + +# 更新 PKG_VERSION +sed -i "s/^PKG_VERSION:=.*/PKG_VERSION:=${VERSION}/" "${MAKEFILE}" + +# 更新 PKG_SOURCE_VERSION +sed -i "s/^PKG_SOURCE_VERSION:=.*/PKG_SOURCE_VERSION:=${COMMIT_HASH}/" "${MAKEFILE}" + +# 更新 PKG_SOURCE_DATE +sed -i "s/^PKG_SOURCE_DATE:=.*/PKG_SOURCE_DATE:=${SOURCE_DATE}/" "${MAKEFILE}" + +# 更新 PKG_SOURCE(Subdir 依赖 PKG_VERSION) +sed -i "s/^PKG_SOURCE_SUBDIR:=.*/PKG_SOURCE_SUBDIR:=\$(PKG_NAME)-\$(PKG_VERSION)/" "${MAKEFILE}" + +# 重置 PKG_RELEASE +sed -i "s/^PKG_RELEASE:=.*/PKG_RELEASE:=1/" "${MAKEFILE}" + +# 清除旧的 PKG_MIRROR_HASH(首次构建时会自动生成正确的 hash) +sed -i "s/^PKG_MIRROR_HASH:=.*/PKG_MIRROR_HASH:=skip/" "${MAKEFILE}" + +# 显示变更 +echo "--- Diff ---" +diff "${MAKEFILE}.bak" "${MAKEFILE}" || true + +# 清理备份 +rm -f "${MAKEFILE}.bak" + +echo "Update complete." \ No newline at end of file