|
@@ -1,118 +1,121 @@
|
|
|
-- Copyright (C) 2017 yushi studio <[email protected]> github.com/ywb94
|
|
|
-- Licensed to the public under the GNU General Public License v3.
|
|
|
-
|
|
|
require "nixio.fs"
|
|
|
require "luci.sys"
|
|
|
require "luci.http"
|
|
|
local m, s, o, kcp_enable
|
|
|
-local shadowsocksr = "shadowsocksr"
|
|
|
local sid = arg[1]
|
|
|
local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
|
|
|
|
|
|
local function isKcptun(file)
|
|
|
-if not nixio.fs.access(file, "rwx", "rx", "rx") then
|
|
|
-nixio.fs.chmod(file, 755)
|
|
|
-end
|
|
|
-local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
|
|
|
-return (str:lower() == "kcptun")
|
|
|
+ if not nixio.fs.access(file, "rwx", "rx", "rx") then
|
|
|
+ nixio.fs.chmod(file, 755)
|
|
|
+ end
|
|
|
+ local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
|
|
|
+ return (str:lower() == "kcptun")
|
|
|
end
|
|
|
|
|
|
local server_table = {}
|
|
|
local encrypt_methods = {
|
|
|
-"none",
|
|
|
-"table",
|
|
|
-"rc4",
|
|
|
-"rc4-md5-6",
|
|
|
-"rc4-md5",
|
|
|
-"aes-128-cfb",
|
|
|
-"aes-192-cfb",
|
|
|
-"aes-256-cfb",
|
|
|
-"aes-128-ctr",
|
|
|
-"aes-192-ctr",
|
|
|
-"aes-256-ctr",
|
|
|
-"bf-cfb",
|
|
|
-"camellia-128-cfb",
|
|
|
-"camellia-192-cfb",
|
|
|
-"camellia-256-cfb",
|
|
|
-"cast5-cfb",
|
|
|
-"des-cfb",
|
|
|
-"idea-cfb",
|
|
|
-"rc2-cfb",
|
|
|
-"seed-cfb",
|
|
|
-"salsa20",
|
|
|
-"chacha20",
|
|
|
-"chacha20-ietf",
|
|
|
+ -- ssr
|
|
|
+ "none",
|
|
|
+ "table",
|
|
|
+ "rc4",
|
|
|
+ "rc4-md5-6",
|
|
|
+ "rc4-md5",
|
|
|
+ "aes-128-cfb",
|
|
|
+ "aes-192-cfb",
|
|
|
+ "aes-256-cfb",
|
|
|
+ "aes-128-ctr",
|
|
|
+ "aes-192-ctr",
|
|
|
+ "aes-256-ctr",
|
|
|
+ "bf-cfb",
|
|
|
+ "camellia-128-cfb",
|
|
|
+ "camellia-192-cfb",
|
|
|
+ "camellia-256-cfb",
|
|
|
+ "cast5-cfb",
|
|
|
+ "des-cfb",
|
|
|
+ "idea-cfb",
|
|
|
+ "rc2-cfb",
|
|
|
+ "seed-cfb",
|
|
|
+ "salsa20",
|
|
|
+ "chacha20",
|
|
|
+ "chacha20-ietf"
|
|
|
}
|
|
|
|
|
|
local encrypt_methods_ss = {
|
|
|
--- aead
|
|
|
-"aes-128-gcm",
|
|
|
-"aes-192-gcm",
|
|
|
-"aes-256-gcm",
|
|
|
-"chacha20-ietf-poly1305",
|
|
|
-"xchacha20-ietf-poly1305",
|
|
|
--- stream
|
|
|
-"table",
|
|
|
-"rc4",
|
|
|
-"rc4-md5",
|
|
|
-"aes-128-cfb",
|
|
|
-"aes-192-cfb",
|
|
|
-"aes-256-cfb",
|
|
|
-"aes-128-ctr",
|
|
|
-"aes-192-ctr",
|
|
|
-"aes-256-ctr",
|
|
|
-"bf-cfb",
|
|
|
-"camellia-128-cfb",
|
|
|
-"camellia-192-cfb",
|
|
|
-"camellia-256-cfb",
|
|
|
-"salsa20",
|
|
|
-"chacha20",
|
|
|
-"chacha20-ietf",
|
|
|
+ -- aead
|
|
|
+ "aes-128-gcm",
|
|
|
+ "aes-192-gcm",
|
|
|
+ "aes-256-gcm",
|
|
|
+ "chacha20-ietf-poly1305",
|
|
|
+ "xchacha20-ietf-poly1305",
|
|
|
+ -- stream
|
|
|
+ "table",
|
|
|
+ "rc4",
|
|
|
+ "rc4-md5",
|
|
|
+ "aes-128-cfb",
|
|
|
+ "aes-192-cfb",
|
|
|
+ "aes-256-cfb",
|
|
|
+ "aes-128-ctr",
|
|
|
+ "aes-192-ctr",
|
|
|
+ "aes-256-ctr",
|
|
|
+ "bf-cfb",
|
|
|
+ "camellia-128-cfb",
|
|
|
+ "camellia-192-cfb",
|
|
|
+ "camellia-256-cfb",
|
|
|
+ "salsa20",
|
|
|
+ "chacha20",
|
|
|
+ "chacha20-ietf"
|
|
|
}
|
|
|
|
|
|
local protocol = {
|
|
|
-"origin",
|
|
|
-"verify_deflate",
|
|
|
-"auth_sha1_v4",
|
|
|
-"auth_aes128_sha1",
|
|
|
-"auth_aes128_md5",
|
|
|
-"auth_chain_a",
|
|
|
-"auth_chain_b",
|
|
|
-"auth_chain_c",
|
|
|
-"auth_chain_d",
|
|
|
-"auth_chain_e",
|
|
|
-"auth_chain_f",
|
|
|
+ -- ssr
|
|
|
+ "origin",
|
|
|
+ "verify_deflate",
|
|
|
+ "auth_sha1_v4",
|
|
|
+ "auth_aes128_sha1",
|
|
|
+ "auth_aes128_md5",
|
|
|
+ "auth_chain_a",
|
|
|
+ "auth_chain_b",
|
|
|
+ "auth_chain_c",
|
|
|
+ "auth_chain_d",
|
|
|
+ "auth_chain_e",
|
|
|
+ "auth_chain_f"
|
|
|
}
|
|
|
|
|
|
obfs = {
|
|
|
-"plain",
|
|
|
-"http_simple",
|
|
|
-"http_post",
|
|
|
-"random_head",
|
|
|
-"tls1.2_ticket_auth",
|
|
|
+ -- ssr
|
|
|
+ "plain",
|
|
|
+ "http_simple",
|
|
|
+ "http_post",
|
|
|
+ "random_head",
|
|
|
+ "tls1.2_ticket_auth"
|
|
|
}
|
|
|
|
|
|
local securitys = {
|
|
|
-"auto",
|
|
|
-"none",
|
|
|
-"aes-128-gcm",
|
|
|
-"chacha20-poly1305"
|
|
|
+ -- vmess
|
|
|
+ "auto",
|
|
|
+ "none",
|
|
|
+ "aes-128-gcm",
|
|
|
+ "chacha20-poly1305"
|
|
|
}
|
|
|
|
|
|
local flows = {
|
|
|
-"xtls-rprx-origin",
|
|
|
-"xtls-rprx-origin-udp443",
|
|
|
-"xtls-rprx-direct",
|
|
|
-"xtls-rprx-direct-udp443",
|
|
|
-"xtls-rprx-splice",
|
|
|
-"xtls-rprx-splice-udp443"
|
|
|
+ -- xlts
|
|
|
+ "xtls-rprx-origin",
|
|
|
+ "xtls-rprx-origin-udp443",
|
|
|
+ "xtls-rprx-direct",
|
|
|
+ "xtls-rprx-direct-udp443",
|
|
|
+ "xtls-rprx-splice",
|
|
|
+ "xtls-rprx-splice-udp443"
|
|
|
}
|
|
|
|
|
|
-m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
|
|
|
+m = Map("shadowsocksr", translate("Edit ShadowSocksR Server"))
|
|
|
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/servers")
|
|
|
-if m.uci:get(shadowsocksr, sid) ~= "servers" then
|
|
|
-luci.http.redirect(m.redirect)
|
|
|
-return
|
|
|
+if m.uci:get("shadowsocksr", sid) ~= "servers" then
|
|
|
+ luci.http.redirect(m.redirect)
|
|
|
+ return
|
|
|
end
|
|
|
|
|
|
-- [[ Servers Setting ]]--
|
|
@@ -126,30 +129,36 @@ o.template = "shadowsocksr/ssrurl"
|
|
|
o.value = sid
|
|
|
|
|
|
o = s:option(ListValue, "type", translate("Server Node Type"))
|
|
|
-o:value("ssr", translate("ShadowsocksR"))
|
|
|
+if nixio.fs.access("/usr/bin/ssr-redir") then
|
|
|
+ o:value("ssr", translate("ShadowsocksR"))
|
|
|
+end
|
|
|
if nixio.fs.access("/usr/bin/ss-redir") then
|
|
|
-o:value("ss", translate("Shadowsocks New Version"))
|
|
|
+ o:value("ss", translate("Shadowsocks New Version"))
|
|
|
end
|
|
|
-if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") or nixio.fs.access("/usr/bin/v2ray/v2ray") or nixio.fs.access("/usr/bin/v2ray") then
|
|
|
-o:value("vmess", translate("Vmess"))
|
|
|
-o:value("vless", translate("VLESS"))
|
|
|
+if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/v2ray") then
|
|
|
+ o:value("vmess", translate("Vmess"))
|
|
|
+ o:value("vless", translate("VLESS"))
|
|
|
end
|
|
|
if nixio.fs.access("/usr/sbin/trojan") then
|
|
|
-o:value("trojan", translate("Trojan"))
|
|
|
+ o:value("trojan", translate("Trojan"))
|
|
|
end
|
|
|
if nixio.fs.access("/usr/bin/naive") then
|
|
|
-o:value("naiveproxy", translate("NaiveProxy"))
|
|
|
+ o:value("naiveproxy", translate("NaiveProxy"))
|
|
|
end
|
|
|
if nixio.fs.access("/usr/sbin/redsocks2") then
|
|
|
-o:value("socks5", translate("Socks5"))
|
|
|
-o:value("tun", translate("Network Tunnel"))
|
|
|
+ o:value("socks5", translate("Socks5"))
|
|
|
+ o:value("tun", translate("Network Tunnel"))
|
|
|
end
|
|
|
o.description = translate("Using incorrect encryption mothod may causes service fail to start")
|
|
|
|
|
|
o = s:option(Value, "alias", translate("Alias(optional)"))
|
|
|
|
|
|
o = s:option(ListValue, "iface", translate("Network interface to use"))
|
|
|
-for _, e in ipairs(luci.sys.net.devices()) do if e ~= "lo" then o:value(e) end end
|
|
|
+for _, e in ipairs(luci.sys.net.devices()) do
|
|
|
+ if e ~= "lo" then
|
|
|
+ o:value(e)
|
|
|
+ end
|
|
|
+end
|
|
|
o:depends("type", "tun")
|
|
|
o.description = translate("Redirect traffic to this network interface")
|
|
|
|
|
@@ -195,26 +204,54 @@ o:depends("type", "naiveproxy")
|
|
|
o:depends({type = "socks5", auth_enable = true})
|
|
|
|
|
|
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
|
|
-for _, v in ipairs(encrypt_methods) do o:value(v) end
|
|
|
+for _, v in ipairs(encrypt_methods) do
|
|
|
+ o:value(v)
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "ssr")
|
|
|
|
|
|
o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method"))
|
|
|
-for _, v in ipairs(encrypt_methods_ss) do o:value(v) end
|
|
|
+for _, v in ipairs(encrypt_methods_ss) do
|
|
|
+ o:value(v)
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "ss")
|
|
|
|
|
|
-- Shadowsocks Plugin
|
|
|
-o = s:option(Value, "plugin", translate("Plugin"))
|
|
|
+o = s:option(ListValue, "plugin", translate("Obfs"))
|
|
|
+o:value("", translate("None"))
|
|
|
+if nixio.fs.access("/usr/bin/obfs-local") then
|
|
|
+ o:value("obfs-local", translate("simple-obfs"))
|
|
|
+end
|
|
|
+if nixio.fs.access("/usr/bin/v2ray-plugin") then
|
|
|
+ o:value("v2ray-plugin", translate("v2ray-plugin"))
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "ss")
|
|
|
|
|
|
-o = s:option(Value, "plugin_opts", translate("Plugin Opts"))
|
|
|
+o = s:option(ListValue, "simple_obfs", translate("Plugin Opts"))
|
|
|
+o:value("obfs=tls;obfs-host=", translate("TLS"))
|
|
|
+o:value("obfs=http;obfs-host=", translate("HTTP"))
|
|
|
+o:depends("plugin", "obfs-local")
|
|
|
+o.rmempty = true
|
|
|
+
|
|
|
+o = s:option(ListValue, "v2ray_plugin", translate("Plugin Opts"))
|
|
|
+o:value("tls;host=", translate("TLS"))
|
|
|
+o:value("mode=quic;host=", translate("QUIC"))
|
|
|
+o:value("none", translate("HTTP"))
|
|
|
+o:depends("plugin", "v2ray-plugin")
|
|
|
o.rmempty = true
|
|
|
-o:depends("type", "ss")
|
|
|
+
|
|
|
+o = s:option(Value, "plugin_opts", translate("Plugin Opts"), translate("Please fill in the Host, for example: www.baidu.com"))
|
|
|
+o.rmempty = true
|
|
|
+o:depends({type = "ss", plugin = "obfs-local"})
|
|
|
+o:depends({type = "ss", v2ray_plugin = "tls;host="})
|
|
|
+o:depends({type = "ss", v2ray_plugin = "mode=quic;host="})
|
|
|
|
|
|
o = s:option(ListValue, "protocol", translate("Protocol"))
|
|
|
-for _, v in ipairs(protocol) do o:value(v) end
|
|
|
+for _, v in ipairs(protocol) do
|
|
|
+ o:value(v)
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "ssr")
|
|
|
|
|
@@ -222,7 +259,9 @@ o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
|
|
|
o:depends("type", "ssr")
|
|
|
|
|
|
o = s:option(ListValue, "obfs", translate("Obfs"))
|
|
|
-for _, v in ipairs(obfs) do o:value(v) end
|
|
|
+for _, v in ipairs(obfs) do
|
|
|
+ o:value(v)
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "ssr")
|
|
|
|
|
@@ -251,7 +290,9 @@ o:depends("type", "vless")
|
|
|
|
|
|
-- 加密方式
|
|
|
o = s:option(ListValue, "security", translate("Encrypt Method"))
|
|
|
-for _, v in ipairs(securitys) do o:value(v, v:upper()) end
|
|
|
+for _, v in ipairs(securitys) do
|
|
|
+ o:value(v, v:upper())
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o:depends("type", "vmess")
|
|
|
|
|
@@ -267,7 +308,6 @@ o:depends("type", "vmess")
|
|
|
o:depends("type", "vless")
|
|
|
|
|
|
-- [[ TCP部分 ]]--
|
|
|
-
|
|
|
-- TCP伪装
|
|
|
o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
|
|
|
o:depends("transport", "tcp")
|
|
@@ -286,7 +326,6 @@ o:depends("tcp_guise", "http")
|
|
|
o.rmempty = true
|
|
|
|
|
|
-- [[ WS部分 ]]--
|
|
|
-
|
|
|
-- WS域名
|
|
|
o = s:option(Value, "ws_host", translate("WebSocket Host"))
|
|
|
o:depends({transport = "ws", tls = false})
|
|
@@ -310,7 +349,6 @@ o:depends("transport", "h2")
|
|
|
o.rmempty = true
|
|
|
|
|
|
-- [[ QUIC部分 ]]--
|
|
|
-
|
|
|
o = s:option(ListValue, "quic_security", translate("QUIC Security"))
|
|
|
o:depends("transport", "quic")
|
|
|
o:value("none", translate("None"))
|
|
@@ -329,19 +367,18 @@ o:value("none", translate("None"))
|
|
|
o:value("srtp", translate("VideoCall (SRTP)"))
|
|
|
o:value("utp", translate("BitTorrent (uTP)"))
|
|
|
o:value("wechat-video", translate("WechatVideo"))
|
|
|
-o:value("dtls", "DTLS 1.2")
|
|
|
-o:value("wireguard", "WireGuard")
|
|
|
+o:value("dtls", translate("DTLS 1.2"))
|
|
|
+o:value("wireguard", translate("WireGuard"))
|
|
|
|
|
|
-- [[ mKCP部分 ]]--
|
|
|
-
|
|
|
o = s:option(ListValue, "kcp_guise", translate("Camouflage Type"))
|
|
|
o:depends("transport", "kcp")
|
|
|
o:value("none", translate("None"))
|
|
|
o:value("srtp", translate("VideoCall (SRTP)"))
|
|
|
o:value("utp", translate("BitTorrent (uTP)"))
|
|
|
o:value("wechat-video", translate("WechatVideo"))
|
|
|
-o:value("dtls", "DTLS 1.2")
|
|
|
-o:value("wireguard", "WireGuard")
|
|
|
+o:value("dtls", translate("DTLS 1.2"))
|
|
|
+o:value("wireguard", translate("WireGuard"))
|
|
|
o.rmempty = true
|
|
|
|
|
|
o = s:option(Value, "mtu", translate("MTU"))
|
|
@@ -397,16 +434,18 @@ o:depends({type = "vless", xtls = false})
|
|
|
o:depends("type", "trojan")
|
|
|
|
|
|
-- XTLS
|
|
|
-if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") then
|
|
|
-o = s:option(Flag, "xtls", translate("XTLS"))
|
|
|
-o.rmempty = true
|
|
|
-o.default = "0"
|
|
|
-o:depends({type = "vless", transport = "tcp", tls = false})
|
|
|
+if nixio.fs.access("/usr/bin/xray") then
|
|
|
+ o = s:option(Flag, "xtls", translate("XTLS"))
|
|
|
+ o.rmempty = true
|
|
|
+ o.default = "0"
|
|
|
+ o:depends({type = "vless", transport = "tcp", tls = false})
|
|
|
end
|
|
|
|
|
|
-- Flow
|
|
|
o = s:option(Value, "vless_flow", translate("Flow"))
|
|
|
-for _, v in ipairs(flows) do o:value(v, v) end
|
|
|
+for _, v in ipairs(flows) do
|
|
|
+ o:value(v, v)
|
|
|
+end
|
|
|
o.rmempty = true
|
|
|
o.default = "xtls-rprx-splice"
|
|
|
o:depends("xtls", true)
|
|
@@ -453,24 +492,30 @@ cert_dir = "/etc/ssl/private/"
|
|
|
local path
|
|
|
|
|
|
luci.http.setfilehandler(function(meta, chunk, eof)
|
|
|
-if not fd then
|
|
|
-if (not meta) or (not meta.name) or (not meta.file) then return end
|
|
|
-fd = nixio.open(cert_dir .. meta.file, "w")
|
|
|
-if not fd then
|
|
|
-path = translate("Create upload file error.")
|
|
|
-return
|
|
|
-end
|
|
|
-end
|
|
|
-if chunk and fd then fd:write(chunk) end
|
|
|
-if eof and fd then
|
|
|
-fd:close()
|
|
|
-fd = nil
|
|
|
-path = '/etc/ssl/private/' .. meta.file .. ''
|
|
|
-end
|
|
|
+ if not fd then
|
|
|
+ if (not meta) or (not meta.name) or (not meta.file) then
|
|
|
+ return
|
|
|
+ end
|
|
|
+ fd = nixio.open(cert_dir .. meta.file, "w")
|
|
|
+ if not fd then
|
|
|
+ path = translate("Create upload file error.")
|
|
|
+ return
|
|
|
+ end
|
|
|
+ end
|
|
|
+ if chunk and fd then
|
|
|
+ fd:write(chunk)
|
|
|
+ end
|
|
|
+ if eof and fd then
|
|
|
+ fd:close()
|
|
|
+ fd = nil
|
|
|
+ path = '/etc/ssl/private/' .. meta.file .. ''
|
|
|
+ end
|
|
|
end)
|
|
|
if luci.http.formvalue("upload") then
|
|
|
-local f = luci.http.formvalue("ulfile")
|
|
|
-if #f <= 0 then path = translate("No specify upload file.") end
|
|
|
+ local f = luci.http.formvalue("ulfile")
|
|
|
+ if #f <= 0 then
|
|
|
+ path = translate("No specify upload file.")
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
o = s:option(Value, "certpath", translate("Current Certificate Path"))
|
|
@@ -496,40 +541,40 @@ o.default = 1234
|
|
|
o.rmempty = false
|
|
|
|
|
|
if nixio.fs.access("/usr/bin/kcptun-client") then
|
|
|
-kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
|
|
|
-kcp_enable.rmempty = true
|
|
|
-kcp_enable.default = "0"
|
|
|
-kcp_enable:depends("type", "ssr")
|
|
|
-kcp_enable:depends("type", "ss")
|
|
|
-
|
|
|
-o = s:option(Value, "kcp_port", translate("KcpTun Port"))
|
|
|
-o.datatype = "port"
|
|
|
-o.default = 4000
|
|
|
-function o.validate(self, value, section)
|
|
|
-local kcp_file = "/usr/bin/kcptun-client"
|
|
|
-local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
|
|
|
-if enable == kcp_enable.enabled then
|
|
|
-if not nixio.fs.access(kcp_file) then
|
|
|
-return nil, translate("Haven't a Kcptun executable file")
|
|
|
-elseif not isKcptun(kcp_file) then
|
|
|
-return nil, translate("Not a Kcptun executable file")
|
|
|
-end
|
|
|
-end
|
|
|
-
|
|
|
-return value
|
|
|
-end
|
|
|
-o:depends("type", "ssr")
|
|
|
-o:depends("type", "ss")
|
|
|
-
|
|
|
-o = s:option(Value, "kcp_password", translate("KcpTun Password"))
|
|
|
-o.password = true
|
|
|
-o:depends("type", "ssr")
|
|
|
-o:depends("type", "ss")
|
|
|
-
|
|
|
-o = s:option(Value, "kcp_param", translate("KcpTun Param"))
|
|
|
-o.default = "--nocomp"
|
|
|
-o:depends("type", "ssr")
|
|
|
-o:depends("type", "ss")
|
|
|
+ kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
|
|
|
+ kcp_enable.rmempty = true
|
|
|
+ kcp_enable.default = "0"
|
|
|
+ kcp_enable:depends("type", "ssr")
|
|
|
+ kcp_enable:depends("type", "ss")
|
|
|
+
|
|
|
+ o = s:option(Value, "kcp_port", translate("KcpTun Port"))
|
|
|
+ o.datatype = "port"
|
|
|
+ o.default = 4000
|
|
|
+ function o.validate(self, value, section)
|
|
|
+ local kcp_file = "/usr/bin/kcptun-client"
|
|
|
+ local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
|
|
|
+ if enable == kcp_enable.enabled then
|
|
|
+ if not nixio.fs.access(kcp_file) then
|
|
|
+ return nil, translate("Haven't a Kcptun executable file")
|
|
|
+ elseif not isKcptun(kcp_file) then
|
|
|
+ return nil, translate("Not a Kcptun executable file")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ return value
|
|
|
+ end
|
|
|
+ o:depends("type", "ssr")
|
|
|
+ o:depends("type", "ss")
|
|
|
+
|
|
|
+ o = s:option(Value, "kcp_password", translate("KcpTun Password"))
|
|
|
+ o.password = true
|
|
|
+ o:depends("type", "ssr")
|
|
|
+ o:depends("type", "ss")
|
|
|
+
|
|
|
+ o = s:option(Value, "kcp_param", translate("KcpTun Param"))
|
|
|
+ o.default = "--nocomp"
|
|
|
+ o:depends("type", "ssr")
|
|
|
+ o:depends("type", "ss")
|
|
|
end
|
|
|
|
|
|
return m
|