From 015810919d1a73c6c72bae3b52254a1317581eb6 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sun, 12 May 2019 23:36:11 +0800 Subject: [PATCH] luci: add v2ray server luci --- package/lean/luci-app-v2ray-server/Makefile | 18 + .../luasrc/controller/v2ray_server.lua | 47 +++ .../cbi/v2ray_server/api/genv2rayconfig.lua | 65 ++++ .../model/cbi/v2ray_server/api/v2ray.lua | 321 ++++++++++++++++++ .../luasrc/model/cbi/v2ray_server/config.lua | 110 ++++++ .../luasrc/model/cbi/v2ray_server/index.lua | 57 ++++ .../view/v2ray_server/users_list_status.htm | 28 ++ .../luasrc/view/v2ray_server/users_status.htm | 3 + .../luasrc/view/v2ray_server/v2ray.htm | 188 ++++++++++ .../po/zh-cn/v2ray_server.po | 53 +++ .../root/etc/config/v2ray_server | 15 + .../root/etc/init.d/v2ray_server | 48 +++ .../etc/uci-defaults/luci-app-v2ray-server | 21 ++ .../usr/share/v2ray_server/firewall.include | 25 ++ 14 files changed, 999 insertions(+) create mode 100644 package/lean/luci-app-v2ray-server/Makefile create mode 100644 package/lean/luci-app-v2ray-server/luasrc/controller/v2ray_server.lua create mode 100644 package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/genv2rayconfig.lua create mode 100644 package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/v2ray.lua create mode 100644 package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/config.lua create mode 100644 package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/index.lua create mode 100644 package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_list_status.htm create mode 100644 package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_status.htm create mode 100644 package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/v2ray.htm create mode 100644 package/lean/luci-app-v2ray-server/po/zh-cn/v2ray_server.po create mode 100644 package/lean/luci-app-v2ray-server/root/etc/config/v2ray_server create mode 100644 package/lean/luci-app-v2ray-server/root/etc/init.d/v2ray_server create mode 100644 package/lean/luci-app-v2ray-server/root/etc/uci-defaults/luci-app-v2ray-server create mode 100644 package/lean/luci-app-v2ray-server/root/usr/share/v2ray_server/firewall.include diff --git a/package/lean/luci-app-v2ray-server/Makefile b/package/lean/luci-app-v2ray-server/Makefile new file mode 100644 index 0000000000..f6d2d6fe91 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/Makefile @@ -0,0 +1,18 @@ +# Copyright (C) 2018-2019 Lienol +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for V2ray Server +LUCI_DEPENDS:=+libsodium +luci-lib-jsonc +v2ray +LUCI_PKGARCH:=all +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature + + diff --git a/package/lean/luci-app-v2ray-server/luasrc/controller/v2ray_server.lua b/package/lean/luci-app-v2ray-server/luasrc/controller/v2ray_server.lua new file mode 100644 index 0000000000..5ca8c3d279 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/controller/v2ray_server.lua @@ -0,0 +1,47 @@ +module("luci.controller.v2ray_server",package.seeall) +local http = require "luci.http" +local v2ray = require "luci.model.cbi.v2ray_server.api.v2ray" + +function index() + if not nixio.fs.access("/etc/config/v2ray_server")then + return + end + entry({"admin","vpn"}, firstchild(), "VPN", 45).dependent = false + entry({"admin","vpn","v2ray_server"},cbi("v2ray_server/index"),_("V2ray Server"),3).dependent=true + entry({"admin","vpn","v2ray_server","config"},cbi("v2ray_server/config")).leaf=true + + entry({"admin","vpn","v2ray_server","users_status"},call("v2ray_users_status")).leaf=true + entry({"admin", "vpn", "v2ray_server", "check"}, call("v2ray_check")).leaf = true + entry({"admin", "vpn", "v2ray_server", "update"}, call("v2ray_update")).leaf = true +end + +local function http_write_json(content) + http.prepare_content("application/json") + http.write_json(content or { code = 1 }) +end + +function v2ray_users_status() + local e={} + e.index=luci.http.formvalue("index") + e.status=luci.sys.call("ps -w| grep -v grep | grep '/var/etc/v2ray_server/" .. luci.http.formvalue("id") .. "' >/dev/null")==0 + http_write_json(e) +end + +function v2ray_check() + local json = v2ray.to_check("") + http_write_json(json) +end + +function v2ray_update() + local json = nil + local task = http.formvalue("task") + if task == "extract" then + json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix")) + elseif task == "move" then + json = v2ray.to_move(http.formvalue("file")) + else + json = v2ray.to_download(http.formvalue("url")) + end + + http_write_json(json) +end \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/genv2rayconfig.lua b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/genv2rayconfig.lua new file mode 100644 index 0000000000..f1d44a0447 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/genv2rayconfig.lua @@ -0,0 +1,65 @@ +local ucursor = require "luci.model.uci".cursor() +local json = require "luci.jsonc" +local server_section = arg[1] +local server = ucursor:get_all("v2ray_server", server_section) + +local v2ray = { + log = { + --error = "/var/log/v2ray.log", + loglevel = "warning" + }, + -- 传入连接 + inbound = { + port = tonumber(server.port), + protocol = server.protocol, + settings = { + clients = { + { + id = server.VMess_id, + alterId = tonumber(server.VMess_alterId), + level = tonumber(server.VMess_level) + } + } + }, + -- 底层传输配置 + streamSettings = { + network = server.transport, + security = (server.tls == '1') and "tls" or "none", + kcpSettings = (server.transport == "mkcp") and { + mtu = tonumber(server.mkcp_mtu), + tti = tonumber(server.mkcp_tti), + uplinkCapacity = tonumber(server.mkcp_uplinkCapacity), + downlinkCapacity = tonumber(server.mkcp_downlinkCapacity), + congestion = (server.mkcp_congestion == "1") and true or false, + readBufferSize = tonumber(server.mkcp_readBufferSize), + writeBufferSize = tonumber(server.mkcp_writeBufferSize), + header = { + type = server.mkcp_guise + } + } or nil, + httpSettings = (server.transport == "h2") and { + path = server.h2_path, + host = server.h2_host, + } or nil, + quicSettings = (server.transport == "quic") and { + security = server.quic_security, + key = server.quic_key, + header = { + type = server.quic_guise + } + } or nil + } + }, + -- 传出连接 + outbound = { + protocol = "freedom" + }, + -- 额外传出连接 + outboundDetour = { + { + protocol = "blackhole", + tag = "blocked" + } + } +} +print(json.stringify(v2ray,1)) \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/v2ray.lua b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/v2ray.lua new file mode 100644 index 0000000000..d7500b4584 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/v2ray.lua @@ -0,0 +1,321 @@ +-- Copyright 2018 Lienol +-- Licensed to the public under the Apache License 2.0. + +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() +local util = require "luci.util" +local i18n = require "luci.i18n" + +module("luci.model.cbi.v2ray_server.api.v2ray", package.seeall) + +local v2ray_api = "https://api.github.com/repos/v2ray/v2ray-core/releases/latest" + +local wget = "/usr/bin/wget" +local wget_args = { "--no-check-certificate", "--quiet", "--timeout=10", "--tries=2" } +local curl = "/usr/bin/curl" +local command_timeout = 40 + +local function _unpack(t, i) + i = i or 1 + if t[i] ~= nil then + return t[i], _unpack(t, i + 1) + end +end + +local function exec(cmd, args, writer, timeout) + local os = require "os" + local nixio = require "nixio" + + local fdi, fdo = nixio.pipe() + local pid = nixio.fork() + + if pid > 0 then + fdo:close() + + if writer or timeout then + local starttime = os.time() + while true do + if timeout and os.difftime(os.time(), starttime) >= timeout then + nixio.kill(pid, nixio.const.SIGTERM) + return 1 + end + + if writer then + local buffer = fdi:read(2048) + if buffer and #buffer > 0 then + writer(buffer) + end + end + + local wpid, stat, code = nixio.waitpid(pid, "nohang") + + if wpid and stat == "exited" then + return code + end + + if not writer and timeout then + nixio.nanosleep(1) + end + end + else + local wpid, stat, code = nixio.waitpid(pid) + return wpid and stat == "exited" and code + end + elseif pid == 0 then + nixio.dup(fdo, nixio.stdout) + fdi:close() + fdo:close() + nixio.exece(cmd, args, nil) + nixio.stdout:close() + os.exit(1) + end +end + +local function compare_versions(ver1, comp, ver2) + local table = table + + local av1 = util.split(ver1, "[%.%-]", nil, true) + local av2 = util.split(ver2, "[%.%-]", nil, true) + + local max = table.getn(av1) + local n2 = table.getn(av2) + if (max < n2) then + max = n2 + end + + for i = 1, max, 1 do + local s1 = av1[i] or "" + local s2 = av2[i] or "" + + if comp == "~=" and (s1 ~= s2) then return true end + if (comp == "<" or comp == "<=") and (s1 < s2) then return true end + if (comp == ">" or comp == ">=") and (s1 > s2) then return true end + if (s1 ~= s2) then return false end + end + + return not (comp == "<" or comp == ">") +end + +local function auto_get_arch() + local arch = nixio.uname().machine or "" + + if arch == "mips" then + if fs.access("/usr/lib/os-release") then + arch = sys.exec("grep 'LEDE_BOARD' /usr/lib/os-release | grep -oE 'ramips|ar71xx'") + elseif fs.access("/etc/openwrt_release") then + arch = sys.exec("grep 'DISTRIB_TARGET' /etc/openwrt_release | grep -oE 'ramips|ar71xx'") + end + end + + return util.trim(arch) +end + +local function get_file_info(arch) + local file_tree = "" + local sub_version = "" + + if arch == "x86_64" then + file_tree = "64" + elseif arch == "ramips" then + file_tree = "mipsle" + elseif arch == "ar71xx" then + file_tree = "mips" + elseif arch:match("^i[%d]86$") then + file_tree = "32" + elseif arch:match("^armv[5-8]") then + file_tree = "arm" + sub_version = arch:match("[5-8]") + end + + return file_tree, sub_version +end + +local function get_api_json(url) + local jsonc = require "luci.jsonc" + + local output = { } + --exec(wget, { "-O-", url, _unpack(wget_args) }, + -- function(chunk) output[#output + 1] = chunk end) + --local json_content = util.trim(table.concat(output)) + + local json_content = luci.sys.exec(curl.." -sL "..url) + + if json_content == "" then + return { } + end + + return jsonc.parse(json_content) or { } +end + +function get_config_option(option, default) + return uci:get("v2ray", "general", option) or default +end + +function get_current_log_file(type) + local log_folder = get_config_option("log_folder", "/var/log/v2ray") + return "%s/%s.%s.log" % { log_folder, type, "general" } +end + +function is_running(client) + if client and client ~= "" then + local file_name = client:match(".*/([^/]+)$") or "" + if file_name ~= "" then + return sys.call("pidof %s >/dev/null" % file_name) == 0 + end + end + + return false +end + +function get_v2ray_version() + return luci.sys.exec("/usr/bin/v2ray/v2ray -version | awk '{print $2}' | sed -n 1P") +end + +function to_check(arch) + if not arch or arch == "" then + arch = auto_get_arch() + end + + local file_tree, sub_version = get_file_info(arch) + + if file_tree == "" then + return { + code = 1, + error = i18n.translate("Can't determine ARCH, or ARCH not supported. Please select manually.") + } + end + + local json = get_api_json(v2ray_api) + + if json.tag_name == nil then + return { + code = 1, + error = i18n.translate("Get remote version info failed.") + } + end + + local remote_version = json.tag_name:match("[^v]+") + local needs_update = compare_versions(get_v2ray_version(), "<", remote_version) + local html_url, download_url + + if needs_update then + html_url = json.html_url + for _, v in ipairs(json.assets) do + if v.name and v.name:match("linux%-" .. file_tree) then + download_url = v.browser_download_url + break + end + end + end + + if needs_update and not download_url then + return { + code = 1, + version = remote_version, + html_url = html_url, + type = file_tree .. sub_version, + error = i18n.translate("New version found, but failed to get new version download url.") + } + end + + return { + code = 0, + update = needs_update, + version = remote_version, + url = { + html = html_url, + download = download_url + }, + type = file_tree .. sub_version + } +end + +function to_download(url) + if not url or url == "" then + return { + code = 1, + error = i18n.translate("Download url is required.") + } + end + + sys.call("/bin/rm -f /tmp/v2ray_download.*") + + local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_download.XXXXXX")) + + local result = exec(wget, { + "-O", tmp_file, url, _unpack(wget_args) }, nil, command_timeout) == 0 + + if not result then + exec("/bin/rm", { "-f", tmp_file }) + return { + code = 1, + error = i18n.translatef("File download failed or timed out: %s", url) + } + end + + return { + code = 0, + file = tmp_file + } +end + +function to_extract(file, subfix) + local isinstall_unzip=sys.call("opkg list-installed | grep unzip > /dev/null")==0 + if not isinstall_unzip then + sys.call("opkg update && opkg install unzip > /dev/null") + end + + if not file or file == "" or not fs.access(file) then + return { + code = 1, + error = i18n.translate("File path required.") + } + end + + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_extract.XXXXXX")) + + local output = { } + exec("/usr/bin/unzip", { "-o", file , "-d", tmp_dir }, + function(chunk) output[#output + 1] = chunk end) + + local files = util.split(table.concat(output)) + + exec("/bin/rm", { "-f", file }) + + return { + code = 0, + file = tmp_dir + } +end + +function to_move(file) + if not file or file == "" then + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + return { + code = 1, + error = i18n.translate("Client file is required.") + } + end + + local client_file = "/usr/bin/v2ray" + + sys.call("mkdir -p "..client_file) + + local result = exec("/bin/mv", { "-f", file.."/v2ray", file.."/v2ctl", client_file }, nil, command_timeout) == 0 + + if not result or not fs.access(client_file) then + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + return { + code = 1, + error = i18n.translatef("Can't move new file to path: %s", client_file) + } + end + + exec("/bin/chmod", { "-R", "755", client_file }) + + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + + return { code = 0 } +end diff --git a/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/config.lua b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/config.lua new file mode 100644 index 0000000000..8b826b96d1 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/config.lua @@ -0,0 +1,110 @@ +local i = "v2ray_server" +local d = require "luci.dispatcher" +local a,t,e + +local header_type={ +"none", +"srtp", +"utp", +"wechat-video", +"dtls", +"wireguard", +} + +a=Map(i,"V2ray "..translate("Server Config")) +a.redirect=d.build_url("admin","vpn","v2ray_server") + +t=a:section(NamedSection,arg[1],"user","") +t.addremove=false +t.dynamic=false + +e=t:option(Flag, "enable", translate("Enable")) +e.default = "1" +e.rmempty = false + +e=t:option(Value,"remarks",translate("Remarks")) +e.default=translate("Remarks") +e.rmempty=false + +e=t:option(Value,"port",translate("Port")) +e.datatype="port" +e.rmempty=false + +e=t:option(ListValue,"protocol",translate("Protocol")) +e:value("vmess",translate("Vmess")) + +e=t:option(Value,"VMess_id",translate("ID")) +e.default = luci.sys.exec("cat /proc/sys/kernel/random/uuid") +e.rmempty=false +e:depends("protocol","vmess") + +e=t:option(Value,"VMess_alterId",translate("Alter ID")) +e.default=16 +e.rmempty=false +e:depends("protocol","vmess") + +e=t:option(Value,"VMess_level",translate("User Level")) +e.default=1 + +e=t:option(ListValue,"transport",translate("Transport")) +e:value("tcp","TCP") +e:value("mkcp", "mKCP") +e:value("quic", "QUIC") + +-- [[ TCP部分 ]]-- + +-- TCP伪装 +e = t:option(ListValue, "tcp_guise", translate("Camouflage Type")) +e:depends("transport", "tcp") +e:value("none", "none") +e:value("http", "http") + +-- HTTP域名 +e = t:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) +e:depends("tcp_guise", "http") + +-- HTTP路径 +e = t:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) +e:depends("tcp_guise", "http") + +-- [[ mKCP部分 ]]-- +e=t:option(ListValue,"mkcp_guise",translate("Camouflage Type")) +for a,t in ipairs(header_type)do e:value(t)end +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_mtu",translate("KCP MTU")) +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_tti",translate("KCP TTI")) +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_uplinkCapacity",translate("KCP uplinkCapacity")) +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_downlinkCapacity",translate("KCP downlinkCapacity")) +e:depends("transport","mkcp") + +e=t:option(Flag,"mkcp_congestion",translate("KCP Congestion")) +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_readBufferSize",translate("KCP readBufferSize")) +e:depends("transport","mkcp") + +e=t:option(Value,"mkcp_writeBufferSize",translate("KCP writeBufferSize")) +e:depends("transport","mkcp") + +-- [[ QUIC部分 ]]-- +e=t:option(ListValue,"quic_security",translate("Encrypt Method")) +e:value("none") +e:value("aes-128-gcm") +e:value("chacha20-poly1305") +e:depends("transport","quic") + +e=t:option(Value,"quic_key",translate("Encrypt Method")..translate("Key")) +e:depends("transport","quic") + +e=t:option(ListValue,"quic_guise",translate("Camouflage Type")) +for a,t in ipairs(header_type)do e:value(t)end +e:depends("transport","quic") + +return a diff --git a/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/index.lua b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/index.lua new file mode 100644 index 0000000000..be1682a772 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/index.lua @@ -0,0 +1,57 @@ +local o = require "luci.dispatcher" +local fs = require "nixio.fs" +local sys = require "luci.sys" +local cursor = luci.model.uci.cursor() +local appname = "v2ray_server" +local a,t,e + +a=Map(appname, translate("V2ray Server")) + +t=a:section(TypedSection,"global",translate("Global Settings")) +t.anonymous=true +t.addremove=false + +e=t:option(Flag,"enable",translate("Enable")) +e.rmempty=false + +t:append(Template("v2ray_server/v2ray")) + +t=a:section(TypedSection,"user",translate("Users Manager")) +t.anonymous=true +t.addremove=true +t.template="cbi/tblsection" +t.extedit=o.build_url("admin","vpn",appname,"config","%s") +function t.create(e,t) + local e=TypedSection.create(e,t) + luci.http.redirect(o.build_url("admin","vpn",appname,"config",e)) +end + +function t.remove(t,a) + t.map.proceed=true + t.map:del(a) + luci.http.redirect(o.build_url("admin","vpn",appname)) +end + +e=t:option(Flag, "enable", translate("Enable")) +e.width="5%" +e.rmempty = false + +e=t:option(DummyValue,"status",translate("Status")) +e.template="v2ray_server/users_status" +e.value=translate("Collecting data...") + +e=t:option(DummyValue,"remarks",translate("Remarks")) +e.width="15%" + +e=t:option(DummyValue,"port",translate("Port")) +e.width="10%" + +e=t:option(DummyValue,"protocol",translate("Protocol")) +e.width="15%" + +e=t:option(DummyValue,"VMess_id",translate("ID")) +e.width="35%" + +a:append(Template("v2ray_server/users_list_status")) + +return a diff --git a/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_list_status.htm b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_list_status.htm new file mode 100644 index 0000000000..d02ca6157d --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_list_status.htm @@ -0,0 +1,28 @@ +<%# + Copyright 2018 Lienol + Licensed to the public under the Apache License 2.0. +-%> + +<% +local dsp = require "luci.dispatcher" +-%> + + \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_status.htm b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_status.htm new file mode 100644 index 0000000000..40c2e3c58c --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/users_status.htm @@ -0,0 +1,3 @@ +<%+cbi/valueheader%> +-- +<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/v2ray.htm b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/v2ray.htm new file mode 100644 index 0000000000..7208bf7f5f --- /dev/null +++ b/package/lean/luci-app-v2ray-server/luasrc/view/v2ray_server/v2ray.htm @@ -0,0 +1,188 @@ +<%# + Copyright 2018 + Licensed to the public under the Apache License 2.0. +-%> + +<% +local v2ray_version=luci.sys.exec("/usr/bin/v2ray/v2ray -version | awk '{print $2}' | sed -n 1P") +local dsp = require "luci.dispatcher" +-%> + + + +
+ +
+
+ + 【 <%=v2ray_version%>】 + + +
+
+
\ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/po/zh-cn/v2ray_server.po b/package/lean/luci-app-v2ray-server/po/zh-cn/v2ray_server.po new file mode 100644 index 0000000000..c5db9b349f --- /dev/null +++ b/package/lean/luci-app-v2ray-server/po/zh-cn/v2ray_server.po @@ -0,0 +1,53 @@ +msgid "V2ray Server" +msgstr "V2ray 服务器" + +msgid "Global Settings" +msgstr "全局设置" + +msgid "Server Config" +msgstr "服务器配置" + +msgid "Users Manager" +msgstr "用户管理" + +msgid "Remarks" +msgstr "备注" + +msgid "Port" +msgstr "端口" + +msgid "Password" +msgstr "密码" + +msgid "Protocol" +msgstr "协议" + +msgid "Null" +msgstr "无" + +msgid "Alter ID" +msgstr "额外ID(AlterID)" + +msgid "User Level" +msgstr "用户等级(Level)" + +msgid "Transport" +msgstr "传输方式" + +msgid "Camouflage Type" +msgstr "伪装类型" + +msgid "Enabled" +msgstr "启用" + +msgid "Status" +msgstr "状态" + +msgid "Current Condition" +msgstr "当前状态" + +msgid "NOT RUNNING" +msgstr "未运行" + +msgid "RUNNING" +msgstr "运行中" \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/root/etc/config/v2ray_server b/package/lean/luci-app-v2ray-server/root/etc/config/v2ray_server new file mode 100644 index 0000000000..cab9eeb88e --- /dev/null +++ b/package/lean/luci-app-v2ray-server/root/etc/config/v2ray_server @@ -0,0 +1,15 @@ + +config global + option enable '0' + +config user + option enable '1' + option remarks '备注222' + option protocol 'vmess' + option VMess_id 'fd00927a-b0c2-4629-aef7-d9ff15a9d722' + option VMess_alterId '16' + option VMess_level '1' + option transport 'tcp' + option tcp_guise 'none' + option port '12366' + diff --git a/package/lean/luci-app-v2ray-server/root/etc/init.d/v2ray_server b/package/lean/luci-app-v2ray-server/root/etc/init.d/v2ray_server new file mode 100644 index 0000000000..1d9f14fb96 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/root/etc/init.d/v2ray_server @@ -0,0 +1,48 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2018-2019 Lienol + +START=99 + +CONFIG=v2ray_server +CONFIG_PATH=/var/etc/$CONFIG + +gen_v2ray_config_file() { + config_get enable $1 enable + [ "$enable" = "0" ] && return 0 + config_get remarks $1 remarks + config_get port $1 port + lua /usr/lib/lua/luci/model/cbi/v2ray_server/api/genv2rayconfig.lua $1 > $CONFIG_PATH/$1.json + /usr/bin/v2ray/v2ray -config $CONFIG_PATH/$1.json >/dev/null 2>&1 & +} + +start_v2ray_server() { + config_foreach gen_v2ray_config_file "user" + fw3 reload +} + +stop_v2ray_server() { + fw3 reload + ps -w | grep "$CONFIG_PATH/" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & +} + +start() { + config_load $CONFIG + enable=$(uci get $CONFIG.@global[0].enable) + if [ "$enable" = "0" ];then + stop_v2ray_server + else + mkdir -p $CONFIG_PATH + start_v2ray_server + fi +} + +stop() { + stop_v2ray_server + rm -rf $CONFIG_PATH +} + +restart() { + stop + sleep 1 + start +} \ No newline at end of file diff --git a/package/lean/luci-app-v2ray-server/root/etc/uci-defaults/luci-app-v2ray-server b/package/lean/luci-app-v2ray-server/root/etc/uci-defaults/luci-app-v2ray-server new file mode 100644 index 0000000000..364f7db225 --- /dev/null +++ b/package/lean/luci-app-v2ray-server/root/etc/uci-defaults/luci-app-v2ray-server @@ -0,0 +1,21 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete firewall.v2ray_server + set firewall.v2ray_server=include + set firewall.v2ray_server.type=script + set firewall.v2ray_server.path=/usr/share/v2ray_server/firewall.include + set firewall.v2ray_server.reload=1 +EOF + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@v2ray_server[-1] + add ucitrack v2ray_server + set ucitrack.@v2ray_server[-1].init=v2ray_server + commit ucitrack +EOF + +chmod a+x /usr/share/v2ray_server/* >/dev/null 2>&1 + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/package/lean/luci-app-v2ray-server/root/usr/share/v2ray_server/firewall.include b/package/lean/luci-app-v2ray-server/root/usr/share/v2ray_server/firewall.include new file mode 100644 index 0000000000..1f06a00b6f --- /dev/null +++ b/package/lean/luci-app-v2ray-server/root/usr/share/v2ray_server/firewall.include @@ -0,0 +1,25 @@ +#!/bin/sh + +. $IPKG_INSTROOT/lib/functions.sh +. $IPKG_INSTROOT/lib/functions/service.sh + +gen_user_iptables() { + config_get enable $1 enable + [ "$enable" = "0" ] && return 0 + config_get remarks $1 remarks + config_get port $1 port + iptables -A V2RAY-SERVER -p tcp --dport $port -m comment --comment "$remarks" -j ACCEPT + iptables -A V2RAY-SERVER -p udp --dport $port -m comment --comment "$remarks" -j ACCEPT +} + +iptables -F V2RAY-SERVER 2>/dev/null +iptables -D INPUT -j V2RAY-SERVER 2>/dev/null +iptables -X V2RAY-SERVER 2>/dev/null + +enable=$(uci get v2ray_server.@global[0].enable) +if [ $enable -eq 1 ]; then + iptables -N V2RAY-SERVER + iptables -I INPUT -j V2RAY-SERVER + config_load v2ray_server + config_foreach gen_user_iptables "user" +fi \ No newline at end of file