mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-01 09:53:56 +08:00
update 2026-05-10 09:48:30
This commit is contained in:
1 parent
95ac96413e
commit
0b362674f1
6244 files changed
+2992248
No files matched your search
@@ -0,0 +1,35 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2025 LunaticKochiya<125438787@qq.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
module("luci.controller.openvpn-server", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/openvpn") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "services", "openvpn-server"},firstchild(), _("OpenVPN Server"), 1).dependent = true
|
||||
|
||||
entry({"admin", "services", "openvpn-server", "general"}, cbi("openvpn-server/openvpn-server"), _("OpenVPN Server"), 1).leaf = true
|
||||
entry({"admin", "services", "openvpn-server", "client"},cbi("openvpn-server/openvpn-server_ovpn"), _("Client"), 2).leaf = true
|
||||
entry({"admin", "services", "openvpn-server", "log"},form("openvpn-server/openvpn-server_run_log"), _("Running log"), 3).leaf = true
|
||||
|
||||
entry({"admin", "services", "openvpn-server","status"},call("act_status")).leaf=true
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e={}
|
||||
e.running=luci.sys.call("pgrep openvpn >/dev/null")==0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2025 LunaticKochiya<125438787@qq.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
--require("luci.tools.webadmin")
|
||||
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local sys = require "luci.sys"
|
||||
|
||||
local function get_openvpn_info()
|
||||
local version_str = sys.exec("openvpn --version 2>/dev/null | head -n1")
|
||||
local full_output = sys.exec("openvpn --version 2>/dev/null")
|
||||
|
||||
local major, minor, patch = version_str:match("OpenVPN%s+(%d+)%.(%d+)%.(%d+)")
|
||||
if not (major and minor and patch) then
|
||||
return nil, nil, nil, false
|
||||
end
|
||||
|
||||
local lzo_supported = full_output:match("%[LZO%]") ~= nil
|
||||
|
||||
return tonumber(major), tonumber(minor), tonumber(patch), lzo_supported
|
||||
end
|
||||
|
||||
local major, minor, patch, lzo = get_openvpn_info()
|
||||
|
||||
mp = Map("openvpn", "OpenVPN Server",translate("An easy config OpenVPN Server Web-UI"))
|
||||
|
||||
mp:section(SimpleSection).template = "openvpn/openvpn_status"
|
||||
|
||||
s = mp:section(TypedSection, "openvpn")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
|
||||
s.filter = function(self, section)
|
||||
return section:match("^myvpn") ~= nil
|
||||
end
|
||||
|
||||
s:tab("basic", translate("Base Setting"))
|
||||
|
||||
o = s:taboption("basic", Flag, "enabled", translate("Enable"))
|
||||
|
||||
port = s:taboption("basic", Value, "port", translate("Port"))
|
||||
port.datatype = "range(1,65535)"
|
||||
|
||||
ddns = s:taboption("basic", Value, "ddns", translate("WAN DDNS or IP"))
|
||||
ddns.datatype = "string"
|
||||
ddns.default = "exmple.com"
|
||||
ddns.rmempty = false
|
||||
|
||||
localnet = s:taboption("basic", Value, "server", translate("Client Network"))
|
||||
localnet.datatype = "string"
|
||||
localnet.description = translate("VPN Client Network IP with subnet")
|
||||
|
||||
proto = s:taboption("basic",Value,"proto", translate("proto"))
|
||||
proto.datatype = "string"
|
||||
proto:value("tcp4")
|
||||
proto:value("udp4")
|
||||
proto:value("tcp6")
|
||||
proto:value("udp6")
|
||||
proto.default ="tcp4"
|
||||
|
||||
if (major > 2) or (major == 2 and minor >= 6) then
|
||||
disable_dco = s:taboption("basic",Flag,"disable_dco", translate("disable dco"))
|
||||
disable_dco.description = translate("Disabling DCO provides better compatibility but disables acceleration.")
|
||||
end
|
||||
|
||||
if (major > 2) or (major == 2 and minor >= 5) then
|
||||
allow_compression = s:taboption("basic",Value,"allow_compression", translate("Allow Compression"))
|
||||
allow_compression.datatype = "string"
|
||||
allow_compression:value("asym")
|
||||
allow_compression:value("yes")
|
||||
allow_compression:value("no")
|
||||
allow_compression.default="asym"
|
||||
allow_compression.description = translate("Allow compression, DCO can only be used when set to NO. asym is compatible mode.")
|
||||
|
||||
push_peer_info = s:taboption("basic",Flag,"push_peer_info", translate("push peer info"))
|
||||
push_peer_info.description = translate("This will allow the server to know more info about the client like HWADDR, very useful for managing IoT devices.")
|
||||
|
||||
end
|
||||
|
||||
if lzo then
|
||||
comp_lzo = s:taboption("basic",Value,"comp_lzo", translate("comp_lzo"))
|
||||
comp_lzo.datatype = "string"
|
||||
comp_lzo:value("adaptive")
|
||||
comp_lzo:value("yes")
|
||||
comp_lzo:value("no")
|
||||
if (major > 2) or (major == 2 and minor >= 5) then
|
||||
comp_lzo:depends("allow_compression", "yes")
|
||||
comp_lzo:depends("allow_compression", "asym")
|
||||
comp_lzo:depends("comp_lzo", "yes")
|
||||
comp_lzo:depends("comp_lzo", "adaptive")
|
||||
comp_lzo.default="adaptive"
|
||||
else
|
||||
comp_lzo:depends("comp_lzo", "yes")
|
||||
comp_lzo:depends("comp_lzo", "adaptive")
|
||||
comp_lzo.default="adaptive"
|
||||
end
|
||||
comp_lzo.description = translate("Using LZO compression, it does not support versions above 2.5.X, does not support DCO; if your version number is greater than this version, select NO to disable it.")
|
||||
end
|
||||
|
||||
auth_user_pass_verify = s:taboption("basic",Value,"auth_user_pass_verify", translate("user password verify"))
|
||||
auth_user_pass_verify.datatype = "string"
|
||||
auth_user_pass_verify.description = translate("Default: /etc/openvpn/server/checkpsw.sh via-env, leave it empty to disable")
|
||||
|
||||
script_security = s:taboption("basic",Value,"script_security", translate("script_security: to use with user and password"))
|
||||
script_security.datatype = "range(1,3)"
|
||||
script_security:value("1")
|
||||
script_security:value("2")
|
||||
script_security:value("3")
|
||||
script_security.description = translate("Default 3, leave it empty to disable")
|
||||
|
||||
duplicate_cn = s:taboption("basic",Flag,"duplicate_cn", translate("duplicate_cn"))
|
||||
duplicate_cn.description = translate("This option allows multiple clients to connect using the same certificate and key and assign different IP addresses")
|
||||
client_to_client = s:taboption("basic",Flag,"client_to_client", translate("client-to-client"))
|
||||
client_to_client.description = translate("Allow clients to see each other, otherwise multiple clients can only access the server and cannot connect to each other")
|
||||
username_as_common_name = s:taboption("basic",Flag,"username_as_common_name", translate("username_as_common_name"))
|
||||
username_as_common_name.description = translate("Use the UserName provided by the client as the Common Name")
|
||||
client_cert_not_required = s:taboption("basic",Flag,"client_cert_not_required", translate("client_cert_not_required"))
|
||||
client_cert_not_required.description = translate("After this option is enabled, the client does not need cert and key. If this option is not enabled, cert and key and user password double verification are required.")
|
||||
|
||||
list = s:taboption("basic", DynamicList, "push")
|
||||
list.title = translate("Client Settings")
|
||||
list.datatype = "string"
|
||||
list.description = translate("Set route 192.168.0.0 255.255.255.0 and dhcp-option DNS 192.168.0.1 base on your router")
|
||||
|
||||
|
||||
local o
|
||||
o = s:taboption("basic", Button,"certificate",translate("OpenVPN Client config file"))
|
||||
o.inputtitle = translate("Download .ovpn file")
|
||||
o.description = translate("If you use user password verification only, remember to delete the key and cert.")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
luci.sys.call("sh /etc/genovpn.sh 2>&1 >/dev/null")
|
||||
Download()
|
||||
end
|
||||
|
||||
s:tab("code", translate("Client code"))
|
||||
local conf = "/etc/ovpnadd.conf"
|
||||
local NXFS = require "nixio.fs"
|
||||
o = s:taboption("code", TextValue, "conf")
|
||||
o.description = translate("Here is the code that you want to add to the .ovpn file. If you use user password verification, you need to add auth-user-pass")
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(conf) or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(conf, value:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
s:tab("passwordfile", translate("User and password"))
|
||||
local pass = "/etc/openvpn/server/psw-file"
|
||||
local NXFS = require "nixio.fs"
|
||||
o = s:taboption("passwordfile", TextValue, "pass")
|
||||
o.description = translate("Each line contains a pair of user and password, separated by a space")
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(pass) or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(pass, value:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
s:tab("checkpsw", translate("Authentication script"))
|
||||
local checkpswconf = "/etc/openvpn/server/checkpsw.sh"
|
||||
local NXFS = require "nixio.fs"
|
||||
o = s:taboption("checkpsw", TextValue, "checkpswconf")
|
||||
o.description = translate("Authentication script")
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(checkpswconf) or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(checkpswconf, value:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
local pid = luci.util.exec("/usr/bin/pgrep openvpn")
|
||||
|
||||
function openvpn_process_status()
|
||||
local status = "OpenVPN is not running now "
|
||||
|
||||
if pid ~= "" then
|
||||
status = "OpenVPN is running with the PID " .. pid .. ""
|
||||
end
|
||||
|
||||
local status = { status=status }
|
||||
local table = { pid=status }
|
||||
return table
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Download()
|
||||
local t,e
|
||||
t=nixio.open("/tmp/my.ovpn","r")
|
||||
luci.http.header('Content-Disposition','attachment; filename="my.ovpn"')
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
while true do
|
||||
e=t:read(nixio.const.buffersize)
|
||||
if(not e)or(#e==0)then
|
||||
break
|
||||
else
|
||||
luci.http.write(e)
|
||||
end
|
||||
end
|
||||
t:close()
|
||||
luci.http.close()
|
||||
end
|
||||
|
||||
t = mp:section(Table, openvpn_process_status())
|
||||
t.anonymous = true
|
||||
|
||||
t:option(DummyValue, "status", translate("OpenVPN status"))
|
||||
|
||||
if pid == "" then
|
||||
start = t:option(Button, "_start", translate("Start"))
|
||||
start.inputstyle = "apply"
|
||||
function start.write(self, section)
|
||||
luci.util.exec("uci set openvpn.myvpn.enabled=='1' && uci commit openvpn")
|
||||
message = luci.util.exec("/etc/init.d/openvpn start 2>&1")
|
||||
luci.util.exec("sleep 2")
|
||||
luci.http.redirect(
|
||||
luci.dispatcher.build_url("admin", "services", "openvpn-server") .. "?message=" .. message
|
||||
)
|
||||
end
|
||||
else
|
||||
stop = t:option(Button, "_stop", translate("Stop"))
|
||||
stop.inputstyle = "reset"
|
||||
function stop.write(self, section)
|
||||
luci.util.exec("uci set openvpn.myvpn.enabled=='0' && uci commit openvpn")
|
||||
luci.util.exec("/etc/init.d/openvpn stop")
|
||||
luci.util.exec("sleep 2")
|
||||
luci.http.redirect(
|
||||
luci.dispatcher.build_url("admin", "services", "openvpn-server")
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local comp_lzo_val = uci:get("openvpn", "myvpn", "comp_lzo")
|
||||
|
||||
function mp.on_after_commit(self)
|
||||
os.execute("uci set firewall.openvpn.dest_port=$(uci get openvpn.myvpn.port) && uci commit firewall && /etc/init.d/firewall restart")
|
||||
os.execute("/etc/init.d/openvpn restart")
|
||||
if comp_lzo_val == "no" then
|
||||
uci:delete("openvpn", "myvpn", "comp_lzo")
|
||||
uci:commit("openvpn")
|
||||
end
|
||||
end
|
||||
|
||||
gen = t:option(Button,"cert",translate("OpenVPN Cert"))
|
||||
gen.inputstyle = "apply"
|
||||
function gen.write(self, section)
|
||||
luci.util.exec("/etc/openvpncert.sh")
|
||||
end
|
||||
|
||||
--local apply = luci.http.formvalue("cbi.apply")
|
||||
--if apply then
|
||||
-- os.execute("/etc/init.d/openvpn restart")
|
||||
--end
|
||||
|
||||
return mp
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2025 LunaticKochiya<125438787@qq.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local NXFS = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
|
||||
local base_dir = "/etc/openvpn"
|
||||
|
||||
local function get_config_path(identifier)
|
||||
if identifier and identifier:match("^[a-zA-Z0-9_%-]+$") then
|
||||
return base_dir .. "/" .. identifier .. ".conf"
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
m2 = Map("openvpn", "OpenVPN Client", translate("Configuration for OpenVPN client instances. The instance name you provide becomes the UCI section name (e.g., 'client1' leads to `config openvpn 'client1'`)."))
|
||||
|
||||
m2:section(SimpleSection).template = "openvpn/openvpn_status"
|
||||
|
||||
sl = m2:section(TypedSection, "openvpn", translate("OpenVPN Client Instances"))
|
||||
sl.title = translate("OpenVPN Client Instances")
|
||||
sl.anonymous = false
|
||||
sl.addremove = true
|
||||
sl.description = translate("Enter a unique identifier (e.g., client1, client2) when adding an instance. This identifier is used for the UCI section name and the corresponding .conf file.")
|
||||
sl.sortable = true
|
||||
|
||||
sl.filter = function(self, section)
|
||||
return section:match("^client") ~= nil
|
||||
end
|
||||
|
||||
sl:tab("base", translate("Base Settings"))
|
||||
sl:tab("config_file", translate("Client Config File Content"))
|
||||
|
||||
local o
|
||||
|
||||
o = sl:taboption("base", Flag, "enabled", translate("Enable Instance"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
|
||||
o = sl:taboption("base", Value, "config", translate("Config File Path"))
|
||||
o.readonly = true
|
||||
o.placeholder = translate("Auto-generated based on instance identifier")
|
||||
o.datatype = "file"
|
||||
o.rmempty = false
|
||||
|
||||
o.cfgvalue = function(self, section)
|
||||
return get_config_path(section) or translate("Invalid instance identifier.")
|
||||
end
|
||||
|
||||
o = sl:taboption("config_file", TextValue, "_config_content")
|
||||
o.title = translate("OpenVPN Configuration (.ovpn/.conf)")
|
||||
o.description = translate("Paste the content of the .ovpn or .conf file here. This will be saved to the path shown in 'Base Settings'.")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.rmempty = true
|
||||
|
||||
o.cfgvalue = function(self, section)
|
||||
local conf_file = get_config_path(section)
|
||||
if conf_file then
|
||||
return NXFS.readfile(conf_file) or ""
|
||||
else
|
||||
return "-- " .. translate("Cannot read file: Invalid instance identifier used for this section.") .. " --"
|
||||
end
|
||||
end
|
||||
|
||||
o.write = function(self, section, value)
|
||||
local conf_file = get_config_path(section)
|
||||
if not conf_file then
|
||||
luci.util.perror("OpenVPN: Invalid identifier '" .. tostring(section) .. "', cannot write config file.")
|
||||
return
|
||||
end
|
||||
|
||||
if value and value ~= "" then
|
||||
NXFS.writefile(conf_file, value:gsub("\r\n", "\n"))
|
||||
self.map:set(section, "config", conf_file)
|
||||
else
|
||||
NXFS.remove(conf_file)
|
||||
end
|
||||
end
|
||||
|
||||
o.remove = function(self, section)
|
||||
local conf_file = get_config_path(section)
|
||||
if conf_file then
|
||||
NXFS.remove(conf_file)
|
||||
end
|
||||
end
|
||||
|
||||
sl.on_remove = function(self, section)
|
||||
local conf_file = get_config_path(section)
|
||||
if conf_file then
|
||||
local ok, err = NXFS.remove(conf_file)
|
||||
if ok then
|
||||
luci.util.perror("OpenVPN: Removed config file: " .. conf_file)
|
||||
else
|
||||
luci.util.perror("OpenVPN: Error removing config file " .. conf_file .. ": " .. tostring(err))
|
||||
end
|
||||
end
|
||||
TypedSection.on_remove(self, section)
|
||||
end
|
||||
|
||||
sp = m2:section(TypedSection, "openvpnpassword", translate("OpenVPN Client Authentication"))
|
||||
sp.title = translate("OpenVPN Client Authentication")
|
||||
sp.anonymous = false
|
||||
sp.addremove = true
|
||||
sp.description = translate("Configure authentication files for OpenVPN client instances.")
|
||||
sp.sortable = true
|
||||
|
||||
o = sp:option(Value, "pwdfile", translate("Authentication File Path"))
|
||||
o.placeholder = translate("Enter the path for the authentication file (e.g., /etc/openvpn/password.txt)")
|
||||
o.datatype = "string"
|
||||
o.rmempty = false
|
||||
|
||||
o = sp:option(TextValue, "_auth_content", translate("Authentication File Content"))
|
||||
o.description = translate("Enter the content of the authentication file (e.g., username on the first line, password on the second line). This will be saved to the path shown above.")
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o.rmempty = true
|
||||
|
||||
o.cfgvalue = function(self, section)
|
||||
local pwdfile = self.map:get(section, "pwdfile")
|
||||
if pwdfile then
|
||||
return NXFS.readfile(pwdfile) or ""
|
||||
else
|
||||
return "-- " .. translate("Cannot read file: Invalid instance identifier used for this section.") .. " --"
|
||||
end
|
||||
end
|
||||
|
||||
o.write = function(self, section, value)
|
||||
local pwdfile = self.map:get(section, "pwdfile")
|
||||
if not pwdfile then
|
||||
luci.util.perror("OpenVPN: Invalid identifier '" .. tostring(section) .. "', cannot write authentication file.")
|
||||
return
|
||||
end
|
||||
|
||||
if value and value ~= "" then
|
||||
NXFS.writefile(pwdfile, value:gsub("\r\n", "\n"))
|
||||
else
|
||||
NXFS.remove(pwdfile)
|
||||
end
|
||||
end
|
||||
|
||||
o.remove = function(self, section)
|
||||
local pwdfile = self.map:get(section, "pwdfile")
|
||||
if pwdfile then
|
||||
NXFS.remove(pwdfile)
|
||||
end
|
||||
end
|
||||
|
||||
sp.on_remove = function(self, section)
|
||||
local pwdfile = self.map:get(section, "pwdfile")
|
||||
if pwdfile then
|
||||
local ok, err = NXFS.remove(pwdfile)
|
||||
if ok then
|
||||
luci.util.perror("OpenVPN: Removed authentication file: " .. pwdfile)
|
||||
else
|
||||
luci.util.perror("OpenVPN: Error removing authentication file " .. pwdfile .. ": " .. tostring(err))
|
||||
end
|
||||
end
|
||||
TypedSection.on_remove(self, section)
|
||||
end
|
||||
|
||||
m2.on_commit = function(self)
|
||||
local result = sys.call("/etc/init.d/openvpn reload")
|
||||
if result ~= 0 then
|
||||
self.message = translate("Failed to reload OpenVPN service.")
|
||||
end
|
||||
end
|
||||
|
||||
return m2
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2025 LunaticKochiya<125438787@qq.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
local fs = require "nixio.fs"
|
||||
local conffile = "/var/openvpn.log"
|
||||
local conffile_pass = "/etc/openvpn/openvpn-password.log"
|
||||
|
||||
f = SimpleForm("logview")
|
||||
|
||||
t1 = f:field(TextValue, "conf_file_log")
|
||||
t1.rmempty = true
|
||||
t1.rows = 20
|
||||
t1.css_style = "width: 95vw !important;"
|
||||
function t1.cfgvalue()
|
||||
return fs.readfile(conffile) or ""
|
||||
end
|
||||
t1.readonly = "readonly"
|
||||
t1.description = "OpenVPN Log File"
|
||||
|
||||
t2 = f:field(TextValue, "conf_logread")
|
||||
t2.rmempty = true
|
||||
t2.rows = 20
|
||||
t2.css_style = "width: 95vw !important;"
|
||||
function t2.cfgvalue()
|
||||
local log_output = ""
|
||||
local handle = io.popen("logread | grep openvpn")
|
||||
if handle then
|
||||
log_output = handle:read("*a")
|
||||
handle:close()
|
||||
end
|
||||
return log_output or ""
|
||||
end
|
||||
t2.readonly = "readonly"
|
||||
t2.description = "OpenVPN Logread Output"
|
||||
|
||||
t3 = f:field(TextValue, "conf_file_pass_log")
|
||||
t3.rmempty = true
|
||||
t3.rows = 20
|
||||
t3.css_style = "width: 95vw !important;"
|
||||
function t3.cfgvalue()
|
||||
return fs.readfile(conffile_pass) or ""
|
||||
end
|
||||
t3.readonly = "readonly"
|
||||
t3.description = "OpenVPN Password Log File"
|
||||
|
||||
|
||||
|
||||
local clear_btn = f:field(Button, "clear_pass_log")
|
||||
clear_btn.title = "清空登陆日志"
|
||||
clear_btn.inputstyle = "remove"
|
||||
clear_btn.description = "点击清空上面内容"
|
||||
|
||||
function clear_btn.write(self, section)
|
||||
fs.writefile(conffile_pass, "")
|
||||
end
|
||||
|
||||
t4 = f:field(TextValue, "ifconfig_tun")
|
||||
t4.rmempty = true
|
||||
t4.rows = 10
|
||||
t4.css_style = "width: 95vw !important;"
|
||||
function t4.cfgvalue()
|
||||
local ifconfig_output = ""
|
||||
local handle = io.popen("ifconfig | grep -A 6 '^tun' 2>/dev/null")
|
||||
if handle then
|
||||
ifconfig_output = handle:read("*a")
|
||||
handle:close()
|
||||
end
|
||||
return ifconfig_output or "No tun interfaces found"
|
||||
end
|
||||
t4.readonly = "readonly"
|
||||
t4.description = "All tun Interfaces Configuration"
|
||||
|
||||
return f
|
||||
@@ -0,0 +1,22 @@
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(3, '<%=url([[admin]], [[services]], [[openvpn-server]], [[status]])%>', null,
|
||||
function(x, data) {
|
||||
var tb = document.getElementById('openvpn_status');
|
||||
if (data && tb) {
|
||||
if (data.running) {
|
||||
var links = '<em><b><font color=green>OpenVPN <%:RUNNING%></font></b></em>';
|
||||
tb.innerHTML = links;
|
||||
} else {
|
||||
tb.innerHTML = '<em><b><font color=red>OpenVPN <%:NOT RUNNING%></font></b></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||
<fieldset class="cbi-section">
|
||||
<p id="openvpn_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
||||
Reference in new issue
Block a user