update 2023-07-07 09:50:53

This commit is contained in:
github-actions[bot] 2023-07-07 09:50:53 +08:00
parent 612a62efb2
commit f166386a43
10 changed files with 583 additions and 0 deletions

View File

@ -0,0 +1,15 @@
# Copyright (C) 2021-2022 Lienol <lawlienol@gmail.com>
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-openvpn-client
PKG_VERSION:=20211229
PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for OpenVPN Client
LUCI_DEPENDS:=+openvpn-openssl +kmod-tun
LUCI_PKGARCH:=all
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,10 @@
-- Copyright 2021-2022 Lienol <lawlienol@gmail.com>
module("luci.controller.openvpn-client", package.seeall)
function index()
if not nixio.fs.access("/etc/config/luci-app-openvpn-client") then return end
entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false
entry({"admin", "vpn", "openvpn-client"}, cbi("openvpn-client/settings"), _("OpenVPN Client"), 50).acl_depends = { "luci-app-openvpn-client" }
entry({"admin", "vpn", "openvpn-client", "client"}, cbi("openvpn-client/client")).leaf = true
end

View File

@ -0,0 +1,119 @@
local d = require "luci.dispatcher"
m = Map("luci-app-openvpn-client", translate("Client List"))
m.apply_on_parse = true
m.redirect = d.build_url("admin", "vpn", "openvpn-client")
s = m:section(NamedSection, arg[1], "clients", "")
s.addremove = false
s.anonymous = true
o = s:option(Flag, "enabled", translate("Enabled"))
o.default = 1
o.rmempty = false
o = s:option(Value, "server", translate("Server IP/Host"))
o.rmempty = false
o = s:option(Value, "port", translate("Port"))
o.datatype = "port"
o.placeholder = "1194"
o.rmempty = false
o = s:option(ListValue, "proto", translate("Protocol"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o.rmempty = false
o = s:option(ListValue, "dev", translate("Type"))
o:value("tun", "TUN")
o:value("tap", "TAP")
o.rmempty = false
o = s:option(Flag, "lzo", translate("LZO compression"))
o.default = "1"
o.rmempty = false
o = s:option(Flag, "route_nopull", translate("No pull route"))
o.default = "1"
o.rmempty = false
o = s:option(DynamicList, "routes", translate("Static Routes"))
o.placeholder = "192.168.10.0/24"
o = s:option(ListValue, "auth", translate("Auth"))
o:value("", translate("None"))
o:value("user_pass", translate("User/Pass"))
o:value("tls_auth", "tls-auth")
o:value("tls_crypt", "tls-crypt")
o = s:option(Value, "username", translate("Username"))
o.placeholder = translate("Username")
o:depends("auth", "user_pass")
o = s:option(Value, "password", translate("Password"))
o.placeholder = translate("Password")
o:depends("auth", "user_pass")
o = s:option(TextValue, "tls_auth", "tls-auth")
o.datatype = "string"
o.rows = 3
o.wrap = "off"
o:depends("auth", "tls_auth")
o = s:option(TextValue, "tls_crypt", "tls-crypt")
o.datatype = "string"
o.rows = 3
o.wrap = "off"
o:depends("auth", "tls_crypt")
o = s:option(TextValue, "ca", "CA")
o.datatype = "string"
o.rows = 3
o.wrap = "off"
o.rmempty = false
o = s:option(TextValue, "cert", "Cert")
o.datatype = "string"
o.rows = 3
o.wrap = "off"
o = s:option(TextValue, "key", "Key")
o.datatype = "string"
o.rows = 3
o.wrap = "off"
o = s:option(ListValue, "proxy", translate("Proxy"))
o:value("", translate("None"))
o:value("socks", "Socks")
o:value("http", "HTTP")
o = s:option(Value, "proxy_server", translate("Proxy Server"))
o.placeholder = "127.0.0.1"
o.default = o.placeholder
o:depends("proxy", "socks")
o:depends("proxy", "http")
o = s:option(Value, "proxy_port", translate("Proxy Port"))
o.datatype = "port"
o.placeholder = "1080"
o.default = o.placeholder
o:depends("proxy", "socks")
o:depends("proxy", "http")
o = s:option(Value, "proxy_username", translate("Proxy Username"))
o.placeholder = translate("Username")
o:depends("proxy", "socks")
o:depends("proxy", "http")
o = s:option(Value, "proxy_password", translate("Proxy Password"))
o.placeholder = translate("Password")
o:depends("proxy", "socks")
o:depends("proxy", "http")
o = s:option(TextValue, "extra_config", translate("Extra Config"))
o.datatype = "string"
o.rows = 3
o.wrap = "off"
return m

View File

@ -0,0 +1,71 @@
local d = require "luci.dispatcher"
local sys = require "luci.sys"
m = Map("luci-app-openvpn-client", translate("OpenVPN Client"))
m.apply_on_parse = true
s = m:section(TypedSection, "clients", translate("Client List"))
s.addremove = true
s.anonymous = true
s.template = "cbi/tblsection"
s.extedit = d.build_url("admin", "vpn", "openvpn-client", "client", "%s")
function s.create(e, t)
t = TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
o = s:option(Flag, "enabled", translate("Enabled"))
o.default = 1
o.rmempty = false
function s.getPID(section) -- Universal function which returns valid pid # or nil
local pid = sys.exec("top -bn1 | grep -v 'grep' | grep '/var/etc/openvpn-client/%s'" % { section })
if pid and #pid > 0 then
return tonumber(pid:match("^%s*(%d+)"))
else
return nil
end
end
local active = s:option( DummyValue, "_active", translate("Status") )
function active.cfgvalue(self, section)
local pid = s.getPID(section)
if pid ~= nil then
return (sys.process.signal(pid, 0))
and translate("RUNNING") .. " (" .. pid .. ")"
or translate("NOT RUNNING")
end
return translate("NOT RUNNING")
end
local updown = s:option( Button, "_updown", translate("Start/Stop") )
updown._state = false
updown.redirect = d.build_url(
"admin", "vpn", "openvpn-client"
)
function updown.cbid(self, section)
local pid = s.getPID(section)
self._state = pid ~= nil and sys.process.signal(pid, 0)
self.option = self._state and "stop" or "start"
return AbstractValue.cbid(self, section)
end
function updown.cfgvalue(self, section)
self.title = self._state and translate("stop") or translate("start")
self.inputstyle = self._state and "reset" or "reload"
end
function updown.write(self, section, value)
if self.option == "stop" then
sys.call("/etc/init.d/luci-app-openvpn-client stop %s" % section)
else
sys.call("/etc/init.d/luci-app-openvpn-client start %s" % section)
end
luci.http.redirect( self.redirect )
end
o = s:option(DummyValue, "server", translate("Server IP/Host"))
o = s:option(DummyValue, "port", translate("Port"))
o = s:option(DummyValue, "proto", translate("Protocol"))
return m

View File

@ -0,0 +1,80 @@
msgid "OpenVPN Client"
msgstr "OpenVPN 客户端"
msgid "Client List"
msgstr "客户端列表"
msgid "Status"
msgstr "状态"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "RUNNING"
msgstr "运行中"
msgid "Start/Stop"
msgstr "启动/关闭"
msgid "start"
msgstr "启动"
msgid "stop"
msgstr "关闭"
msgid "Enabled"
msgstr "启用"
msgid "Server IP/Host"
msgstr "服务器IP/域名"
msgid "Port"
msgstr "端口"
msgid "Protocol"
msgstr "协议"
msgid "Type"
msgstr "类型"
msgid "LZO compression"
msgstr "LZO 压缩"
msgid "No pull route"
msgstr "不拉取路由"
msgid "Static Routes"
msgstr "静态路由"
msgid "Auth"
msgstr "身份认证"
msgid "None"
msgstr "无"
msgid "User/Pass"
msgstr "用户/密码"
msgid "Username"
msgstr "用户名"
msgid "Password"
msgstr "密码"
msgid "Proxy"
msgstr "代理"
msgid "Proxy Server"
msgstr "代理服务器"
msgid "Proxy Port"
msgstr "代理端口"
msgid "Proxy Username"
msgstr "代理用户名"
msgid "Proxy Password"
msgstr "代理密码"
msgid "Extra Config"
msgstr "额外配置"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,264 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2021-2022 Lienol <lawlienol@gmail.com>
START=99
STOP=10
USE_PROCD=1
PROG=/usr/sbin/openvpn
CONFIG="luci-app-openvpn-client"
TMP_OVPN_PATH=/var/etc/openvpn-client
start_instance() {
local cfgid=${1}
stop_instance ${cfgid}
local c_enabled=$(uci -q get ${CONFIG}.${cfgid}.enabled)
[ "${c_enabled}" -eq 1 ] || return 1
local c_server=$(uci -q get ${CONFIG}.${cfgid}.server)
[ -n "${c_server}" ] || return 1
local c_port=$(uci -q get ${CONFIG}.${cfgid}.port)
[ -n "${c_port}" ] || return 1
local c_ca="$(uci -q get ${CONFIG}.${cfgid}.ca)"
[ -n "${c_ca}" ] || return 1
local cfgid=$(uci show ${CONFIG}.${cfgid} | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1)
local c_dev="ovpn_${cfgid}"
mkdir -p ${TMP_OVPN_PATH}
mkdir -p ${TMP_OVPN_PATH}/${cfgid}
echo "${c_ca}" >> ${TMP_OVPN_PATH}/${cfgid}/ca
local _ca="ca ca"
local c_cert="$(uci -q get ${CONFIG}.${cfgid}.cert)"
[ -n "${c_cert}" ] && {
echo "${c_cert}" >> ${TMP_OVPN_PATH}/${cfgid}/cert
local _cert="cert cert"
}
local c_key="$(uci -q get ${CONFIG}.${cfgid}.key)"
[ -n "${c_key}" ] && {
echo "${c_key}" >> ${TMP_OVPN_PATH}/${cfgid}/key
local _key="key key"
}
local c_lzo=$(uci -q get ${CONFIG}.${cfgid}.lzo)
[ "${c_lzo}" = "1" ] && local _lzo="comp-lzo"
local c_route_nopull=$(uci -q get ${CONFIG}.${cfgid}.route_nopull)
[ "${c_route_nopull}" = "1" ] && local _route_nopull="route-nopull"
local c_auth=$(uci -q get ${CONFIG}.${cfgid}.auth)
[ -n "${c_auth}" ] && {
if [ "${c_auth}" = "user_pass" ]; then
local c_username=$(uci -q get ${CONFIG}.${cfgid}.username)
local c_password=$(uci -q get ${CONFIG}.${cfgid}.password)
echo "${c_username}" >> ${TMP_OVPN_PATH}/${cfgid}/auth-user-pass
echo "${c_password}" >> ${TMP_OVPN_PATH}/${cfgid}/auth-user-pass
local _auth_user_pass="auth-user-pass auth-user-pass"
elif [ "${c_auth}" = "tls_auth" ]; then
local c_tls_auth="$(uci -q get ${CONFIG}.${cfgid}.tls_auth)"
[ -n "${c_tls_auth}" ] && {
echo "${c_tls_auth}" >> ${TMP_OVPN_PATH}/${cfgid}/tls-auth
local _tls_auth="tls-auth tls-auth"
}
elif [ "${c_auth}" = "tls_crypt" ]; then
local c_tls_crypt="$(uci -q get ${CONFIG}.${cfgid}.tls_crypt)"
[ -n "${c_tls_crypt}" ] && {
echo "${c_tls_crypt}" >> ${TMP_OVPN_PATH}/${cfgid}/tls-crypt
local _tls_crypt="tls-crypt tls-crypt"
}
fi
}
local c_proxy=$(uci -q get ${CONFIG}.${cfgid}.proxy)
[ -n "${c_proxy}" ] && {
local _proxy=""
local c_p_username=$(uci -q get ${CONFIG}.${cfgid}.proxy_username)
local c_p_password=$(uci -q get ${CONFIG}.${cfgid}.proxy_password)
if [ -n "${c_p_username}" ] && [ -n "${c_p_password}" ]; then
echo "${c_p_username}" >> ${TMP_OVPN_PATH}/${cfgid}/proxy-auth
echo "${c_p_password}" >> ${TMP_OVPN_PATH}/${cfgid}/proxy-auth
local _proxy_auth="proxy-auth"
fi
local c_p_server=$(uci -q get ${CONFIG}.${cfgid}.proxy_server)
local c_p_port=$(uci -q get ${CONFIG}.${cfgid}.proxy_port)
if [ "${c_proxy}" = "http" ]; then
_proxy="http-proxy ${c_p_server} ${c_p_port} ${_proxy_auth}"
elif [ "${c_proxy}" = "socks" ]; then
_proxy="socks-proxy ${c_p_server} ${c_p_port} ${_proxy_auth}"
fi
}
echo "#!/bin/sh" > ${TMP_OVPN_PATH}/${cfgid}/up.sh
echo "#!/bin/sh" > ${TMP_OVPN_PATH}/${cfgid}/down.sh
[ ! -s "/var/etc/${CONFIG}.include" ] && echo '#!/bin/sh' > /var/etc/${CONFIG}.include
cat <<-EOF >> ${TMP_OVPN_PATH}/${cfgid}/up.sh
eval "\$(ipcalc.sh \${ifconfig_local} \${ifconfig_netmask})"
echo "\${IP}" > ${TMP_OVPN_PATH}/${cfgid}/ip
echo "\${NETWORK}" > ${TMP_OVPN_PATH}/${cfgid}/network
echo "\${PREFIX}" > ${TMP_OVPN_PATH}/${cfgid}/mask
${TMP_OVPN_PATH}/${cfgid}/iptables_add.sh
EOF
cat <<-EOF >> ${TMP_OVPN_PATH}/${cfgid}/down.sh
ifup ovpn_${cfgid} >/dev/null 2>&1
ifdown ovpn_${cfgid} >/dev/null 2>&1
${TMP_OVPN_PATH}/${cfgid}/iptables_del.sh
EOF
cat <<-EOF >> ${TMP_OVPN_PATH}/${cfgid}/iptables_add.sh
${TMP_OVPN_PATH}/${cfgid}/iptables_del.sh
#允许服务端配置静态路由表访问内网
iptables -t nat -I POSTROUTING -s \$(cat ${TMP_OVPN_PATH}/${cfgid}/network)/\$(cat ${TMP_OVPN_PATH}/${cfgid}/mask) -m comment --comment "${c_dev}" -j MASQUERADE
iptables -t nat -I POSTROUTING -o ${c_dev} -m comment --comment "${c_dev}" -j MASQUERADE
iptables -I FORWARD -i ${c_dev} -m comment --comment "${c_dev}" -j ACCEPT
iptables -I FORWARD -o ${c_dev} -m comment --comment "${c_dev}" -j ACCEPT
EOF
cat <<-EOF >> ${TMP_OVPN_PATH}/${cfgid}/iptables_del.sh
ipt_del() {
for i in \$(seq 1 \$(\$1 -nL \$2 | grep -c "${c_dev}")); do
local index=\$(\$1 --line-number -nL \$2 | grep "${c_dev}" | head -1 | awk '{print \$1}')
\$1 -w -D \$2 \$index 2>/dev/null
done
}
ipt_del "iptables" "FORWARD"
ipt_del "iptables -t nat" "POSTROUTING"
EOF
cat <<-EOF >> /var/etc/${CONFIG}.include
${TMP_OVPN_PATH}/${cfgid}/iptables_add.sh
EOF
local c_routes=$(uci -q get ${CONFIG}.${cfgid}.routes)
[ -n "${c_routes}" ] && {
for c_route in ${c_routes}; do
local c_network=$(echo -n "${c_route}" | awk -F ',' '{print $1}')
local c_gateway=$(echo -n "${c_route}" | awk -F ',' '{print $2}')
if [ -n "${c_gateway}" ]; then
echo "route add -net ${c_network} gw ${c_gateway} dev ${c_dev} >/dev/null 2>&1" >> ${TMP_OVPN_PATH}/${cfgid}/up.sh
echo "route del -net ${c_network} gw ${c_gateway} dev ${c_dev} >/dev/null 2>&1" >> ${TMP_OVPN_PATH}/${cfgid}/down.sh
else
echo "route add -net ${c_network} dev ${c_dev} >/dev/null 2>&1" >> ${TMP_OVPN_PATH}/${cfgid}/up.sh
echo "route del -net ${c_network} dev ${c_dev} >/dev/null 2>&1" >> ${TMP_OVPN_PATH}/${cfgid}/down.sh
fi
done
}
chmod 0755 ${TMP_OVPN_PATH}/${cfgid}/*.sh
cat <<-EOF >> ${TMP_OVPN_PATH}/${cfgid}/client.conf
client
float
dev ${c_dev}
dev-type $(uci -q get ${CONFIG}.${cfgid}.dev)
remote ${c_server} ${c_port}
proto $(uci -q get ${CONFIG}.${cfgid}.proto)
${_ca}
${_cert}
${_key}
${_proxy}
resolv-retry infinite
nobind
persist-key
persist-tun
auth-nocache
${_auth_user_pass}
${_tls_auth}
${_tls_crypt}
${_lzo}
${_route_nopull}
verb 3
up up.sh
down down.sh
script-security 3
log openvpn.log
log-append openvpn.log
$(uci -q get ${CONFIG}.${cfgid}.extra_config)
EOF
sed -i '/^\s*$/d' ${TMP_OVPN_PATH}/${cfgid}/client.conf >/dev/null 2>&1
procd_open_instance "${CONFIG}_${cfgid}"
procd_set_param command "${PROG}" \
--cd "${TMP_OVPN_PATH}/${cfgid}" \
--config "client.conf"
procd_set_param file "${TMP_OVPN_PATH}/${cfgid}/client.conf"
procd_set_param term_timeout 15
procd_set_param respawn
procd_append_param respawn 3600
procd_append_param respawn 5
procd_append_param respawn -1
procd_close_instance
}
stop_instance() {
local cfgid=${1}
[ -d "${TMP_OVPN_PATH}/${cfgid}" ] && {
"${TMP_OVPN_PATH}/${cfgid}/down.sh" >/dev/null 2>&1
}
top -bn1 | grep "${TMP_OVPN_PATH}/${cfgid}" | grep -v "grep" | awk '{print $1}' | xargs kill -2 >/dev/null 2>&1
sed -i "/${cfgid}/d" /var/etc/${CONFIG}.include >/dev/null 2>&1
rm -rf ${TMP_OVPN_PATH}/${cfgid}
}
start_instance_all() {
local _clients=$(uci -q show ${CONFIG} | grep "=clients" | cut -d '.' -sf2 | cut -d '=' -sf 1)
[ -n "${_clients}" ] && {
mkdir -p ${TMP_OVPN_PATH}
for _client in ${_clients}; do
start_instance ${_client}
done
}
}
stop_instance_all() {
[ -d "${TMP_OVPN_PATH}" ] && {
for cfgid in $(ls ${TMP_OVPN_PATH}); do
"${TMP_OVPN_PATH}/${cfgid}/down.sh" >/dev/null 2>&1
done
}
top -bn1 | grep "${TMP_OVPN_PATH}" | grep -v "grep" | awk '{print $1}' | xargs kill -2 >/dev/null 2>&1
rm -rf /var/etc/${CONFIG}.include
rm -rf ${TMP_OVPN_PATH}
}
start_service() {
local cfgid=${1}
if [ -n "${cfgid}" ]; then
start_instance ${cfgid}
else
start_instance_all
fi
}
stop_service() {
local cfgid=${1}
if [ -n "${cfgid}" ]; then
stop_instance ${cfgid}
else
stop_instance_all
fi
}
reload_service() {
restart
}
service_triggers() {
procd_add_reload_trigger "${CONFIG}"
}

View File

@ -0,0 +1,12 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete firewall.openvpn_client
set firewall.openvpn_client=include
set firewall.openvpn_client.type=script
set firewall.openvpn_client.path=/var/etc/luci-app-openvpn-client.include
set firewall.openvpn_client.reload=1
EOF
rm -rf /tmp/luci-*cache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-openvpn-client": {
"description": "Grant UCI access for luci-app-openvpn-client",
"read": {
"uci": [ "luci-app-openvpn-client" ]
},
"write": {
"uci": [ "luci-app-openvpn-client" ]
}
}
}