mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-31 18:15:13 +08:00
🎈 Sync 2026-10-04 14:38:18
This commit is contained in:
1 parent
0e6611f767
commit
aba12667c5
88 files changed
+4600
-1458
No files matched your search
@@ -6,11 +6,11 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for OpenVPN Server
|
||||
LUCI_DEPENDS:=+openvpn-openssl +openvpn-easy-rsa
|
||||
LUCI_DEPENDS:=+openvpn-openssl +openvpn-easy-rsa +ip-full +resolveip
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-openvpn-server-client
|
||||
PKG_VERSION:=6.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
MAINTAINER:=lunatickochiya <125438787@qq.com>
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
@@ -27,9 +27,57 @@ function index()
|
||||
entry({"admin", "vpn", "openvpn-server","status"},call("act_status")).leaf=true
|
||||
end
|
||||
|
||||
-- 内核是否提供 DCO (需要 ovpn.ko)
|
||||
function dco_kernel_supported()
|
||||
local fs = require "nixio.fs"
|
||||
local krel = luci.sys.exec("uname -r"):gsub("%s+$", "")
|
||||
return (fs.access("/sys/module/ovpn") or fs.access("/lib/modules/" .. krel .. "/ovpn.ko")) and true or false
|
||||
end
|
||||
|
||||
-- openvpn 是否编译了 DCO 支持
|
||||
function dco_build_supported()
|
||||
local v = luci.sys.exec("openvpn --version 2>/dev/null | head -n1")
|
||||
return v:find("%[DCO%]") ~= nil
|
||||
end
|
||||
|
||||
-- DCO 是否真的在工作: 优先看内核模块引用计数, 退路是查运行日志
|
||||
function dco_in_use()
|
||||
local fs = require "nixio.fs"
|
||||
local rc = fs.readfile("/sys/module/ovpn/refcnt")
|
||||
if rc then
|
||||
-- 注意: gsub 返回两个值, 必须加括号只取第一个
|
||||
local n = tonumber((rc:gsub("%s+$", "")))
|
||||
if n and n > 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local logf = uci:get("openvpn", "myvpn", "log") or "/tmp/openvpn.log"
|
||||
local hit = luci.sys.exec("grep -m1 -E 'DCO device .* opened|ovpn-dco device' '" .. logf .. "' 2>/dev/null")
|
||||
return hit ~= nil and hit ~= ""
|
||||
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)
|
||||
local e = {}
|
||||
e.running = luci.sys.call("pgrep openvpn >/dev/null") == 0
|
||||
|
||||
e.dco_kernel = dco_kernel_supported()
|
||||
e.dco_build = dco_build_supported()
|
||||
e.dco_supported = (e.dco_kernel and e.dco_build) and true or false
|
||||
e.dco_active = dco_in_use()
|
||||
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local ac = uci:get("openvpn", "myvpn", "allow_compression")
|
||||
local lzo = uci:get("openvpn", "myvpn", "comp_lzo")
|
||||
local dis = uci:get("openvpn", "myvpn", "disable_dco")
|
||||
|
||||
e.dco_disabled = (dis == "1")
|
||||
e.allow_compression = ac or ""
|
||||
e.comp_lzo = lzo or ""
|
||||
-- 非法的压缩组合: allow-compression=no 与 comp_lzo 同时存在, openvpn 会拒绝启动
|
||||
e.conflict = (ac == "no" and lzo ~= nil and lzo ~= "")
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
@@ -33,6 +33,42 @@ end
|
||||
|
||||
local major, minor, patch, lzo = get_openvpn_info()
|
||||
|
||||
-- DCO 是否真正可用: 需要内核模块 ovpn.ko (只有 openvpn 编译支持还不够)
|
||||
local function dco_supported()
|
||||
local fs = require "nixio.fs"
|
||||
local krel = luci.sys.exec("uname -r"):gsub("%s+$", "")
|
||||
return (fs.access("/sys/module/ovpn") or fs.access("/lib/modules/" .. krel .. "/ovpn.ko")) and true or false
|
||||
end
|
||||
local dco_ok = dco_supported()
|
||||
|
||||
-- 打开页面时顺手修复历史遗留的不一致配置:
|
||||
-- 1) allow-compression=no 与 comp_lzo 不能共存 (openvpn 会拒绝启动)
|
||||
-- 2) 启用 DCO 时不能有压缩 (否则 DCO 静默失效, 不加速)
|
||||
if (major > 2) or (major == 2 and minor >= 5) or dco_ok then
|
||||
local cur = require("luci.model.uci").cursor()
|
||||
cur:foreach("openvpn", "openvpn", function(sec)
|
||||
local name = sec[".name"]
|
||||
local ac, lzo, dis = sec.allow_compression, sec.comp_lzo, sec.disable_dco
|
||||
local need_fix = false
|
||||
|
||||
if dco_ok and dis ~= "1" then
|
||||
-- DCO 已启用: 压缩必须关掉
|
||||
if ac ~= "no" or (lzo ~= nil and lzo ~= "") then
|
||||
need_fix = true
|
||||
end
|
||||
elseif ac == "no" and lzo then
|
||||
-- 致命冲突: allow-compression=no 与 comp_lzo 共存
|
||||
need_fix = true
|
||||
end
|
||||
|
||||
if need_fix then
|
||||
cur:set("openvpn", name, "allow_compression", "no")
|
||||
cur:delete("openvpn", name, "comp_lzo")
|
||||
cur:commit("openvpn")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
mp = Map("openvpn", "OpenVPN Server",translate("An easy config OpenVPN Server Web-UI"))
|
||||
|
||||
mp:section(SimpleSection).template = "openvpn/openvpn_status"
|
||||
@@ -72,7 +108,16 @@ 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.")
|
||||
if dco_ok then
|
||||
disable_dco.description = translate("Better compatibility but no acceleration. This device supports DCO: uncheck to enable it (compression will be turned off automatically).")
|
||||
else
|
||||
disable_dco.description = translate("Better compatibility but no acceleration. This device does NOT support DCO (kernel module ovpn.ko is missing); unchecking has no effect.")
|
||||
end
|
||||
|
||||
-- DCO 与压缩互斥: 启用 DCO 时必须关闭压缩, 否则 openvpn 会静默退回用户态,
|
||||
-- DCO 等于没开。
|
||||
-- 注意: Flag 取消勾选时 LuCI 不会调用 write, 所以实际修正放在 on_after_commit
|
||||
-- (那个钩子每次保存都会执行, 已验证)。
|
||||
end
|
||||
|
||||
if (major > 2) or (major == 2 and minor >= 5) then
|
||||
@@ -84,6 +129,26 @@ 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.")
|
||||
|
||||
-- 修复 allow_compression 与 comp_lzo 的冲突:
|
||||
-- openvpn 2.5+ 在两者同时存在时会直接拒绝启动, 报:
|
||||
-- "Options error: Compression is not allowed since allow-compression is set to 'stub-only'"
|
||||
-- CBI 的 depends 只会把 comp_lzo 隐藏, 并不会删除 UCI 里已有的值,
|
||||
-- 于是把 Allow Compression 改成 no 再保存, openvpn 就起不来了。
|
||||
-- 这里在写入 allow_compression=no 时同步删除 comp_lzo。
|
||||
local _allow_compression_write = allow_compression.write
|
||||
allow_compression.write = function(self, section, value)
|
||||
local c = require("luci.model.uci").cursor()
|
||||
-- DCO 已启用时不允许再开压缩 (DCO 与压缩互斥), 直接强制为 no
|
||||
if dco_ok and c:get("openvpn", section, "disable_dco") ~= "1" then
|
||||
value = "no"
|
||||
end
|
||||
_allow_compression_write(self, section, value)
|
||||
if value == "no" then
|
||||
c:delete("openvpn", section, "comp_lzo")
|
||||
c:commit("openvpn")
|
||||
end
|
||||
end
|
||||
|
||||
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.")
|
||||
|
||||
@@ -107,6 +172,17 @@ 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.")
|
||||
-- 反向保护: 只要 allow_compression 已经是 no, 就绝不写入 comp_lzo
|
||||
if (major > 2) or (major == 2 and minor >= 5) then
|
||||
local _comp_lzo_write = comp_lzo.write
|
||||
comp_lzo.write = function(self, section, value)
|
||||
local ac = require("luci.model.uci").cursor():get("openvpn", section, "allow_compression")
|
||||
if ac == "no" then
|
||||
return
|
||||
end
|
||||
_comp_lzo_write(self, section, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
auth_user_pass_verify = s:taboption("basic",Value,"auth_user_pass_verify", translate("user password verify"))
|
||||
@@ -252,6 +328,20 @@ end
|
||||
local comp_lzo_val = uci:get("openvpn", "myvpn", "comp_lzo")
|
||||
|
||||
function mp.on_after_commit(self)
|
||||
-- 保存后统一修正 DCO / 压缩 的互斥关系。
|
||||
-- Flag 取消勾选(启用 DCO)时 LuCI 不会走 write, 所以在这里处理
|
||||
-- (on_after_commit 每次保存都会执行)。
|
||||
local c = require("luci.model.uci").cursor()
|
||||
if dco_ok and c:get("openvpn", "myvpn", "disable_dco") ~= "1" then
|
||||
local ac = c:get("openvpn", "myvpn", "allow_compression")
|
||||
local lzo = c:get("openvpn", "myvpn", "comp_lzo")
|
||||
if ac ~= "no" or (lzo ~= nil and lzo ~= "") then
|
||||
c:set("openvpn", "myvpn", "allow_compression", "no")
|
||||
c:delete("openvpn", "myvpn", "comp_lzo")
|
||||
c:commit("openvpn")
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
+12
-1
@@ -48,6 +48,11 @@ o = sl:taboption("base", Flag, "enabled", translate("Enable Instance"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
|
||||
+o = sl:taboption("base", Flag, "tcp_cubic", translate("Use CUBIC for outer TCP"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
o.description = translate("For TCP client profiles only. Uses the current route to each remote endpoint and keeps the system congestion control unchanged.")
|
||||
|
||||
o = sl:taboption("base", Value, "config", translate("Config File Path"))
|
||||
o.readonly = true
|
||||
o.placeholder = translate("Auto-generated based on instance identifier")
|
||||
@@ -60,7 +65,7 @@ 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.description = translate("Paste the content of the .ovpn or .conf file here. This will be saved to the path shown in 'Base Settings'.") .. " " .. translate("If DCO hangs on this device, add disable-dco on its own line before reconnecting.")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.rmempty = true
|
||||
@@ -171,6 +176,12 @@ sp.on_remove = function(self, section)
|
||||
end
|
||||
|
||||
m2.on_commit = function(self)
|
||||
sys.call("/etc/init.d/openvpn-client-cubic enable >/dev/null 2>&1")
|
||||
local route_result = sys.call("/etc/init.d/openvpn-client-cubic restart >/dev/null 2>&1")
|
||||
if route_result ~= 0 then
|
||||
self.message = translate("Could not prepare the CUBIC route for the OpenVPN client.")
|
||||
return
|
||||
end
|
||||
local result = sys.call("/etc/init.d/openvpn reload")
|
||||
if result ~= 0 then
|
||||
self.message = translate("Failed to reload OpenVPN service.")
|
||||
|
||||
@@ -2,14 +2,44 @@
|
||||
XHR.poll(3, '<%=url([[admin]], [[vpn]], [[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>';
|
||||
}
|
||||
if (!(data && tb)) return;
|
||||
|
||||
var s = '';
|
||||
|
||||
/* OpenVPN 运行状态 */
|
||||
s += data.running
|
||||
? '<em><b><font color="#27ae60">OpenVPN <%:RUNNING%></font></b></em>'
|
||||
: '<em><b><font color="#e74c3c">OpenVPN <%:NOT RUNNING%></font></b></em>';
|
||||
|
||||
s += ' · ';
|
||||
|
||||
/* DCO 状态 */
|
||||
if (data.dco_active) {
|
||||
s += '<em><b><font color="#27ae60"><%:DCO ACTIVE%></font></b></em>';
|
||||
} else if (!data.dco_supported) {
|
||||
s += '<em><b><font color="#95a5a6"><%:DCO NOT SUPPORTED%></font></b></em>';
|
||||
} else if (data.dco_disabled) {
|
||||
s += '<em><b><font color="#95a5a6"><%:DCO DISABLED%></font></b></em>';
|
||||
} else {
|
||||
s += '<em><b><font color="#e67e22"><%:DCO INACTIVE (COMPRESSION CONFLICT)%></font></b></em>';
|
||||
}
|
||||
|
||||
/* 压缩配置冲突 */
|
||||
if (data.conflict) {
|
||||
s += ' · <em><b><font color="#e74c3c"><%:COMPRESSION CONFIG CONFLICT%></font></b></em>';
|
||||
}
|
||||
|
||||
/* 明细 */
|
||||
var d = [];
|
||||
d.push('<%:DCO kernel module%>: ' + (data.dco_kernel ? '✔' : '✘'));
|
||||
d.push('<%:OpenVPN built with DCO%>: ' + (data.dco_build ? '✔' : '✘'));
|
||||
d.push('allow-compression: ' + (data.allow_compression || '-'));
|
||||
d.push('comp_lzo: ' + (data.comp_lzo || '-'));
|
||||
if (data.conflict) {
|
||||
d.push('<font color="#e74c3c"><%:allow-compression=no and comp_lzo cannot coexist, openvpn will refuse to start.%></font>');
|
||||
}
|
||||
|
||||
tb.innerHTML = s + '<br><small style="color:#7f8c8d">' + d.join(' | ') + '</small>';
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
@@ -19,4 +49,4 @@ XHR.poll(3, '<%=url([[admin]], [[vpn]], [[openvpn-server]], [[status]])%>', null
|
||||
<p id="openvpn_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
@@ -216,3 +216,104 @@ msgstr "这将允许服务器获取更多关于客户端的信息,比如硬件
|
||||
|
||||
msgid "Disabling DCO provides better compatibility but disables acceleration."
|
||||
msgstr "禁用DCO可以提供更好的兼容性,但会关闭加速功能。"
|
||||
|
||||
# ---- DCO / compression related (added) ----
|
||||
|
||||
msgid "Allow Compression"
|
||||
msgstr "允许压缩"
|
||||
|
||||
msgid "Allow compression, DCO can only be used when set to NO. asym is compatible mode."
|
||||
msgstr "允许压缩。只有设为 NO 时才能使用 DCO 加速;asym 为兼容模式。"
|
||||
|
||||
msgid "Base Settings"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Better compatibility but no acceleration. This device does NOT support DCO (kernel module ovpn.ko is missing); unchecking has no effect."
|
||||
msgstr "兼容性更好但不走加速。本机不支持 DCO(缺少内核模块 ovpn.ko),取消勾选也不会生效。"
|
||||
|
||||
msgid "Better compatibility but no acceleration. This device supports DCO: uncheck to enable it (compression will be turned off automatically)."
|
||||
msgstr "兼容性更好但不走加速。本机支持 DCO:取消勾选即可启用(会同时自动关闭压缩)。"
|
||||
|
||||
msgid "COMPRESSION CONFIG CONFLICT"
|
||||
msgstr "压缩配置冲突"
|
||||
|
||||
msgid "Client"
|
||||
msgstr "客户端"
|
||||
|
||||
msgid "Client Config File Content"
|
||||
msgstr "客户端配置内容"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据…"
|
||||
|
||||
msgid "Config File Path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Configure authentication files for OpenVPN client instances."
|
||||
msgstr "为 OpenVPN 客户端实例配置认证文件。"
|
||||
|
||||
msgid "DCO ACTIVE"
|
||||
msgstr "DCO 加速中"
|
||||
|
||||
msgid "DCO DISABLED"
|
||||
msgstr "DCO 已关闭"
|
||||
|
||||
msgid "DCO INACTIVE (COMPRESSION CONFLICT)"
|
||||
msgstr "DCO 未生效(压缩冲突)"
|
||||
|
||||
msgid "DCO NOT SUPPORTED"
|
||||
msgstr "DCO 不支持"
|
||||
|
||||
msgid "DCO kernel module"
|
||||
msgstr "DCO 内核模块"
|
||||
|
||||
msgid "Failed to reload OpenVPN service."
|
||||
msgstr "OpenVPN 服务重载失败。"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "OpenVPN Cert"
|
||||
msgstr "OpenVPN 证书"
|
||||
|
||||
msgid "OpenVPN Client Authentication"
|
||||
msgstr "OpenVPN 客户端认证"
|
||||
|
||||
msgid "OpenVPN built with DCO"
|
||||
msgstr "openvpn 编译支持 DCO"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "Start"
|
||||
msgstr "启动"
|
||||
|
||||
msgid "Stop"
|
||||
msgstr "停止"
|
||||
|
||||
msgid "allow-compression=no and comp_lzo cannot coexist, openvpn will refuse to start."
|
||||
msgstr "allow-compression=no 与 comp_lzo 不能共存,openvpn 会拒绝启动。"
|
||||
|
||||
msgid "client-to-client"
|
||||
msgstr "客户端互通(client-to-client)"
|
||||
|
||||
msgid "client_cert_not_required"
|
||||
msgstr "客户端免证书(client_cert_not_required)"
|
||||
|
||||
msgid "comp_lzo"
|
||||
msgstr "LZO 压缩(comp_lzo)"
|
||||
|
||||
msgid "disable dco"
|
||||
msgstr "关闭 DCO"
|
||||
|
||||
msgid "duplicate_cn"
|
||||
msgstr "允许重复 CN(duplicate_cn)"
|
||||
|
||||
msgid "proto"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "push peer info"
|
||||
msgstr "推送客户端信息(push_peer_info)"
|
||||
|
||||
msgid "username_as_common_name"
|
||||
msgstr "用户名作为 CN(username_as_common_name)"
|
||||
@@ -1,41 +0,0 @@
|
||||
|
||||
config openvpn 'myvpn'
|
||||
option enabled '0'
|
||||
option proto 'tcp4'
|
||||
option dev 'tun'
|
||||
option topology 'subnet'
|
||||
option server '10.8.0.0 255.255.255.0'
|
||||
option comp_lzo 'adaptive'
|
||||
option ca '/etc/openvpn/pki/ca.crt'
|
||||
option dh '/etc/openvpn/pki/dh.pem'
|
||||
option cert '/etc/openvpn/pki/server.crt'
|
||||
option key '/etc/openvpn/pki/server.key'
|
||||
option persist_key '1'
|
||||
option persist_tun '1'
|
||||
option max_clients '88'
|
||||
option keepalive '10 120'
|
||||
option verb '3'
|
||||
option status '/var/log/openvpn_status.log'
|
||||
option log '/tmp/openvpn.log'
|
||||
option port '1194'
|
||||
option ddns 'myserver.f3322.net'
|
||||
option auth_user_pass_verify '/etc/openvpn/server/checkpsw.sh via-env'
|
||||
option script_security '3'
|
||||
list push 'route 192.168.9.0 255.255.255.0'
|
||||
list push 'comp-lzo adaptive'
|
||||
list push 'redirect-gateway def1 bypass-dhcp'
|
||||
list push 'dhcp-option DNS 192.168.9.1'
|
||||
|
||||
config openvpn 'client1'
|
||||
option enabled '0'
|
||||
option config '/etc/openvpn/client1.conf'
|
||||
|
||||
config openvpn 'client2'
|
||||
option enabled '0'
|
||||
option config '/etc/openvpn/client2.conf'
|
||||
|
||||
config openvpnpassword 'pwd1'
|
||||
option pwdfile '/etc/openvpn/pass.txt'
|
||||
|
||||
config openvpnpassword 'pwd2'
|
||||
option pwdfile '/etc/openvpn/pass2.txt'
|
||||
@@ -1,10 +0,0 @@
|
||||
set_var EASYRSA_OPENSSL "openssl"
|
||||
set_var EASYRSA_KEY_SIZE 2048
|
||||
set_var EASYRSA_REQ_COUNTRY "lunatickochiya"
|
||||
set_var EASYRSA_REQ_PROVINCE "github"
|
||||
set_var EASYRSA_REQ_CITY "github"
|
||||
set_var EASYRSA_REQ_ORG "github"
|
||||
set_var EASYRSA_REQ_EMAIL "lunatickochiya@github.com"
|
||||
set_var EASYRSA_REQ_OU "github"
|
||||
set_var EASYRSA_CA_EXPIRE 3650
|
||||
set_var EASYRSA_CERT_EXPIRE 3650
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$ACTION" in
|
||||
ifup|ifupdate) /usr/libexec/openvpn-client-cubic-route update >/dev/null 2>&1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=89
|
||||
STOP=10
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
local attempt=0
|
||||
/usr/libexec/openvpn-client-cubic-route enabled || return 0
|
||||
|
||||
# OpenVPN starts at 90. Wait for DNS and the uplink before it connects.
|
||||
while ! /usr/libexec/openvpn-client-cubic-route update; do
|
||||
attempt=$((attempt + 1))
|
||||
[ "$attempt" -lt 12 ] || {
|
||||
logger -t openvpn-client-cubic 'Could not install CUBIC route before OpenVPN startup'
|
||||
return 1
|
||||
}
|
||||
sleep 2
|
||||
done
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /usr/libexec/openvpn-client-cubic-route watch
|
||||
procd_set_param respawn 3600 5 -1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
/usr/libexec/openvpn-client-cubic-route clear
|
||||
}
|
||||
@@ -1,34 +1,52 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
function rand_str() {
|
||||
rand_str() {
|
||||
(base64 /dev/urandom | tr -dc 'A-Za-z' | head -c $1) 2>/dev/null
|
||||
}
|
||||
|
||||
function rand_str_upper() {
|
||||
rand_str_upper() {
|
||||
(rand_str $1 | tr 'a-z' 'A-Z') 2>/dev/null
|
||||
}
|
||||
|
||||
function rand_str_lower() {
|
||||
rand_str_lower() {
|
||||
(rand_str $1 | tr 'A-Z' 'a-z') 2>/dev/null
|
||||
}
|
||||
|
||||
function rand_easy_rsa_vars() {
|
||||
set_easy_rsa_var() {
|
||||
local name="$1"
|
||||
local value="$2"
|
||||
|
||||
if grep -q "^[[:space:]]*set_var[[:space:]]\+$name[[:space:]]" /etc/easy-rsa/vars; then
|
||||
sed -i "s|^[[:space:]]*set_var[[:space:]]\+$name[[:space:]].*$|set_var $name\t$value|" /etc/easy-rsa/vars
|
||||
else
|
||||
printf 'set_var %s\t%s\n' "$name" "$value" >> /etc/easy-rsa/vars
|
||||
fi
|
||||
}
|
||||
|
||||
init_easy_rsa_vars() {
|
||||
touch /etc/easy-rsa/vars
|
||||
set_easy_rsa_var EASYRSA_OPENSSL '"openssl"'
|
||||
set_easy_rsa_var EASYRSA_KEY_SIZE '2048'
|
||||
set_easy_rsa_var EASYRSA_CA_EXPIRE '3650'
|
||||
set_easy_rsa_var EASYRSA_CERT_EXPIRE '3650'
|
||||
}
|
||||
|
||||
rand_easy_rsa_vars() {
|
||||
local KEY_PROVINCE="$(rand_str_upper 6)"
|
||||
local KEY_CITY="$(rand_str 8)"
|
||||
local KEY_ORG="$(rand_str 8)"
|
||||
local KEY_EMAIL="$(rand_str_lower 8)@$(rand_str_lower 4).$(rand_str_lower 3)"
|
||||
local KEY_OU="$(rand_str 8)"
|
||||
sed -i \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_COUNTRY[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_COUNTRY\t\"$KEY_PROVINCE\"/" \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_PROVINCE[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_PROVINCE\t\"$KEY_CITY\"/" \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_CITY[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_CITY\t\"$KEY_ORG\"/" \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_ORG[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_ORG\t\"$KEY_ORG\"/" \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_EMAIL[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_EMAIL\t\"$KEY_EMAIL\"/" \
|
||||
-e "s/^[[:space:]]*set_var[[:space:]]\+EASYRSA_REQ_OU[[:space:]]\+\".*\"$/set_var EASYRSA_REQ_OU\t\"$KEY_OU\"/" \
|
||||
/etc/easy-rsa/vars
|
||||
set_easy_rsa_var EASYRSA_REQ_COUNTRY "\"$KEY_PROVINCE\""
|
||||
set_easy_rsa_var EASYRSA_REQ_PROVINCE "\"$KEY_CITY\""
|
||||
set_easy_rsa_var EASYRSA_REQ_CITY "\"$KEY_ORG\""
|
||||
set_easy_rsa_var EASYRSA_REQ_ORG "\"$KEY_ORG\""
|
||||
set_easy_rsa_var EASYRSA_REQ_EMAIL "\"$KEY_EMAIL\""
|
||||
set_easy_rsa_var EASYRSA_REQ_OU "\"$KEY_OU\""
|
||||
}
|
||||
|
||||
init_easy_rsa_vars
|
||||
rand_easy_rsa_vars
|
||||
|
||||
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/etc/init.d/openvpn-client-cubic enable
|
||||
exit 0
|
||||
@@ -1,6 +1,70 @@
|
||||
#!/bin/sh
|
||||
|
||||
grep -qv "myvpn" /etc/config/openvpn && grep -q "myvpn" /etc/config/openvpn-opkg && cp -f /etc/config/openvpn-opkg /etc/config/openvpn
|
||||
if ! uci -q get openvpn.myvpn >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set openvpn.myvpn=openvpn
|
||||
set openvpn.myvpn.enabled='0'
|
||||
set openvpn.myvpn.proto='tcp4'
|
||||
set openvpn.myvpn.dev='tun'
|
||||
set openvpn.myvpn.topology='subnet'
|
||||
set openvpn.myvpn.server='10.8.0.0 255.255.255.0'
|
||||
set openvpn.myvpn.comp_lzo='adaptive'
|
||||
set openvpn.myvpn.ca='/etc/openvpn/pki/ca.crt'
|
||||
set openvpn.myvpn.dh='/etc/openvpn/pki/dh.pem'
|
||||
set openvpn.myvpn.cert='/etc/openvpn/pki/server.crt'
|
||||
set openvpn.myvpn.key='/etc/openvpn/pki/server.key'
|
||||
set openvpn.myvpn.persist_key='1'
|
||||
set openvpn.myvpn.persist_tun='1'
|
||||
set openvpn.myvpn.max_clients='88'
|
||||
set openvpn.myvpn.keepalive='10 120'
|
||||
set openvpn.myvpn.verb='3'
|
||||
set openvpn.myvpn.status='/var/log/openvpn_status.log'
|
||||
set openvpn.myvpn.log='/tmp/openvpn.log'
|
||||
set openvpn.myvpn.port='1194'
|
||||
set openvpn.myvpn.ddns='myserver.f3322.net'
|
||||
set openvpn.myvpn.auth_user_pass_verify='/etc/openvpn/server/checkpsw.sh via-env'
|
||||
set openvpn.myvpn.script_security='3'
|
||||
add_list openvpn.myvpn.push='route 192.168.9.0 255.255.255.0'
|
||||
add_list openvpn.myvpn.push='comp-lzo adaptive'
|
||||
add_list openvpn.myvpn.push='redirect-gateway def1 bypass-dhcp'
|
||||
add_list openvpn.myvpn.push='dhcp-option DNS 192.168.9.1'
|
||||
commit openvpn
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! uci -q get openvpn.client1 >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set openvpn.client1=openvpn
|
||||
set openvpn.client1.enabled='0'
|
||||
set openvpn.client1.config='/etc/openvpn/client1.conf'
|
||||
commit openvpn
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! uci -q get openvpn.client2 >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set openvpn.client2=openvpn
|
||||
set openvpn.client2.enabled='0'
|
||||
set openvpn.client2.config='/etc/openvpn/client2.conf'
|
||||
commit openvpn
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! uci -q get openvpn.pwd1 >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set openvpn.pwd1=openvpnpassword
|
||||
set openvpn.pwd1.pwdfile='/etc/openvpn/pass.txt'
|
||||
commit openvpn
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! uci -q get openvpn.pwd2 >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set openvpn.pwd2=openvpnpassword
|
||||
set openvpn.pwd2.pwdfile='/etc/openvpn/pass2.txt'
|
||||
commit openvpn
|
||||
EOF
|
||||
fi
|
||||
|
||||
openvpn_port="$(uci -q get openvpn.myvpn.port)"
|
||||
[ -z "$openvpn_port" ] && openvpn_port=1194
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#!/bin/sh
|
||||
# Set CUBIC only for opted-in OpenVPN clients' outer TCP destinations.
|
||||
|
||||
umask 077
|
||||
state=${OPENVPN_CLIENT_CUBIC_STATE:-/tmp/openvpn-client-cubic-routes}
|
||||
|
||||
sections() {
|
||||
uci -q show openvpn 2>/dev/null |
|
||||
sed -n 's/^openvpn\.\(client[A-Za-z0-9_-]*\)=openvpn$/\1/p'
|
||||
}
|
||||
|
||||
client_enabled() {
|
||||
[ "$(uci -q get "openvpn.$1.enabled")" = 1 ] &&
|
||||
[ "$(uci -q get "openvpn.$1.tcp_cubic")" = 1 ]
|
||||
}
|
||||
|
||||
has_clients() {
|
||||
for section in $(sections); do
|
||||
client_enabled "$section" && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
delete_old_routes() {
|
||||
[ -f "$state" ] || return 0
|
||||
while IFS='|' read -r address via device; do
|
||||
[ -n "$address" ] && [ -n "$device" ] || continue
|
||||
if [ -n "$via" ]; then
|
||||
ip -4 route del "$address/32" via "$via" dev "$device" 2>/dev/null
|
||||
else
|
||||
ip -4 route del "$address/32" dev "$device" 2>/dev/null
|
||||
fi
|
||||
done < "$state"
|
||||
return 0
|
||||
}
|
||||
|
||||
add_route() {
|
||||
local address=$1 route via device
|
||||
route=$(ip -4 route get "$address" 2>/dev/null) || return 1
|
||||
set -- $route
|
||||
while [ "$#" -gt 1 ]; do
|
||||
case "$1" in
|
||||
via) via=$2; shift 2 ;;
|
||||
dev) device=$2; shift 2 ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$device" ] && [ "$device" != lo ] || return 1
|
||||
if [ -n "$via" ]; then
|
||||
ip -4 route replace "$address/32" via "$via" dev "$device" congctl cubic || return 1
|
||||
else
|
||||
ip -4 route replace "$address/32" dev "$device" congctl cubic || return 1
|
||||
fi
|
||||
printf '%s|%s|%s\n' "$address" "$via" "$device" >> "$new_state"
|
||||
}
|
||||
|
||||
update_routes() {
|
||||
local section conf host addresses address failed=0 desired new_state
|
||||
desired=$(mktemp /tmp/openvpn-client-cubic-desired.XXXXXX) || return 1
|
||||
new_state=$(mktemp /tmp/openvpn-client-cubic-state.XXXXXX) || {
|
||||
rm -f "$desired"
|
||||
return 1
|
||||
}
|
||||
|
||||
for section in $(sections); do
|
||||
client_enabled "$section" || continue
|
||||
conf=$(uci -q get "openvpn.$section.config")
|
||||
if [ ! -r "$conf" ]; then
|
||||
logger -t openvpn-client-cubic "Cannot read config for $section"
|
||||
failed=1
|
||||
continue
|
||||
fi
|
||||
# An outer TCP congestion controller has no effect on UDP clients.
|
||||
grep -Eiq '^[[:space:]]*proto[[:space:]]+tcp' "$conf" || continue
|
||||
for host in $(awk '$1 == "remote" { gsub(/["\047]/, "", $2); print $2 }' "$conf"); do
|
||||
case "$host" in
|
||||
''|*[!0-9.]*) addresses=$(resolveip -4 -t 5 "$host" 2>/dev/null) ;;
|
||||
*) addresses=$host ;;
|
||||
esac
|
||||
if [ -z "$addresses" ]; then
|
||||
logger -t openvpn-client-cubic "Cannot resolve $host for $section"
|
||||
failed=1
|
||||
continue
|
||||
fi
|
||||
for address in $addresses; do
|
||||
case "$address" in
|
||||
*[!0-9.]*|'') continue ;;
|
||||
esac
|
||||
printf '%s\n' "$address" >> "$desired"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$failed" -ne 0 ]; then
|
||||
rm -f "$desired" "$new_state"
|
||||
return 1
|
||||
fi
|
||||
|
||||
delete_old_routes
|
||||
sort -u "$desired" | while IFS= read -r address; do
|
||||
[ -n "$address" ] || continue
|
||||
add_route "$address" || exit 1
|
||||
done
|
||||
failed=$?
|
||||
rm -f "$desired"
|
||||
if [ "$failed" -eq 0 ]; then
|
||||
mv -f "$new_state" "$state"
|
||||
else
|
||||
rm -f "$new_state"
|
||||
fi
|
||||
return "$failed"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
enabled) has_clients ;;
|
||||
update) update_routes ;;
|
||||
clear) delete_old_routes; rm -f "$state" ;;
|
||||
watch)
|
||||
while sleep 300; do
|
||||
update_routes || logger -t openvpn-client-cubic 'Could not refresh CUBIC routes'
|
||||
done
|
||||
;;
|
||||
*) echo "Usage: $0 {enabled|update|clear|watch}" >&2; exit 2 ;;
|
||||
esac
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"luci-app-openvpn-server-client": {
|
||||
"description": "Grant UCI access for luci-app-openvpn-server-client",
|
||||
"read": {
|
||||
"uci": [ "openvpn" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "openvpn" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user