🎁 Sync 2026-11-03 22:44:23

This commit is contained in:
github-actions[bot] committed 2026-11-03 22:44:23 +08:00
1 parent c98c555863
commit b064eba78c
13 files changed
+428 -57

No files matched your search

+2 -2
View File
@@ -9,8 +9,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=cups
PKG_VERSION:=2.3.3op2
PKG_RELEASE:=6
PKG_VERSION:=2.4.20
PKG_RELEASE:=7
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-source.tar.gz
PKG_SOURCE_URL:=https://github.com/OpenPrinting/cups/releases/download/v$(PKG_VERSION)
PKG_MD5SUM:=skip
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=filebrowser-q
PKG_VERSION:=1.5.6-stable
PKG_RELEASE:=12
PKG_VERSION:=2.0.2-stable
PKG_RELEASE:=13
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/gtsteffaniak/filebrowser/tar.gz/v$(PKG_VERSION)?
+17 -22
View File
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=honk
PKG_VERSION:=2026.11.03~77176ff
PKG_RELEASE:=27
PKG_RELEASE:=28
HONK_SRC_URL:=https://github.com/daeuniverse/honk.git
HONK_SRC_VERSION:=77176ff8e8cc2b75385a7030dc376536c382574a
@@ -55,36 +55,31 @@ define Package/honk/conffiles
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
mkdir -p "$(PKG_BUILD_DIR)"
endef
define Build/Compile
@if [ -f $(CURDIR)/files/honk-core.bin ]; then \
$(INSTALL_DIR) $(PKG_INSTALL_DIR)/bin; \
$(INSTALL_BIN) $(CURDIR)/files/honk-core.bin $(PKG_INSTALL_DIR)/bin/honk-core; \
else \
echo "ERROR: $(CURDIR)/files/honk-core.bin missing!" >&2; \
echo "Compile it first via: ./scripts/build_honk_core.sh <arch>" >&2; \
exit 1; \
fi
"$(CURDIR)/build_honk_core.sh" --if-needed "$(ARCH)" "$(CURDIR)/files/honk-core.bin"
$(INSTALL_DIR) "$(PKG_INSTALL_DIR)/bin"
$(INSTALL_BIN) "$(CURDIR)/files/honk-core.bin" "$(PKG_INSTALL_DIR)/bin/honk-core"
endef
define Package/honk/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/honk-core $(1)/usr/bin/honk-core
$(INSTALL_DIR) "$(1)/usr/bin"
$(INSTALL_BIN) "$(PKG_INSTALL_DIR)/bin/honk-core" "$(1)/usr/bin/honk-core"
$(INSTALL_DIR) $(1)/etc/honk/config.d
$(INSTALL_CONF) $(CURDIR)/files/config.dae $(1)/etc/honk/config.dae
$(INSTALL_CONF) $(CURDIR)/files/config.d/node.dae $(1)/etc/honk/config.d/node.dae
$(INSTALL_CONF) $(CURDIR)/files/config.d/route.dae $(1)/etc/honk/config.d/route.dae
$(INSTALL_CONF) $(CURDIR)/files/config.d/dns.dae $(1)/etc/honk/config.d/dns.dae
$(INSTALL_CONF) $(CURDIR)/files/config.d/api.dae $(1)/etc/honk/config.d/api.dae
$(INSTALL_DIR) "$(1)/etc/honk/config.d"
$(INSTALL_CONF) "$(CURDIR)/files/config.dae" "$(1)/etc/honk/config.dae"
$(INSTALL_CONF) "$(CURDIR)/files/config.d/node.dae" "$(1)/etc/honk/config.d/node.dae"
$(INSTALL_CONF) "$(CURDIR)/files/config.d/route.dae" "$(1)/etc/honk/config.d/route.dae"
$(INSTALL_CONF) "$(CURDIR)/files/config.d/dns.dae" "$(1)/etc/honk/config.d/dns.dae"
$(INSTALL_CONF) "$(CURDIR)/files/config.d/api.dae" "$(1)/etc/honk/config.d/api.dae"
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) $(CURDIR)/files/honk.config $(1)/etc/config/honk
$(INSTALL_DIR) "$(1)/etc/config"
$(INSTALL_CONF) "$(CURDIR)/files/honk.config" "$(1)/etc/config/honk"
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(CURDIR)/files/honk.init $(1)/etc/init.d/honk
$(INSTALL_DIR) "$(1)/etc/init.d"
$(INSTALL_BIN) "$(CURDIR)/files/honk.init" "$(1)/etc/init.d/honk"
endef
$(eval $(call BuildPackage,honk))
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env bash
# Build honk-core for an OpenWrt arch/target triple.
#
# ./honk/build_honk_core.sh [--if-needed] <arch|target_triple> [output_file] [source_dir]
#
# --if-needed: skip when the output exists and its .stamp matches the target
# (or has no stamp, i.e. a prebuilt artifact); rebuild on a target mismatch.
set -euo pipefail
IF_NEEDED=0
while [ $# -gt 0 ]; do
case "$1" in
--if-needed) IF_NEEDED=1; shift ;;
*) break ;;
esac
done
TARGET_IN="${1:?usage: $0 [--if-needed] <arch|target_triple> [output_file] [source_dir]}"
OUT_FILE="${2:-}"
SRC_DIR="${3:-}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "${HOME:-}/.cargo/env" ]; then
. "${HOME:-}/.cargo/env"
fi
export PATH="${HOME:-}/.cargo/bin:/usr/local/bin:/usr/bin:/bin:${PATH:-}"
case "$TARGET_IN" in
x86_64|x86_64-unknown-linux-musl)
RUST_TARGET=x86_64-unknown-linux-musl
ZIG_TARGET=x86_64-linux-musl
;;
aarch64|aarch64_generic|aarch64-unknown-linux-musl)
RUST_TARGET=aarch64-unknown-linux-musl
ZIG_TARGET=aarch64-linux-musl
;;
*)
echo "ERROR: unsupported arch: $TARGET_IN" >&2
exit 1
;;
esac
OUT_FILE="${OUT_FILE:-$SCRIPT_DIR/files/honk-core.bin}"
case "$OUT_FILE" in
/*) ;;
*) OUT_FILE="$PWD/$OUT_FILE" ;;
esac
if [ "$IF_NEEDED" = 1 ] && [ -f "$OUT_FILE" ]; then
if [ ! -f "$OUT_FILE.stamp" ]; then
echo "==> using prebuilt honk-core (no stamp): $OUT_FILE"
exit 0
fi
if [ "$(cat "$OUT_FILE.stamp")" = "$RUST_TARGET" ]; then
echo "==> honk-core is up to date: $OUT_FILE"
exit 0
fi
echo "==> honk-core target changed, rebuilding: $OUT_FILE"
fi
# Building: drop the old artifact so a failed build cannot be reused.
rm -f "$OUT_FILE" "$OUT_FILE.stamp"
MAKEFILE="${HONK_MAKEFILE:-$SCRIPT_DIR/Makefile}"
if [ -n "$SRC_DIR" ]; then
eval "$("$SCRIPT_DIR/honk_toolchain.sh" --src "$SRC_DIR" "$MAKEFILE")"
else
eval "$("$SCRIPT_DIR/honk_toolchain.sh" "$MAKEFILE")"
SRC_DIR="$SCRIPT_DIR/honk-src"
CACHED_REV=$(git -C "$SRC_DIR" rev-parse HEAD 2>/dev/null || true)
if [ -d "$SRC_DIR/crates/honk-core" ] && [ "$CACHED_REV" = "$HONK_SRC_VERSION" ]; then
echo "==> Reusing $SRC_DIR at ${HONK_SRC_VERSION}"
else
if [ -n "$CACHED_REV" ]; then
echo "==> honk-src is at ${CACHED_REV}, expected ${HONK_SRC_VERSION}; refetching..."
fi
rm -rf "$SRC_DIR"
echo "==> Fetching honk source (${HONK_SRC_URL} @ ${HONK_SRC_VERSION})..."
git init -q "$SRC_DIR"
git -C "$SRC_DIR" remote add origin "$HONK_SRC_URL"
git -C "$SRC_DIR" fetch --depth 1 origin "$HONK_SRC_VERSION"
git -C "$SRC_DIR" checkout -q --detach FETCH_HEAD
fi
fi
SRC_DIR="$(cd "$SRC_DIR" && pwd)"
echo "==> Source: $SRC_DIR"
echo "==> Target: $RUST_TARGET (zig: $ZIG_TARGET)"
command -v zig >/dev/null 2>&1 || { echo "ERROR: zig not found in PATH" >&2; exit 1; }
command -v bpf-linker >/dev/null 2>&1 || { echo "ERROR: bpf-linker not found in PATH" >&2; exit 1; }
command -v cargo >/dev/null 2>&1 || { echo "ERROR: cargo not found in PATH" >&2; exit 1; }
ZIG_ACTUAL="$(zig version)"
if [ "$ZIG_ACTUAL" != "$ZIG_VERSION" ]; then
echo "ERROR: zig ${ZIG_ACTUAL} does not match the honk pin ${ZIG_VERSION}" >&2
exit 1
fi
echo "==> zig ${ZIG_ACTUAL}"
# bpf-linker 0.11.0 reports 0.0.0; its tarball is checked by sha256 at install time.
echo "==> $(bpf-linker --version 2>/dev/null | head -n 1)"
cd "$SRC_DIR"
EBPF_CHANNEL=$(sed -n 's/^channel[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' crates/honk-ebpf/rust-toolchain.toml 2>/dev/null | head -n 1)
EBPF_CHANNEL="${EBPF_CHANNEL:-nightly}"
if command -v rustup >/dev/null 2>&1; then
rustup target add "$RUST_TARGET"
rustup toolchain install "$EBPF_CHANNEL" --component rust-src,llvm-tools
fi
echo "==> Building honk-ebpf object..."
(
cd crates/honk-ebpf
cargo "+${EBPF_CHANNEL}" build --release -Zbuild-std=core --target bpfel-unknown-none
)
EBPF_OBJ="crates/honk-ebpf/target/bpfel-unknown-none/release/honk-ebpf"
[ -f "$EBPF_OBJ" ] || { echo "ERROR: eBPF object not found at $EBPF_OBJ" >&2; exit 1; }
if command -v readelf >/dev/null 2>&1; then
readelf -S "$EBPF_OBJ" | grep -q '\.BTF' || { echo "ERROR: $EBPF_OBJ has no .BTF section" >&2; exit 1; }
fi
export ZIGCC_TARGET="$ZIG_TARGET"
L=$(printf '%s' "$RUST_TARGET" | tr '-' '_')
U=$(printf '%s' "$RUST_TARGET" | tr 'a-z-' 'A-Z_')
export "CC_${L}=$SRC_DIR/ci/zigcc"
export "CXX_${L}=$SRC_DIR/ci/zigcxx"
export "CARGO_TARGET_${U}_LINKER=$SRC_DIR/ci/zigcc"
if [[ "$RUST_TARGET" == *-musl ]]; then
export "CARGO_TARGET_${U}_RUSTFLAGS=-C link-self-contained=no"
fi
export BINDGEN_EXTRA_CLANG_ARGS="$("$SRC_DIR/ci/zig-bindgen-env" "$ZIGCC_TARGET")"
echo "==> Building honk-core for $RUST_TARGET..."
cargo build --release --locked \
-p honk-core \
--no-default-features \
--features ebpf,rprx,clash-api,native-api,mimalloc \
--target "$RUST_TARGET"
BUILT_BIN="$SRC_DIR/target/$RUST_TARGET/release/honk-core"
[ -f "$BUILT_BIN" ] || { echo "ERROR: expected output not found at $BUILT_BIN" >&2; exit 1; }
FILE_DESC=$(file -b "$BUILT_BIN")
case "$FILE_DESC" in
ELF*) ;;
*) echo "ERROR: output is not an ELF binary: $FILE_DESC" >&2; exit 1 ;;
esac
if [[ "$RUST_TARGET" == *-musl ]] && [[ "$FILE_DESC" != *"statically linked"* ]]; then
echo "ERROR: $RUST_TARGET binary is not statically linked: $FILE_DESC" >&2
exit 1
fi
mkdir -p "$(dirname "$OUT_FILE")"
cp -f "$BUILT_BIN" "$OUT_FILE"
chmod +x "$OUT_FILE"
printf '%s\n' "$RUST_TARGET" > "$OUT_FILE.stamp"
echo "==> Build succeeded: $OUT_FILE"
echo "==> $FILE_DESC"
ls -lh "$OUT_FILE"
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Resolve the toolchain pins for the honk commit pinned by the package Makefile.
#
# ./honk/honk_toolchain.sh [--src DIR] [Makefile]
#
# Prints HONK_SRC_URL / HONK_SRC_VERSION plus BPF_LINKER_VERSION / SHA256 and
# ZIG_VERSION, read from that commit's .github/ci/pins.env and release.yml (or
# from --src when the source is already checked out).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SRC_DIR=""
MAKEFILE=""
while [ $# -gt 0 ]; do
case "$1" in
--src) SRC_DIR="${2:?--src needs a directory}"; shift 2 ;;
*) MAKEFILE="$1"; shift ;;
esac
done
MAKEFILE="${MAKEFILE:-${HONK_MAKEFILE:-$SCRIPT_DIR/Makefile}}"
[ -f "$MAKEFILE" ] || { echo "ERROR: Makefile not found: $MAKEFILE" >&2; exit 1; }
URL=$(sed -n 's/^[[:space:]]*HONK_SRC_URL:=//p' "$MAKEFILE" | head -n 1)
REV=$(sed -n 's/^[[:space:]]*HONK_SRC_VERSION:=//p' "$MAKEFILE" | head -n 1)
[ -n "$URL" ] && [ -n "$REV" ] || {
echo "ERROR: HONK_SRC_URL / HONK_SRC_VERSION missing in $MAKEFILE" >&2
exit 1
}
if [ -n "$SRC_DIR" ]; then
SRC_DIR="$(cd "$SRC_DIR" && pwd)"
PINS_FILE="$SRC_DIR/.github/ci/pins.env"
RELEASE_FILE="$SRC_DIR/.github/workflows/release.yml"
[ -f "$PINS_FILE" ] && [ -f "$RELEASE_FILE" ] || {
echo "ERROR: $SRC_DIR is not a honk checkout with .github metadata" >&2
exit 1
}
else
REPO_PATH="${URL#https://github.com/}"
REPO_PATH="${REPO_PATH%.git}"
RAW="https://raw.githubusercontent.com/${REPO_PATH}/${REV}"
fetch() {
curl -fsSL --retry 3 "$1" || { echo "ERROR: failed to fetch $1" >&2; exit 1; }
}
PINS_FILE="$(mktemp)"
RELEASE_FILE="$(mktemp)"
trap 'rm -f "$PINS_FILE" "$RELEASE_FILE"' EXIT
fetch "${RAW}/.github/ci/pins.env" > "$PINS_FILE"
fetch "${RAW}/.github/workflows/release.yml" > "$RELEASE_FILE"
fi
BPF_LINKER_VERSION=$(sed -n 's/^BPF_LINKER_VERSION=//p' "$PINS_FILE" | head -n 1)
BPF_LINKER_SHA256=$(sed -n 's/^BPF_LINKER_SHA256=//p' "$PINS_FILE" | head -n 1)
[ -n "$BPF_LINKER_VERSION" ] && [ -n "$BPF_LINKER_SHA256" ] || {
echo "ERROR: BPF_LINKER_VERSION / BPF_LINKER_SHA256 missing in $PINS_FILE" >&2
exit 1
}
ZIG_VERSION=$(awk '
/setup-zig/ { seen = 1; next }
seen && /^[[:space:]]*version:[[:space:]]*/ {
sub(/^[[:space:]]*version:[[:space:]]*/, "")
gsub(/[[:space:]"]/, "")
print
exit
}
' "$RELEASE_FILE")
[ -n "$ZIG_VERSION" ] || { echo "ERROR: no setup-zig version in $RELEASE_FILE" >&2; exit 1; }
printf 'HONK_SRC_URL=%s\nHONK_SRC_VERSION=%s\nBPF_LINKER_VERSION=%s\nBPF_LINKER_SHA256=%s\nZIG_VERSION=%s\n' \
"$URL" "$REV" "$BPF_LINKER_VERSION" "$BPF_LINKER_SHA256" "$ZIG_VERSION"
@@ -710,8 +710,8 @@ const CBITextValue = form.TextValue.extend({
const CBIGenValue = form.Value.extend({
__name__: 'CBI.GenValue',
renderWidget(/* ... */) {
let node = form.Value.prototype.renderWidget.apply(this, arguments);
renderWidget(section_id, option_index, cfgvalue) {
let node = form.Value.prototype.renderWidget.call(this, section_id, option_index, cfgvalue);
if (!this.password)
node.classList.add('control-group');
@@ -719,7 +719,7 @@ const CBIGenValue = form.Value.extend({
(node.querySelector('.control-group') || node).appendChild(E('button', {
class: 'cbi-button cbi-button-add',
title: _('Generate'),
click: ui.createHandlerFn(this, handleGenKey, this.hm_options || this.option)
click: ui.createHandlerFn(this, handleGenKey, section_id, this.hm_options || this.option)
}, [ _('Generate') ]));
return node;
@@ -729,13 +729,13 @@ const CBIGenValue = form.Value.extend({
const CBIGenText = CBITextValue.extend({
__name__: 'CBI.GenText',
renderWidget(/* ... */) {
let node = CBITextValue.prototype.renderWidget.apply(this, arguments);
renderWidget(section_id, option_index, cfgvalue) {
let node = CBITextValue.prototype.renderWidget.call(this, section_id, option_index, cfgvalue);
node.appendChild(E('button', {
class: 'cbi-button cbi-button-add',
title: _('Generate'),
click: ui.createHandlerFn(this, handleGenKey, this.hm_options || this.option)
click: ui.createHandlerFn(this, handleGenKey, section_id, this.hm_options || this.option)
}, [ _('Generate') ]));
return node;
@@ -912,7 +912,7 @@ const CBIHandleImport = baseclass.extend(/** @lends hm.HandleImport.prototype */
return uci.save()
.then(L.bind(this.map.load, this.map))
.then(L.bind(this.map.reset, this.map))
.then(L.ui.hideModal)
.then(ui.hideModal)
.catch(() => {});
},
@@ -1548,8 +1548,7 @@ function renderResLink(section_id) {
return El;
}
function handleGenKey(option) {
const section_id = this.section.section;
function handleGenKey(section_id, option) {
const type = this.section.getOption('type')?.formvalue(section_id);
const widget = L.bind(function(option) {
return this.map.findElement('id', 'widget.' + this.cbid(section_id).replace(/\.[^\.]+$/, '.') + option);
@@ -1653,7 +1653,7 @@ return view.extend({
const zerotier_listen_port = {
load(section_id) {
const listen_port = this.map.data.get(this.section.config, section_id, 'zerotier_listen_port') || '';
const listen_port = uci.get(this.section.config, section_id, 'zerotier_listen_port') || '';
const value = [
this.map.data.get(this.section.config, section_id, 'zerotier_primary_port'),
this.map.data.get(this.section.config, section_id, 'zerotier_secondary_port')
@@ -1661,13 +1661,12 @@ return view.extend({
if (listen_port != value) {
uci.set(this.section.config, section_id, 'zerotier_listen_port', value);
return uci.save()
.then(L.bind(this.map.load, this.map))
uci.save()
.then(L.bind(this.map.reset, this.map))
.catch(() => {});
}
return form.Value.prototype.load.apply(this, arguments);
return this.super('load', section_id);
},
write(section_id, formvalue) {
@@ -1678,7 +1677,7 @@ return view.extend({
uci.set(this.section.config, section_id, 'zerotier_listen_port', value);
return form.Value.prototype[formvalue ? 'write' : 'remove'].apply(this, arguments);
return this.super(formvalue ? 'write' : 'remove', ...arguments);
}
};
@@ -1705,19 +1704,18 @@ return view.extend({
const easytier_listen_port = {
load(section_id) {
const listen_port = this.map.data.get(this.section.config, section_id, 'easytier_listen_port') || '';
const listen_port = uci.get(this.section.config, section_id, 'easytier_listen_port') || '';
const value = [...new Set(this.map.data.get(this.section.config, section_id, 'endpoint_listeners')?.map(uri => new URL(uri).port) || [])]
.filter(Boolean).join(',');
if (listen_port != value) {
uci.set(this.section.config, section_id, 'easytier_listen_port', value);
return uci.save()
.then(L.bind(this.map.load, this.map))
uci.save()
.then(L.bind(this.map.reset, this.map))
.catch(() => {});
}
return form.Value.prototype.load.apply(this, arguments);
return this.super('load', section_id);
},
write(section_id, formvalue) {
@@ -1726,7 +1724,7 @@ return view.extend({
uci.set(this.section.config, section_id, 'easytier_listen_port', value);
return form.Value.prototype[formvalue ? 'write' : 'remove'].apply(this, arguments);
return this.super(formvalue ? 'write' : 'remove', ...arguments);
}
};
@@ -162,6 +162,16 @@ return view.extend({
uci.set('firewall', section_id, 'flow_offloading_hw',
(value === '2' && L.hasSystemFeature('offloading_hw')) ? '1' : null);
};
if (fw4 && L.hasSystemFeature('offloading_hw')) {
o = s.option(form.ListValue, 'flow_offloading_hw_ipv6', _('Hardware offloading protocols'));
o.value('1', _('IPv4+v6 acceleration'));
o.value('0', _('IPv4 acceleration'));
o.default = '1';
o.rmempty = false;
o.retain = true;
o.depends('offloading_type', '2');
}
}
+9
View File
@@ -557,6 +557,15 @@ msgstr "基于硬件的流量卸载,可能支持 NAT。"
msgid "Hardware flow offloading"
msgstr "硬件流量卸载"
msgid "Hardware offloading protocols"
msgstr "硬件加速协议"
msgid "IPv4+v6 acceleration"
msgstr "IPv4+v6加速"
msgid "IPv4 acceleration"
msgstr "IPv4加速"
#: applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/ipsets.js:145
msgid "IP (range)"
msgstr "IP(范围)"
+2 -1
View File
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=198
PKG_RELEASE:=98
PKG_RELEASE:=99
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
@@ -20,6 +20,7 @@ PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_NONE_Client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_NONE_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Simple_Obfs \
@@ -479,6 +479,9 @@ end
if is_finded("xray") then
o:value("hysteria2", translate("Hysteria2"))
end
if is_finded("xray") then
o:value("masque", translate("MASQUE"))
end
if is_finded("xray") or is_finded("mihomo") then
o:value("snell", translate("Snell"))
end
@@ -495,6 +498,7 @@ o:depends("type", "ss-rust")
o:depends("type", "trojan")
o:depends("type", "naiveproxy")
o:depends("type", "hysteria2")
o:depends("type", "masque")
o:depends("type", "tuic")
o:depends("type", "shadowtls")
o:depends("type", "socks5")
@@ -520,6 +524,7 @@ o:depends("type", "ss-rust")
o:depends("type", "trojan")
o:depends("type", "naiveproxy")
o:depends("type", "hysteria2")
o:depends("type", "masque")
o:depends("type", "tuic")
o:depends("type", "shadowtls")
o:depends("type", "socks5")
@@ -542,6 +547,7 @@ o.default = "0"
o:depends("type", "socks5")
o:depends({type = "v2ray", v2ray_protocol = "http"})
o:depends({type = "v2ray", v2ray_protocol = "socks"})
o:depends({type = "v2ray", v2ray_protocol = "masque"})
o = s:option(Value, "username", translate("Username"))
o.rmempty = true
@@ -550,6 +556,7 @@ o:depends({type = "v2ray", v2ray_protocol = "naive"})
o:depends({type = "socks5", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "http", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "socks", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "masque", auth_enable = true})
o = s:option(Value, "password", translate("Password"))
o.password = true
@@ -563,6 +570,7 @@ o:depends("type", "shadowtls")
o:depends({type = "socks5", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "http", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "socks", socks_ver = "5", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "masque", auth_enable = true})
o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"})
o:depends({type = "v2ray", v2ray_protocol = "trojan"})
o:depends({type = "v2ray", v2ray_protocol = "anytls"})
@@ -581,6 +589,56 @@ for _, field in ipairs({
o:depends({type = "v2ray", v2ray_protocol = "anytls"})
end
-- [[ MASQUE ]] --
o = s:option(Flag, "masque_warp", "WARP")
o.default = "0"
o:depends({type = "v2ray", v2ray_protocol = "masque"})
for _, field in ipairs({
{ "masque_warp_private_key", translate("WARP Device Private Key") },
{ "masque_warp_public_key", translate("WARP Endpoint Public Key") }
}) do
o = s:option(TextValue, field[1], field[2])
o.rows = 3
o.wrap = "off"
o:depends({type = "v2ray", v2ray_protocol = "masque", masque_warp = "1"})
o.cfgvalue = function(self, section)
return (m:get(section, self.option) or ""):gsub("\\n", "\n")
end
o.validate = function(self, value)
return trim(value):gsub("\r\n?", "\n"):gsub("\n", "\\n")
end
end
o = s:option(DynamicList, "masque_warp_address", "WARP " .. translate("Local Address"))
o:depends({type = "v2ray", v2ray_protocol = "masque", masque_warp = "1"})
o = s:option(Value, "masque_path", translate("MASQUE Path"))
o:depends({type = "v2ray", v2ray_protocol = "masque"})
o = s:option(TextValue, "masque_headers", translate("Custom HTTP Headers"))
o.rows = 5
o.wrap = "off"
o:depends({type = "v2ray", v2ray_protocol = "masque"})
o.cfgvalue = function(self, section)
return (m:get(section, "masque_headers") or ""):gsub("\\n", "\n")
end
o.validate = function(self, value)
value = trim(value):gsub("\r\n", "\n"):gsub("\r", "\n")
local headers = {}
for line in value:gmatch("[^\n]+") do
if trim(line) ~= "" then
local key = line:match("^%s*([^:]+):")
key = key and trim(key):lower()
if not key or not key:match("^[!#$%%&'*+%.%^_`|~%w%-]+$") or headers[key] or key == "host" or key == "capsule-protocol" then
return nil, translate("Not true format, please re-enter!") .. " (" .. line .. ")"
end
headers[key] = true
end
end
return value:gsub("\n", "\\n")
end
o = s:option(Value, "snell_psk", translate("Snell PSK"))
o.password = true
o.rmempty = true
@@ -1501,6 +1559,7 @@ o:depends("transport", "ws")
o:depends("transport", "httpupgrade")
o:depends("transport", "xhttp")
o:depends("transport", "grpc")
o:depends("v2ray_protocol", "masque")
--[[ FinalMask部分 ]]--
o = s:option(Flag, "enable_finalmask", translate("FinalMask"))
@@ -1591,6 +1650,7 @@ o:depends({type = "v2ray", v2ray_protocol = "vmess", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "trojan", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "shadowsocks", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "hysteria2", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "masque", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "anytls", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "socks", socks_ver = "5", reality = false})
o:depends({type = "v2ray", v2ray_protocol = "http", reality = false})
@@ -1649,8 +1709,17 @@ if is_finded("xray") then
o:value("randomized", translate("randomized"))
o:value("unsafe", translate("unsafe"))
o:value("", translate("disable"))
o:depends({type = "v2ray", tls = true})
o:depends({type = "v2ray", reality = true})
local protocols = s.fields["v2ray_protocol"].keylist
if protocols and type(protocols) == "table" and #protocols > 0 then
for _, proto in ipairs(protocols) do
if not proto:find("^_") then
if proto ~= "masque" then
o:depends({type = "v2ray", v2ray_protocol = proto, tls = true})
o:depends({type = "v2ray", v2ray_protocol = proto, reality = true})
end
end
end
end
o = s:option(Flag, "enable_ech", translate("Enable ECH(optional)"))
o.rmempty = true
@@ -1730,6 +1799,8 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
o:depends("type", "trojan")
o:depends("type", "hysteria2")
o:depends("tls", true)
-- TUIC ALPN
@@ -1782,6 +1853,23 @@ if xray_version_val >= 260131 then
string.format("<a href='javascript:void(0)' onclick='javascript:fetchCertByName(this)'>%s</a>", "→ " .. translate("Fetch Manually"))
end
o = s:option(Flag, "masque_certificate", translate("TLS Certificate (PEM)"))
o.default = "0"
o:depends({type = "v2ray", v2ray_protocol = "masque", tls = true})
o = s:option(TextValue, "masque_certificate_pem", " ", translate("Full certificate (chain), PEM format."))
o.default = ""
o.rows = 5
o.wrap = "off"
o:depends("masque_certificate", 1)
o.cfgvalue = function(self, section)
return (m:get(section, "masque_certificate_pem") or ""):gsub("\\n", "\n")
end
o.validate = function(self, value)
value = trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value:gsub("\n", "\\n")
end
-- [[ Hysteria2 TLS pinSHA256 ]] --
o = s:option(Value, "pinsha256", translate("Certificate fingerprint"))
o:depends("type", "hysteria2")
@@ -1861,6 +1949,7 @@ o:depends({type = "v2ray", v2ray_protocol = "trojan"})
o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"})
o:depends({type = "v2ray", v2ray_protocol = "socks"})
o:depends({type = "v2ray", v2ray_protocol = "http"})
o:depends({type = "v2ray", v2ray_protocol = "masque"})
-- [[ TESTPRE ]]--
o = s:option(Value, "preconns", translate("Pre-connections"), translate("Number of early established connections to reduce latency."))
@@ -1956,6 +2045,7 @@ o:depends("type", "ss-rust")
o:depends("type", "trojan")
o:depends("type", "hysteria2")
o:depends({type = "v2ray", v2ray_protocol = "vless", transport = "xhttp"})
o:depends({type = "v2ray", v2ray_protocol = "masque"})
o:depends({type = "v2ray", v2ray_protocol = "hysteria2"})
o = s:option(Flag, "switch_enable", translate("Enable Auto Switch"))
@@ -584,10 +584,20 @@ Xray.outbounds = {
return server.insecure == "1"
end)(),
serverName = server.tls_host,
certificates = server.certificate and {
usage = "verify",
certificateFile = server.certpath
} or nil,
certificates = (function()
if server.masque_certificate == "1" and server.masque_certificate_pem and server.masque_certificate_pem ~= "" then
return {
certificate = split(server.masque_certificate_pem:gsub("\\n", "\n"), "\n"),
usage = "verify"
}
elseif server.certificate == "1" and server.certpath and server.certpath ~= "" then
return {
usage = "verify",
certificateFile = server.certpath
}
end
return nil
end)(),
pinnedPeerCertSha256 = (function()
if xray_version_val < 260131 then return nil end
if not server.tls_CertSha then return "" end
@@ -712,6 +722,28 @@ Xray.outbounds = {
initial_windows_size = server.initial_windows_size and tonumber(server.initial_windows_size) or nil,
user_agent = server.user_agent
} or nil,
masqueSettings = (server.v2ray_protocol == "masque") and {
path = (server.masque_path and server.masque_path ~= "") and server.masque_path or nil,
warp = (server.masque_warp == "1") and {
privateKey = (server.masque_warp_private_key or ""):gsub("\\n", "\n"),
publicKey = (server.masque_warp_public_key or ""):gsub("\\n", "\n"),
address = server.masque_warp_address
} or nil,
headers = (function()
local headers = {}
if server.auth_enable == "1" and server.masque_warp ~= "1" and ((server.username and server.username ~= "") or (server.password and server.password ~= "")) then
headers["authorization"] = "Basic " .. base64Encode((server.username or "") .. ":" .. (server.password or ""))
end
if server.user_agent and server.user_agent ~= "" then
headers["user-agent"] = server.user_agent
end
for line in (server.masque_headers or ""):gsub("\\n", "\n"):gmatch("[^\r\n]+") do
local key, value = line:match("^%s*([^:]+):%s*(.-)%s*$")
if key then headers[trim(key):lower()] = value end
end
return next(headers) and headers or nil
end)()
} or nil,
hysteriaSettings = (server.v2ray_protocol == "hysteria2") and {
-- hysteria2
version = 2,
@@ -922,7 +954,7 @@ Xray.outbounds = {
tcpFastOpen = (function()
if server.transport == "xhttp" then
return (server.fast_open == "1") and true or false
elseif server.v2ray_protocol == "hysteria2" then
elseif server.v2ray_protocol == "hysteria2" or server.v2ray_protocol == "masque" then
return (server.fast_open == "1") and true or nil
else
return nil
@@ -936,7 +968,7 @@ Xray.outbounds = {
((remarks and remarks ~= "") and (node_id .. "." .. remarks) or ("direct" .. "." .. node_id)) or nil
}
} or nil,
mux = (server.v2ray_protocol ~= "hysteria2" and server.v2ray_protocol ~= "wireguard" and server.v2ray_protocol ~= "anytls") and {
mux = (server.v2ray_protocol ~= "hysteria2" and server.v2ray_protocol ~= "wireguard" and server.v2ray_protocol ~= "anytls" and server.v2ray_protocol ~= "masque") and {
-- mux
enabled = (server.mux == "1"), -- Mux
concurrency = (server.mux == "1" and (tonumber(server.concurrency) or -1)) or nil, -- TCP 最大并发连接数
@@ -1027,7 +1059,7 @@ if xray_fragment.fragment ~= "0" or (xray_fragment.noise ~= "0" and xray_noise.e
tcpFastOpen = (function()
if server.transport == "xhttp" then
return (server.fast_open == "1") and true or false
elseif server.v2ray_protocol == "hysteria2" then
elseif server.v2ray_protocol == "hysteria2" or server.v2ray_protocol == "masque" then
return (server.fast_open == "1") and true or nil
else
return nil
+2 -2
View File
@@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ooniprobe
PKG_VERSION:=3.30.0
PKG_RELEASE:=11
PKG_VERSION:=3.31.1
PKG_RELEASE:=12
PKG_SOURCE:=probe-cli-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/ooni/probe-cli/tar.gz/v$(PKG_VERSION)?