mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-31 14:55:13 +08:00
🐶 Sync 2026-06-03 21:58:23
This commit is contained in:
1 parent
8353d69d4c
commit
50ef4176ab
33 files changed
+485
-162
No files matched your search
+2
-2
@@ -6,8 +6,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=gowebdav
|
||||
PKG_VERSION:=5.11.9
|
||||
PKG_RELEASE:=9
|
||||
PKG_VERSION:=5.11.10
|
||||
PKG_RELEASE:=10
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/hacdias/webdav/tar.gz/v$(PKG_VERSION)?
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.6.2
|
||||
PKG_RELEASE:=152
|
||||
PKG_RELEASE:=153
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -1144,10 +1144,12 @@ function fetch_certsha256()
|
||||
local id = http.formvalue("id") or ""
|
||||
local address = (id ~= "") and uci:get(appname, id, "address") or ""
|
||||
local port = (id ~= "") and uci:get(appname, id, "port") or 0
|
||||
if id == "" or address == "" or not api.datatypes.hostname(address) or port == 0 then
|
||||
local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or ""
|
||||
sni = (sni ~= "") and sni or address
|
||||
if address == "" or port == 0 then
|
||||
http_write_json_error()
|
||||
return
|
||||
end
|
||||
local data = api.fetch_cert_sha256(address, port, 5)
|
||||
local data = api.fetch_cert_sha256(address, port, sni, 5)
|
||||
http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
|
||||
end
|
||||
@@ -1570,31 +1570,23 @@ function cleanEmptyTables(t)
|
||||
return next(t) and t or nil
|
||||
end
|
||||
|
||||
function fetch_cert_sha256(host, port, timeout)
|
||||
if not host or not datatypes.hostname(host) then return "" end
|
||||
function fetch_cert_sha256(host, port, sni, timeout)
|
||||
if not host then return "" end
|
||||
port = tonumber(port) or 443
|
||||
sni = sni or host
|
||||
timeout = tonumber(timeout) or 5
|
||||
local xray = finded_com("xray")
|
||||
local cmd
|
||||
if xray then
|
||||
cmd = string.format(
|
||||
"timeout %d %q tls ping %s:%d 2>/dev/null " ..
|
||||
"| awk 'tolower($0) ~ /without sni/ {f=1} tolower($0) ~ /with sni/ {f=0} " ..
|
||||
"f && tolower($0) ~ /cert.*leaf.*sha256/ {sub(/.*:/,\"\"); gsub(/[[:space:]]/,\"\"); print; exit}'",
|
||||
timeout, xray, host, port
|
||||
)
|
||||
else
|
||||
cmd = string.format(
|
||||
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
|
||||
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
|
||||
"| openssl x509 -outform der 2>/dev/null " ..
|
||||
"| sha256sum 2>/dev/null",
|
||||
timeout, host, port, host
|
||||
)
|
||||
end
|
||||
local cmd = string.format(
|
||||
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
|
||||
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
|
||||
"| openssl x509 -outform der 2>/dev/null " ..
|
||||
"| sha256sum 2>/dev/null",
|
||||
timeout, host, port, sni
|
||||
)
|
||||
local out = trim(sys.exec(cmd))
|
||||
local fp = out:match("^([0-9a-fA-F]+)")
|
||||
if not fp then return "" end
|
||||
if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then
|
||||
return ""
|
||||
end
|
||||
return fp:upper()
|
||||
end
|
||||
|
||||
|
||||
@@ -1666,7 +1666,8 @@ function gen_config(var)
|
||||
invert = e.invert == "1" and true or nil
|
||||
}
|
||||
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
if w:find("#") == 1 then return end
|
||||
w = api.trim(w)
|
||||
if w == "" or w:find("#") == 1 then return end
|
||||
if w:find("geosite:") == 1 then
|
||||
local _geosite = w:sub(1 + #"geosite:") --适配srs
|
||||
local t = geo_rule_set("geosite", _geosite)
|
||||
@@ -1703,7 +1704,7 @@ function gen_config(var)
|
||||
domain_table.fakedns = true
|
||||
end
|
||||
|
||||
if outboundTag then
|
||||
if outboundTag and (rule.domain or rule.domain_suffix or rule.domain_keyword or rule.domain_regex or rule.rule_set) then
|
||||
table.insert(dns_domain_rules, api.clone(domain_table))
|
||||
end
|
||||
end
|
||||
@@ -1712,7 +1713,8 @@ function gen_config(var)
|
||||
local ip_cidr = {}
|
||||
local is_private = false
|
||||
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
if w:find("#") == 1 then return end
|
||||
w = api.trim(w)
|
||||
if w == "" or w:find("#") == 1 then return end
|
||||
if w:find("geoip:") == 1 then
|
||||
local _geoip = w:sub(1 + #"geoip:") --适配srs
|
||||
if _geoip == "private" then
|
||||
|
||||
@@ -498,9 +498,9 @@ function gen_config_server(node)
|
||||
|
||||
if node.protocol == "vmess" or node.protocol == "vless" then
|
||||
if node.uuid then
|
||||
local clients = {}
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
clients[i] = {
|
||||
users[i] = {
|
||||
id = node.uuid[i],
|
||||
flow = (node.protocol == "vless"
|
||||
and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none"))
|
||||
@@ -508,7 +508,7 @@ function gen_config_server(node)
|
||||
}
|
||||
end
|
||||
settings = {
|
||||
clients = clients,
|
||||
users = users,
|
||||
decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil
|
||||
}
|
||||
end
|
||||
@@ -516,7 +516,7 @@ function gen_config_server(node)
|
||||
settings = {
|
||||
udp = ("1" == node.udp_forward) and true or false,
|
||||
auth = ("1" == node.auth) and "password" or "noauth",
|
||||
accounts = ("1" == node.auth) and {
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
@@ -526,7 +526,7 @@ function gen_config_server(node)
|
||||
elseif node.protocol == "http" then
|
||||
settings = {
|
||||
allowTransparent = false,
|
||||
accounts = ("1" == node.auth) and {
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
@@ -544,20 +544,20 @@ function gen_config_server(node)
|
||||
}
|
||||
elseif node.protocol == "trojan" then
|
||||
if node.uuid then
|
||||
local clients = {}
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
clients[i] = {
|
||||
users[i] = {
|
||||
password = node.uuid[i],
|
||||
}
|
||||
end
|
||||
settings = {
|
||||
clients = clients
|
||||
users = users
|
||||
}
|
||||
end
|
||||
elseif node.protocol == "hysteria2" then
|
||||
settings = {
|
||||
version = 2,
|
||||
clients = node.hysteria2_auth_password and {
|
||||
users = node.hysteria2_auth_password and {
|
||||
{ auth = node.hysteria2_auth_password }
|
||||
}
|
||||
}
|
||||
@@ -946,7 +946,7 @@ function gen_config(var)
|
||||
end
|
||||
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
|
||||
inbound.settings.auth = "password"
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_socks_username,
|
||||
pass = local_socks_password
|
||||
@@ -963,7 +963,7 @@ function gen_config(var)
|
||||
settings = {allowTransparent = false}
|
||||
}
|
||||
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_http_username,
|
||||
pass = local_http_password
|
||||
@@ -1422,7 +1422,8 @@ function gen_config(var)
|
||||
}
|
||||
domains = {}
|
||||
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
if w:find("#") == 1 then return end
|
||||
w = api.trim(w)
|
||||
if w == "" or w:find("#") == 1 then return end
|
||||
if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end
|
||||
table.insert(domains, w)
|
||||
table.insert(domain_table.domain, w)
|
||||
@@ -1430,16 +1431,17 @@ function gen_config(var)
|
||||
if inner_fakedns == "1" and node[e[".name"] .. "_fakedns"] == "1" and #domains > 0 then
|
||||
domain_table.fakedns = true
|
||||
end
|
||||
if outbound_tag then
|
||||
if #domains == 0 then domains = nil end
|
||||
if outbound_tag and domains then
|
||||
table.insert(dns_domain_rules, api.clone(domain_table))
|
||||
end
|
||||
if #domains == 0 then domains = nil end
|
||||
end
|
||||
local ip = nil
|
||||
if e.ip_list then
|
||||
ip = {}
|
||||
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
if w:find("#") == 1 then return end
|
||||
w = api.trim(w)
|
||||
if w == "" or w:find("#") == 1 then return end
|
||||
if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end
|
||||
table.insert(ip, w)
|
||||
end)
|
||||
@@ -2036,7 +2038,7 @@ function gen_proto_config(var)
|
||||
}
|
||||
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
|
||||
inbound.settings.auth = "password"
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_socks_username,
|
||||
pass = local_socks_password
|
||||
@@ -2056,7 +2058,7 @@ function gen_proto_config(var)
|
||||
}
|
||||
}
|
||||
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_http_username,
|
||||
pass = local_http_password
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.5.19
|
||||
PKG_RELEASE:=50
|
||||
PKG_VERSION:=26.6.3
|
||||
PKG_RELEASE:=51
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -22,7 +22,6 @@ function index()
|
||||
local appname = api.appname -- global definitions not available
|
||||
local uci = api.uci -- in function index()
|
||||
entry({"admin", "services", appname}).dependent = true
|
||||
entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true
|
||||
entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true
|
||||
entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true
|
||||
local e
|
||||
@@ -110,26 +109,12 @@ function index()
|
||||
--[[Backup]]
|
||||
entry({"admin", "services", appname, "create_backup"}, call("create_backup")).leaf = true
|
||||
entry({"admin", "services", appname, "restore_backup"}, call("restore_backup")).leaf = true
|
||||
entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true
|
||||
|
||||
--[[geoview]]
|
||||
entry({"admin", "services", appname, "geo_view"}, call("geo_view")).leaf = true
|
||||
end
|
||||
|
||||
local function http_write_json(content)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify(content or {code = 1}))
|
||||
end
|
||||
|
||||
local function http_write_json_ok(data)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify({code = 1, data = data}))
|
||||
end
|
||||
|
||||
local function http_write_json_error(data)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify({code = 0, data = data}))
|
||||
end
|
||||
|
||||
function check_site(host, port)
|
||||
local nixio = require "nixio"
|
||||
local socket = nixio.socket("inet", "stream")
|
||||
@@ -185,7 +170,24 @@ function check_ip()
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
local function http_write_json(content)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify(content or {code = 1}))
|
||||
end
|
||||
|
||||
local function http_write_json_ok(data)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify({code = 1, data = data}))
|
||||
end
|
||||
|
||||
local function http_write_json_error(data)
|
||||
http.prepare_content("application/json")
|
||||
http.write(jsonStringify({code = 0, data = data}))
|
||||
end
|
||||
|
||||
function reset_config()
|
||||
uci:revert(appname)
|
||||
luci.sys.call("echo '' > /tmp/log/passwall2.log")
|
||||
luci.sys.call('/etc/init.d/passwall2 stop')
|
||||
luci.sys.call('[ -f "/usr/share/passwall2/0_default_config" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2')
|
||||
http.redirect(api.url())
|
||||
@@ -801,6 +803,7 @@ function restore_backup()
|
||||
fp:write(decoded)
|
||||
fp:close()
|
||||
if chunk_index + 1 == total_chunks then
|
||||
uci:revert(appname)
|
||||
api.sys.call("echo '' > /tmp/log/passwall2.log")
|
||||
api.log(0, string.format(" * PassWall2 %s", i18n.translate("Configuration file uploaded successfully…")))
|
||||
local temp_dir = '/tmp/passwall2_bak'
|
||||
|
||||
@@ -72,7 +72,7 @@ end
|
||||
|
||||
m:append(Template(appname .. "/global/status"))
|
||||
|
||||
global_cfgid = m:get("@global[0]")[".name"]
|
||||
global_cfgid = (m:get("@global[0]") or {})[".name"] or ""
|
||||
|
||||
s = m:section(TypedSection, "global")
|
||||
s.anonymous = true
|
||||
|
||||
@@ -59,11 +59,13 @@ o.rewrite_option = o.option
|
||||
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
@@ -339,13 +339,28 @@ o:depends({ [_n("protocol")] = "vless" })
|
||||
---- [[hysteria2]]
|
||||
o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
|
||||
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
|
||||
o.datatype = "or(uinteger,portrange)"
|
||||
o.placeholder = "30"
|
||||
o.default = "30"
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
if api.compare_versions(xray_version, ">", "26.5.9") then
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
else
|
||||
o:depends({ [_n("protocol")] = "__hide"})
|
||||
end
|
||||
|
||||
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
@@ -354,10 +369,12 @@ o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
@@ -431,11 +448,26 @@ if api.compare_versions(xray_version, ">=", "26.1.31") then
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
end
|
||||
|
||||
o = s:option(Flag, _n("ech"), translate("ECH"))
|
||||
o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("tls_certificate")] = true })
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Flag, _n("ech"), translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
@@ -706,7 +738,7 @@ o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("finalmask"), " ")
|
||||
o:depends({ [_n("use_finalmask")] = true })
|
||||
@@ -775,10 +807,14 @@ local protocols = s.fields[_n("protocol")].keylist
|
||||
if #protocols > 0 then
|
||||
for i, v in ipairs(protocols) do
|
||||
if not v:find("^_") then
|
||||
s.fields[_n("address")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("port")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v })
|
||||
local depends_condition = { [_n("protocol")] = v }
|
||||
if v == "hysteria2" then
|
||||
depends_condition[_n("hysteria2_realms")] = false
|
||||
end
|
||||
s.fields[_n("address")]:depends(depends_condition)
|
||||
s.fields[_n("port")]:depends(depends_condition)
|
||||
s.fields[_n("domain_resolver")]:depends(depends_condition)
|
||||
s.fields[_n("domain_strategy")]:depends(depends_condition)
|
||||
|
||||
if v ~= "hysteria2" then
|
||||
s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v })
|
||||
@@ -801,7 +837,7 @@ if not load_shunt_options then
|
||||
o:value("2", translate("Landing Node"))
|
||||
|
||||
o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o1:depends({ [_n("chain_proxy")] = "1" })
|
||||
o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
|
||||
o1.template = appname .. "/cbi/nodes_listvalue"
|
||||
o1.group = {}
|
||||
|
||||
@@ -813,7 +849,7 @@ if not load_shunt_options then
|
||||
end
|
||||
|
||||
o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
|
||||
o2:depends({ [_n("chain_proxy")] = "2" })
|
||||
o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
|
||||
o2.template = appname .. "/cbi/nodes_listvalue"
|
||||
o2.group = {}
|
||||
|
||||
|
||||
@@ -423,10 +423,12 @@ if singbox_tags:find("with_quic") then
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
@@ -531,6 +533,24 @@ o:depends({ [_n("protocol")] = "hysteria"})
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "hysteria"})
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
|
||||
o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("tls_certificate")] = true })
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Flag, _n("ech"), translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
|
||||
|
||||
@@ -48,12 +48,14 @@ o:depends({ [_n("custom")] = false })
|
||||
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Flag, _n("udp"), translate("UDP"))
|
||||
o.default = "1"
|
||||
|
||||
@@ -127,6 +127,17 @@ o:value("xtls-rprx-vision")
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
---- [[ hysteria2 ]]
|
||||
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
@@ -134,10 +145,12 @@ o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"))
|
||||
o.default = 0
|
||||
@@ -210,7 +223,8 @@ function o.write(self, section, value)
|
||||
end
|
||||
|
||||
o = s:option(ListValue, _n("alpn"), translate("alpn"))
|
||||
o.default = "h2,http/1.1"
|
||||
o.default = "default"
|
||||
o:value("default", translate("Default"))
|
||||
o:value("h3")
|
||||
o:value("h2")
|
||||
o:value("h3,h2")
|
||||
@@ -378,7 +392,7 @@ o:depends({ [_n("custom")] = false, [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("custom")] = false, [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("custom")] = false, [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("custom")] = false, [_n("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("finalmask"), "FinalMask JSON")
|
||||
o:depends({ [_n("use_finalmask")] = true })
|
||||
|
||||
@@ -175,10 +175,12 @@ if singbox_tags:find("with_quic") then
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm"))
|
||||
o.default = 0
|
||||
|
||||
@@ -154,12 +154,14 @@ function base64Encode(text)
|
||||
end
|
||||
|
||||
function UrlEncode(szText)
|
||||
if type(szText) ~= "string" then return "" end
|
||||
return szText:gsub("([^%w%-_%.%~])", function(c)
|
||||
return string.format("%%%02X", string.byte(c))
|
||||
end)
|
||||
end
|
||||
|
||||
function UrlDecode(szText)
|
||||
if type(szText) ~= "string" then return "" end
|
||||
return szText and szText:gsub("%+", " "):gsub("%%(%x%x)", function(h)
|
||||
return string.char(tonumber(h, 16))
|
||||
end) or nil
|
||||
|
||||
@@ -20,8 +20,8 @@ function gen_config_server(node)
|
||||
key = node.tls_keyFile,
|
||||
},
|
||||
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
|
||||
type = "salamander",
|
||||
salamander = {
|
||||
type = node.hysteria2_obfs_type,
|
||||
[node.hysteria2_obfs_type] = {
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
@@ -101,8 +101,8 @@ function gen_config(var)
|
||||
end)() or nil
|
||||
},
|
||||
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
|
||||
type = "salamander",
|
||||
salamander = {
|
||||
type = node.hysteria2_obfs_type,
|
||||
[node.hysteria2_obfs_type] = {
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
|
||||
@@ -255,6 +255,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
--max_version = "1.3",
|
||||
fragment = fragment,
|
||||
record_fragment = record_fragment,
|
||||
certificate = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and split(node.tls_certificate_pem, "\n") or nil,
|
||||
ech = (node.ech == "1") and (function()
|
||||
local function get_ech_domain(s) --兼容xray "域名+DNS" 格式ech
|
||||
local domain, dns = s:match("^([^+]+)%+(.+)$")
|
||||
|
||||
@@ -73,8 +73,8 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
local run_socks_instance = true
|
||||
if proxy_table ~= nil and type(proxy_table) == "table" then
|
||||
proxy_tag = proxy_table.tag or nil
|
||||
fragment = proxy_table.fragment or nil
|
||||
noise = proxy_table.noise or nil
|
||||
fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil
|
||||
noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil
|
||||
run_socks_instance = proxy_table.run_socks_instance
|
||||
end
|
||||
|
||||
@@ -189,7 +189,11 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
if not node.tls_CertByName then return "" end
|
||||
return node.tls_CertByName
|
||||
end)(),
|
||||
echConfigList = (node.ech == "1") and node.ech_config or nil
|
||||
echConfigList = (node.ech == "1") and node.ech_config or nil,
|
||||
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
|
||||
certificate = api.split(node.tls_certificate_pem, "\n"),
|
||||
usage = "verify"
|
||||
} or nil
|
||||
} or nil,
|
||||
realitySettings = (node.stream_security == "reality") and {
|
||||
serverName = node.tls_serverName,
|
||||
@@ -298,14 +302,36 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
udp[#udp+1] = c
|
||||
finalmask.udp = udp
|
||||
elseif TP == "hysteria" then
|
||||
local udp = {}
|
||||
if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then
|
||||
finalmask.udp = {{
|
||||
type = node.hysteria2_obfs_type,
|
||||
local o = {
|
||||
type = "salamander",
|
||||
settings = node.hysteria2_obfs_password and {
|
||||
password = node.hysteria2_obfs_password
|
||||
password = node.hysteria2_obfs_password,
|
||||
packetSize = node.hysteria2_obfs_type == "gecko" and "512-1200" or nil
|
||||
} or nil
|
||||
}}
|
||||
}
|
||||
udp[#udp+1] = o
|
||||
end
|
||||
if node.hysteria2_realms then
|
||||
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
|
||||
local url, stun
|
||||
if realm then
|
||||
if realm.token and realm.server_url and realm.realm_id then
|
||||
url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
|
||||
end
|
||||
stun = realm.stun_servers or node.hysteria2_realm_stun
|
||||
end
|
||||
local r = {
|
||||
type = "realm",
|
||||
settings = {
|
||||
url = url,
|
||||
stunServers = stun
|
||||
}
|
||||
}
|
||||
udp[#udp+1] = r
|
||||
end
|
||||
finalmask.udp = udp
|
||||
local up = tonumber(node.hysteria2_up_mbps) or 0
|
||||
local down = tonumber(node.hysteria2_down_mbps) or 0
|
||||
finalmask.quicParams = {
|
||||
@@ -415,6 +441,13 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
|
||||
if node.protocol == "wireguard" then
|
||||
result.settings.kernelMode = false
|
||||
if node.finalmask and node.finalmask ~= "" then
|
||||
local ok, fm = pcall(jsonc.parse, api.base64Decode(node.finalmask))
|
||||
if ok and type(fm) == "table" then
|
||||
result.streamSettings = result.streamSettings or {}
|
||||
result.streamSettings.finalmask = fm
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local alpn = {}
|
||||
@@ -487,9 +520,9 @@ function gen_config_server(node)
|
||||
|
||||
if node.protocol == "vmess" or node.protocol == "vless" then
|
||||
if node.uuid then
|
||||
local clients = {}
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
clients[i] = {
|
||||
users[i] = {
|
||||
id = node.uuid[i],
|
||||
flow = (node.protocol == "vless"
|
||||
and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none"))
|
||||
@@ -497,7 +530,7 @@ function gen_config_server(node)
|
||||
}
|
||||
end
|
||||
settings = {
|
||||
clients = clients,
|
||||
users = users,
|
||||
decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil
|
||||
}
|
||||
end
|
||||
@@ -505,7 +538,7 @@ function gen_config_server(node)
|
||||
settings = {
|
||||
udp = ("1" == node.udp_forward) and true or false,
|
||||
auth = ("1" == node.auth) and "password" or "noauth",
|
||||
accounts = ("1" == node.auth) and {
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
@@ -515,7 +548,7 @@ function gen_config_server(node)
|
||||
elseif node.protocol == "http" then
|
||||
settings = {
|
||||
allowTransparent = false,
|
||||
accounts = ("1" == node.auth) and {
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
@@ -533,20 +566,20 @@ function gen_config_server(node)
|
||||
}
|
||||
elseif node.protocol == "trojan" then
|
||||
if node.uuid then
|
||||
local clients = {}
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
clients[i] = {
|
||||
password = node.uuid[i]
|
||||
users[i] = {
|
||||
password = node.uuid[i],
|
||||
}
|
||||
end
|
||||
settings = {
|
||||
clients = clients
|
||||
users = users
|
||||
}
|
||||
end
|
||||
elseif node.protocol == "hysteria2" then
|
||||
settings = {
|
||||
version = 2,
|
||||
clients = node.hysteria2_auth_password and {
|
||||
users = node.hysteria2_auth_password and {
|
||||
{ auth = node.hysteria2_auth_password }
|
||||
}
|
||||
}
|
||||
@@ -724,14 +757,36 @@ function gen_config_server(node)
|
||||
udp[#udp+1] = c
|
||||
finalmask.udp = udp
|
||||
elseif node.transport == "hysteria" then
|
||||
local udp = {}
|
||||
if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then
|
||||
finalmask.udp = {{
|
||||
type = node.hysteria2_obfs_type,
|
||||
local o = {
|
||||
type = "salamander",
|
||||
settings = node.hysteria2_obfs_password and {
|
||||
password = node.hysteria2_obfs_password
|
||||
password = node.hysteria2_obfs_password,
|
||||
packetSize = node.hysteria2_obfs_type == "gecko" and "512-1200" or nil
|
||||
} or nil
|
||||
}}
|
||||
}
|
||||
udp[#udp+1] = o
|
||||
end
|
||||
if node.hysteria2_realms then
|
||||
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
|
||||
local url, stun
|
||||
if realm then
|
||||
if realm.token and realm.server_url and realm.realm_id then
|
||||
url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
|
||||
end
|
||||
stun = realm.stun_servers or node.hysteria2_realm_stun
|
||||
end
|
||||
local r = {
|
||||
type = "realm",
|
||||
settings = {
|
||||
url = url,
|
||||
stunServers = stun
|
||||
}
|
||||
}
|
||||
udp[#udp+1] = r
|
||||
end
|
||||
finalmask.udp = udp
|
||||
local ignore = tonumber(node.hysteria2_ignore_client_bandwidth) == 1
|
||||
local up = (not ignore) and tonumber(node.hysteria2_up_mbps) or 0
|
||||
local down = (not ignore) and tonumber(node.hysteria2_down_mbps) or 0
|
||||
@@ -761,7 +816,7 @@ function gen_config_server(node)
|
||||
}
|
||||
|
||||
local alpn = {}
|
||||
if node.alpn then
|
||||
if node.alpn and node.alpn ~= "default" then
|
||||
string.gsub(node.alpn, '[^' .. "," .. ']+', function(w)
|
||||
table.insert(alpn, w)
|
||||
end)
|
||||
@@ -907,7 +962,7 @@ function gen_config(var)
|
||||
end
|
||||
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
|
||||
inbound.settings.auth = "password"
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_socks_username,
|
||||
pass = local_socks_password
|
||||
@@ -925,7 +980,7 @@ function gen_config(var)
|
||||
settings = {allowTransparent = false}
|
||||
}
|
||||
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_http_username,
|
||||
pass = local_http_password
|
||||
@@ -2047,7 +2102,7 @@ function gen_proto_config(var)
|
||||
}
|
||||
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
|
||||
inbound.settings.auth = "password"
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_socks_username,
|
||||
pass = local_socks_password
|
||||
@@ -2067,7 +2122,7 @@ function gen_proto_config(var)
|
||||
}
|
||||
}
|
||||
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
|
||||
inbound.settings.accounts = {
|
||||
inbound.settings.users = {
|
||||
{
|
||||
user = local_http_username,
|
||||
pass = local_http_password
|
||||
|
||||
@@ -150,12 +150,9 @@ local api = require "luci.passwall2.api"
|
||||
if (confirm("<%: Do you want to restore the client to default settings?%>")) {
|
||||
setTimeout(function () {
|
||||
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
|
||||
var xhr1 = new XMLHttpRequest();
|
||||
xhr1.open("GET",'<%= api.url("clear_log") %>', false);
|
||||
xhr1.send();
|
||||
var xhr2 = new XMLHttpRequest();
|
||||
xhr2.open("GET",'<%= api.url("reset_config") %>', false);
|
||||
xhr2.send();
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET",'<%= api.url("reset_config") %>', false);
|
||||
xhr.send();
|
||||
window.location.href = '<%= api.url("log") %>'
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
@@ -600,7 +600,7 @@ local current_node = map:get(section)
|
||||
v_password = opt.get("hysteria2_auth_password");
|
||||
var dom_obfs = opt.get("hysteria2_obfs_password");
|
||||
if (dom_obfs && dom_obfs.value != "") {
|
||||
params += "&obfs=" + "salamander";
|
||||
params += opt.query("obfs", "hysteria2_obfs_type");
|
||||
params += opt.query("obfs-password", "hysteria2_obfs_password");
|
||||
}
|
||||
params += opt.query("mport", "hysteria2_hop");
|
||||
@@ -1598,7 +1598,7 @@ local current_node = map:get(section)
|
||||
opt.set(dom_prefix + 'protocol', "hysteria2");
|
||||
opt.set(dom_prefix + 'hysteria2_auth_password', decodeURIComponent(password));
|
||||
if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
|
||||
opt.set(dom_prefix + 'hysteria2_obfs_type', "salamander");
|
||||
opt.set(dom_prefix + 'hysteria2_obfs_type', queryParam.obfs || "salamander");
|
||||
opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
|
||||
}
|
||||
opt.set(dom_prefix + 'hysteria2_hop', queryParam.mport || "");
|
||||
@@ -1609,7 +1609,7 @@ local current_node = map:get(section)
|
||||
dom_prefix = "hysteria2_"
|
||||
opt.set(dom_prefix + 'auth_password', decodeURIComponent(password));
|
||||
if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
|
||||
opt.set(dom_prefix + 'obfs_type', "salamander");
|
||||
opt.set(dom_prefix + 'obfs_type', queryParam.obfs || "salamander");
|
||||
opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
|
||||
}
|
||||
opt.set(dom_prefix + 'hop', queryParam.mport || "");
|
||||
|
||||
@@ -1656,6 +1656,12 @@ msgstr "نام گواهی TLS (CertName)"
|
||||
msgid "TLS is used to verify the leaf certificate name."
|
||||
msgstr "TLS برای تأیید نام گواهی برگ (Leaf Certificate) استفاده میشود."
|
||||
|
||||
msgid "TLS Certificate (PEM)"
|
||||
msgstr "گواهی TLS (PEM)"
|
||||
|
||||
msgid "Full certificate (chain), PEM format."
|
||||
msgstr "گواهی کامل (زنجیرهای)، فرمت PEM."
|
||||
|
||||
msgid "ECH Config"
|
||||
msgstr "پیکربندی ECH"
|
||||
|
||||
@@ -2281,8 +2287,8 @@ msgstr "نادیده گرفتن گره %s به دلیل ناسازگاری با
|
||||
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
|
||||
msgstr "صرفنظر از گره: %s. زیرا Sing-Box از روش انتقال %s پروتکل %s پشتیبانی نمیکند، باید به جای آن از Xray استفاده شود."
|
||||
|
||||
msgid "Xray unsupport %s plugin."
|
||||
msgstr "Xray از افزونه %s پشتیبانی نمیکند."
|
||||
msgid "%s unsupport SS %s plugin."
|
||||
msgstr "%s از افزونه %s پشتیبانی نمیکند."
|
||||
|
||||
msgid "Plugin options Incomplete."
|
||||
msgstr "گزینههای افزونه ناقص است."
|
||||
|
||||
@@ -1657,6 +1657,12 @@ msgstr "Имя TLS-сертификата (CertName)"
|
||||
msgid "TLS is used to verify the leaf certificate name."
|
||||
msgstr "Используется TLS для проверки имени конечного сертификата."
|
||||
|
||||
msgid "TLS Certificate (PEM)"
|
||||
msgstr "Сертификат TLS (PEM)"
|
||||
|
||||
msgid "Full certificate (chain), PEM format."
|
||||
msgstr "Полный сертификат (цепочка), формат PEM."
|
||||
|
||||
msgid "ECH Config"
|
||||
msgstr "Конфигурация ECH"
|
||||
|
||||
@@ -2279,8 +2285,8 @@ msgstr "Пропуск сервера %s: несовместимость с яд
|
||||
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
|
||||
msgstr "Пропуск сервера: %s. Sing-Box не поддерживает метод передачи %s протокола %s, необходимо использовать Xray."
|
||||
|
||||
msgid "Xray unsupport %s plugin."
|
||||
msgstr "Xray не поддерживает плагин %s."
|
||||
msgid "%s unsupport SS %s plugin."
|
||||
msgstr "%s не поддерживает плагин %s."
|
||||
|
||||
msgid "Plugin options Incomplete."
|
||||
msgstr "Опции плагина указаны не полностью."
|
||||
|
||||
@@ -1648,6 +1648,12 @@ msgstr "TLS 证书名称(CertName)"
|
||||
msgid "TLS is used to verify the leaf certificate name."
|
||||
msgstr "TLS 用于验证 leaf 证书的 name。"
|
||||
|
||||
msgid "TLS Certificate (PEM)"
|
||||
msgstr "TLS 证书(PEM)"
|
||||
|
||||
msgid "Full certificate (chain), PEM format."
|
||||
msgstr "完整证书(链),PEM 格式。"
|
||||
|
||||
msgid "ECH Config"
|
||||
msgstr "ECH 配置"
|
||||
|
||||
@@ -2267,8 +2273,8 @@ msgstr "跳过 %s 节点,因未适配到 %s 核心程序,或未正确设置
|
||||
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
|
||||
msgstr "跳过节点:%s,因 Sing-Box 不支持 %s 协议的 %s 传输方式,需更换 Xray。"
|
||||
|
||||
msgid "Xray unsupport %s plugin."
|
||||
msgstr "Xray 不支持 %s 插件。"
|
||||
msgid "%s unsupport SS %s plugin."
|
||||
msgstr "%s 不支持 %s 插件。"
|
||||
|
||||
msgid "Plugin options Incomplete."
|
||||
msgstr "插件选项不完整。"
|
||||
|
||||
@@ -1648,6 +1648,12 @@ msgstr "TLS 憑證名稱(CertName)"
|
||||
msgid "TLS is used to verify the leaf certificate name."
|
||||
msgstr "TLS 用於驗證 leaf 憑證的 name。"
|
||||
|
||||
msgid "TLS Certificate (PEM)"
|
||||
msgstr "TLS 憑證(PEM)"
|
||||
|
||||
msgid "Full certificate (chain), PEM format."
|
||||
msgstr "完整憑證(鏈),PEM 格式。"
|
||||
|
||||
msgid "ECH Config"
|
||||
msgstr "ECH 配置"
|
||||
|
||||
@@ -2273,8 +2279,8 @@ msgstr "跳過 %s 節點,因未適配到 %s 核心程序,或未正確設置
|
||||
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
|
||||
msgstr "跳過節點:%s,因 Sing-Box 不支持 %s 協議的 %s 傳輸方式,需更換 Xray。"
|
||||
|
||||
msgid "Xray unsupport %s plugin."
|
||||
msgstr "Xray 不支持 %s 插件。"
|
||||
msgid "%s unsupport SS %s plugin."
|
||||
msgstr "%s 不支持 %s 插件。"
|
||||
|
||||
msgid "Plugin options Incomplete."
|
||||
msgstr "插件選項不完整。"
|
||||
|
||||
@@ -1012,9 +1012,10 @@ acl_app() {
|
||||
[ -n "$items" ] && {
|
||||
local index=0
|
||||
local item
|
||||
local redir_port dns_port dnsmasq_port
|
||||
local redir_port dns_port dnsmasq_port socks_port
|
||||
local ipt_tmp msg msg2
|
||||
redir_port=11200
|
||||
socks_port=11600
|
||||
dns_port=11300
|
||||
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
|
||||
for item in $items; do
|
||||
@@ -1098,12 +1099,13 @@ acl_app() {
|
||||
set_cache_var "ACL_${sid}_default" "1"
|
||||
else
|
||||
redir_port=$(get_new_port $(expr $redir_port + 1))
|
||||
socks_port=$(get_new_port $(expr $socks_port + 1))
|
||||
|
||||
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
|
||||
if [ -n "${type}" ]; then
|
||||
config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json
|
||||
dns_port=$(get_new_port $(expr $dns_port + 1))
|
||||
local acl_socks_port=$(get_new_port $(expr $redir_port + $index))
|
||||
local acl_socks_port=$socks_port
|
||||
local run_func
|
||||
[ -n "${XRAY_BIN}" ] && run_func="run_xray"
|
||||
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
|
||||
|
||||
@@ -528,36 +528,50 @@ local function parseClashNode(node, add_mode, group, sub_cfg)
|
||||
elseif node.plugin == "v2ray-plugin" then
|
||||
result.plugin = "v2ray-plugin"
|
||||
end
|
||||
if node["plugin-opts"] then
|
||||
if node.plugin == "obfs" then
|
||||
local plugin_opts = ""
|
||||
local opts_mode = node["plugin-opts"].mode
|
||||
if opts_mode then
|
||||
plugin_opts = plugin_opts .. "obfs=" .. opts_mode .. ";"
|
||||
if result.plugin then
|
||||
result.plugin_enabled = "1"
|
||||
if result.type == 'Xray' then
|
||||
if result.plugin ~= "obfs-local" then
|
||||
result.plugin_enabled = nil
|
||||
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Xray", result.plugin)
|
||||
end
|
||||
local opts_host = node["plugin-opts"].host
|
||||
if opts_host then
|
||||
plugin_opts = plugin_opts .. "obfs-host=" .. opts_host
|
||||
elseif result.type == 'sing-box' then
|
||||
if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" then
|
||||
result.plugin_enabled = nil
|
||||
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Sing-Box", result.plugin)
|
||||
end
|
||||
result.plugin_opts = plugin_opts
|
||||
elseif node.plugin == "v2ray-plugin" then
|
||||
local plugin_opts = ""
|
||||
local opts_mode = node["plugin-opts"].mode
|
||||
local opts_tls = node["plugin-opts"].tls
|
||||
if opts_tls then
|
||||
plugin_opts = plugin_opts .. "tls;"
|
||||
end
|
||||
if node["plugin-opts"] and result.plugin_enabled == "1" then
|
||||
if node.plugin == "obfs" then
|
||||
local plugin_opts = ""
|
||||
local opts_mode = node["plugin-opts"].mode
|
||||
if opts_mode then
|
||||
plugin_opts = plugin_opts .. "obfs=" .. opts_mode .. ";"
|
||||
end
|
||||
local opts_host = node["plugin-opts"].host
|
||||
if opts_host then
|
||||
plugin_opts = plugin_opts .. "obfs-host=" .. opts_host
|
||||
end
|
||||
result.plugin_opts = plugin_opts
|
||||
elseif node.plugin == "v2ray-plugin" then
|
||||
local plugin_opts = ""
|
||||
local opts_mode = node["plugin-opts"].mode
|
||||
local opts_tls = node["plugin-opts"].tls
|
||||
if opts_tls then
|
||||
plugin_opts = plugin_opts .. "tls;"
|
||||
end
|
||||
local opts_skip_cert_verify = node["plugin-opts"]["skip-cert-verify"]
|
||||
local opts_host = node["plugin-opts"].host
|
||||
if opts_host then
|
||||
plugin_opts = plugin_opts .. "host=" .. opts_host .. ";"
|
||||
end
|
||||
local opts_path = node["plugin-opts"].path
|
||||
local opts_mux = node["plugin-opts"].mux
|
||||
if node["plugin-opts"].headers then
|
||||
--todo
|
||||
end
|
||||
result.plugin_opts = plugin_opts
|
||||
end
|
||||
local opts_skip_cert_verify = node["plugin-opts"]["skip-cert-verify"]
|
||||
local opts_host = node["plugin-opts"].host
|
||||
if opts_host then
|
||||
plugin_opts = plugin_opts .. "host=" .. opts_host .. ";"
|
||||
end
|
||||
local opts_path = node["plugin-opts"].path
|
||||
local opts_mux = node["plugin-opts"].mux
|
||||
if node["plugin-opts"].headers then
|
||||
--todo
|
||||
end
|
||||
result.plugin_opts = plugin_opts
|
||||
end
|
||||
end
|
||||
elseif node.type == 'ssr' then
|
||||
@@ -961,6 +975,11 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.tls = "0"
|
||||
end
|
||||
|
||||
if info.ech and info.ech ~= "" then
|
||||
result.ech = "1"
|
||||
result.ech_config = info.ech
|
||||
end
|
||||
|
||||
result.tcp_fast_open = info.tfo
|
||||
|
||||
info.fm = (info.fm and info.fm ~= "") and UrlDecode(info.fm) or nil
|
||||
@@ -1090,7 +1109,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if result.type == 'Xray' then
|
||||
-- The obfs-local plugin converts data to a format supported by xray.
|
||||
if result.plugin ~= "obfs-local" then
|
||||
result.error_msg = i18n.translatef("Xray unsupport %s plugin.", result.plugin)
|
||||
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Xray", result.plugin)
|
||||
else
|
||||
local obfs = result.plugin_opts:match("obfs=([^;]+)") or ""
|
||||
local obfs_host = result.plugin_opts:match("obfs%-host=([^;]+)") or ""
|
||||
@@ -1110,6 +1129,12 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.plugin = nil
|
||||
result.plugin_opts = nil
|
||||
end
|
||||
elseif result.type == 'sing-box' then
|
||||
if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" then
|
||||
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Sing-Box", result.plugin)
|
||||
else
|
||||
result.plugin_enabled = "1"
|
||||
end
|
||||
else
|
||||
result.plugin_enabled = "1"
|
||||
end
|
||||
@@ -1223,7 +1248,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
local insecure = params.allowinsecure or params.allowInsecure or params.insecure
|
||||
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0")
|
||||
result.uot = params.udp
|
||||
elseif (params.type ~= "tcp" and params.type ~= "raw") and (params.headerType and params.headerType ~= "none") then
|
||||
else
|
||||
result.error_msg = i18n.translatef("Please replace Xray or Sing-Box to support more transmission methods in Shadowsocks.")
|
||||
end
|
||||
end
|
||||
@@ -1684,7 +1709,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.hysteria2_down_mbps = params.downmbps or sub_hy_down_mbps
|
||||
result.hysteria2_hop = params.mport
|
||||
if params["obfs-password"] or params["obfs_password"] then
|
||||
result.hysteria2_obfs_type = "salamander"
|
||||
result.hysteria2_obfs_type = params.obfs or "salamander"
|
||||
result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"]
|
||||
end
|
||||
|
||||
@@ -1818,6 +1843,10 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.reality_publicKey = params.pbk or nil
|
||||
result.reality_shortId = params.sid or nil
|
||||
end
|
||||
if params.ech and params.ech ~= "" then
|
||||
result.ech = "1"
|
||||
result.ech_config = params.ech
|
||||
end
|
||||
end
|
||||
result.port = port
|
||||
local insecure = params.allowinsecure or params.insecure
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fastfetch
|
||||
PKG_VERSION:=2.63.1
|
||||
PKG_RELEASE:=6
|
||||
PKG_VERSION:=2.64.0
|
||||
PKG_RELEASE:=7
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/fastfetch-cli/fastfetch/tar.gz/$(PKG_VERSION)?
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=opera-proxy
|
||||
PKG_VERSION:=1.22.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru>
|
||||
PKG_LICENSE:=MIT
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
# --- Маппинг OpenWrt ARCH+CPU → имя бинарника на GitHub ---
|
||||
# Формат имён на GitHub: opera-proxy.linux-<suffix>
|
||||
#
|
||||
# OpenWrt $(ARCH) / $(CONFIG_CPU_TYPE) → суффикс GitHub
|
||||
# mips / 24kc → mips
|
||||
# mipsel / 24kc → mipsle
|
||||
# aarch64 / cortex-a53 и др. → arm64
|
||||
# arm / cortex-a7 и др. → arm
|
||||
# arm / cortex-a9+vfpv3 → arm (armv6 нет, ближайший arm)
|
||||
# x86_64 / - → amd64
|
||||
# i386 / - → 386
|
||||
|
||||
ifeq ($(ARCH),mips)
|
||||
GOARCH_SUFFIX:=mips
|
||||
else ifeq ($(ARCH),mipsel)
|
||||
GOARCH_SUFFIX:=mipsle
|
||||
else ifeq ($(ARCH),mips64)
|
||||
GOARCH_SUFFIX:=mips64
|
||||
else ifeq ($(ARCH),mips64el)
|
||||
GOARCH_SUFFIX:=mips64le
|
||||
else ifeq ($(ARCH),aarch64)
|
||||
GOARCH_SUFFIX:=arm64
|
||||
else ifeq ($(ARCH),arm)
|
||||
GOARCH_SUFFIX:=arm
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
GOARCH_SUFFIX:=amd64
|
||||
else ifeq ($(ARCH),i386)
|
||||
GOARCH_SUFFIX:=386
|
||||
else
|
||||
GOARCH_SUFFIX:=$(ARCH)
|
||||
endif
|
||||
|
||||
PKG_SOURCE_URL:=https://github.com/Alexey71/opera-proxy/releases/download/v$(PKG_VERSION)
|
||||
PKG_SOURCE:=opera-proxy.linux-$(GOARCH_SUFFIX)
|
||||
PKG_HASH:=skip
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/opera-proxy
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Standalone Opera VPN proxy client
|
||||
URL:=https://github.com/Alexey71/opera-proxy
|
||||
DEPENDS:=
|
||||
endef
|
||||
|
||||
define Package/opera-proxy/description
|
||||
Standalone Opera VPN client. Starts a plain HTTP/SOCKS5 proxy server
|
||||
forwarding traffic through Opera VPN proxies.
|
||||
Supports country selection: EU, AS, AM.
|
||||
endef
|
||||
|
||||
define Package/opera-proxy/conffiles
|
||||
/etc/config/opera-proxy
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) $(DL_DIR)/$(PKG_SOURCE) $(PKG_BUILD_DIR)/opera-proxy
|
||||
chmod +x $(PKG_BUILD_DIR)/opera-proxy
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/opera-proxy/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/opera-proxy $(1)/usr/bin/opera-proxy
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(CURDIR)/files/opera-proxy.init $(1)/etc/init.d/opera-proxy
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) $(CURDIR)/files/opera-proxy.config $(1)/etc/config/opera-proxy
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,opera-proxy))
|
||||
@@ -0,0 +1,6 @@
|
||||
config opera-proxy 'main'
|
||||
option country 'EU'
|
||||
option bind_address '127.0.0.1:18080'
|
||||
option verbosity '20'
|
||||
option timeout '10s'
|
||||
option socks_mode '0'
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
USE_PROCD=1
|
||||
START=90
|
||||
STOP=10
|
||||
|
||||
NAME=opera-proxy
|
||||
PROG=/usr/bin/${NAME}
|
||||
|
||||
start_service() {
|
||||
local country bind_address verbosity socks_mode timeout
|
||||
|
||||
config_load opera-proxy
|
||||
config_get country main country "EU"
|
||||
config_get bind_address main bind_address "127.0.0.1:18080"
|
||||
config_get verbosity main verbosity "20"
|
||||
config_get timeout main timeout "10s"
|
||||
config_get_bool socks_mode main socks_mode 0
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_append_param command -country "$country"
|
||||
procd_append_param command -bind-address "$bind_address"
|
||||
procd_append_param command -verbosity "$verbosity"
|
||||
procd_append_param command -timeout "$timeout"
|
||||
|
||||
[ "$socks_mode" = "1" ] && procd_append_param command -socks-mode
|
||||
|
||||
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "opera-proxy"
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qBittorrent-Enhanced-Edition
|
||||
PKG_VERSION:=5.1.3.10
|
||||
PKG_RELEASE:=7
|
||||
PKG_VERSION:=5.2.1.10
|
||||
PKG_RELEASE:=8
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/c0re100/qBittorrent-Enhanced-Edition/tar.gz/release-$(PKG_VERSION)?
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=teleproxy
|
||||
PKG_VERSION:=4.14.1
|
||||
PKG_RELEASE:=17
|
||||
PKG_VERSION:=4.15.0
|
||||
PKG_RELEASE:=18
|
||||
|
||||
PKG_MAINTAINER:=Kosntantine Shevlakov <shevlakov@132lan.ru>
|
||||
PKG_LICENSE:=GPLv2
|
||||
|
||||
Reference in new issue
Block a user