From 98a1c196ed8d76c0449ed85f291b4fac1ace9467 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sun, 16 Aug 2020 18:03:21 +0200 Subject: [PATCH] mesh-vpn: fully abstract VPN methods This fully abstracts VPN methods, making gluon-mesh-vpn-fastd and gluon-mesh-vpn-tunneldigger completely self-contained. Provide a LUA interface for generic interacting with VPN methods in gluon-mesh-vpn-core and web packages. This also adds the ability to install tunneldigger and fastd to the same image, selecting the VPN method based on the selected domain. Signed-off-by: David Bauer --- .../config-mode/reboot/0100-mesh-vpn.lua | 27 +++++------- .../config-mode/wizard/0300-mesh-vpn.lua | 8 ++-- .../luasrc/lib/gluon/mesh-vpn/update-config | 43 +++++------------- .../luasrc/lib/gluon/upgrade/500-mesh-vpn | 11 ++--- .../luasrc/usr/lib/lua/gluon/mesh-vpn.lua | 44 ++++++++++++++++++- .../lib/gluon/mesh-vpn/{ => provider}/fastd | 0 .../lib/gluon/upgrade/400-mesh-vpn-fastd | 3 +- .../lib/lua/gluon/mesh-vpn/provider/fastd.lua | 36 +++++++++++++++ .../mesh-vpn/{ => provider}/tunneldigger | 0 .../gluon/upgrade/400-mesh-vpn-tunneldigger | 3 +- .../gluon/mesh-vpn/provider/tunneldigger.lua | 42 ++++++++++++++++++ .../gluon/config-mode/view/admin/info.html | 11 +++-- 12 files changed, 160 insertions(+), 68 deletions(-) rename package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/{ => provider}/fastd (100%) create mode 100644 package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua rename package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/{ => provider}/tunneldigger (100%) create mode 100644 package/gluon-mesh-vpn-tunneldigger/luasrc/lib/lua/gluon/mesh-vpn/provider/tunneldigger.lua diff --git a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua index b94d194a..31403ddb 100644 --- a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua +++ b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua @@ -1,20 +1,14 @@ local site_i18n = i18n 'gluon-site' local uci = require("simple-uci").cursor() -local unistd = require 'posix.unistd' local platform = require 'gluon.platform' local site = require 'gluon.site' local sysconfig = require 'gluon.sysconfig' -local util = require "gluon.util" +local vpn = require 'gluon.mesh-vpn' local pretty_hostname = require 'pretty_hostname' - -local has_fastd = unistd.access('/lib/gluon/mesh-vpn/fastd') -local has_tunneldigger = unistd.access('/lib/gluon/mesh-vpn/tunneldigger') - - local hostname = pretty_hostname.get(uci) local contact = uci:get_first("gluon-node-info", "owner", "contact") @@ -22,19 +16,18 @@ local pubkey local msg -if has_tunneldigger then - local tunneldigger_enabled = uci:get_bool("tunneldigger", "mesh_vpn", "enabled") - if not tunneldigger_enabled then - msg = site_i18n._translate('gluon-config-mode:novpn') +if vpn.enabled() then + local _, active_vpn = vpn.get_active_provider() + + if active_vpn ~= nil then + pubkey = active_vpn.public_key() end -elseif has_fastd then - local fastd_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled") - if fastd_enabled then - pubkey = util.trim(util.exec("/etc/init.d/fastd show_key mesh_vpn")) + + if pubkey ~= nil then msg = site_i18n._translate('gluon-config-mode:pubkey') - else - msg = site_i18n._translate('gluon-config-mode:novpn') end +else + msg = site_i18n._translate('gluon-config-mode:novpn') end if not msg then return end diff --git a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua index 70a1307b..bdd091ee 100644 --- a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua +++ b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua @@ -1,10 +1,8 @@ -local unistd = require 'posix.unistd' - -local has_fastd = unistd.access('/lib/gluon/mesh-vpn/fastd') -local has_tunneldigger = unistd.access('/lib/gluon/mesh-vpn/tunneldigger') +local vpn = require 'gluon.mesh-vpn' +local _, active_vpn = vpn.get_active_provider() return function(form, uci) - if not (has_fastd or has_tunneldigger) then + if active_vpn == nil then return end diff --git a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/mesh-vpn/update-config b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/mesh-vpn/update-config index 45ecc2d5..935d0b9a 100755 --- a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/mesh-vpn/update-config +++ b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/mesh-vpn/update-config @@ -1,14 +1,7 @@ #!/usr/bin/lua local uci = require('simple-uci').cursor() -local unistd = require 'posix.unistd' - -local vpn -if unistd.access('/lib/gluon/mesh-vpn/fastd') then - vpn = 'fastd' -elseif unistd.access('/lib/gluon/mesh-vpn/tunneldigger') then - vpn = 'tunneldigger' -end +local vpn_name, vpn = require('gluon.mesh-vpn').get_active_provider() local vpn_config = { enabled = uci:get_bool('gluon', 'mesh_vpn', 'enabled'), @@ -17,32 +10,20 @@ local vpn_config = { limit_ingress = uci:get('gluon', 'mesh_vpn', 'limit_ingress'), } -uci:delete('simple-tc', 'mesh_vpn') -uci:section('simple-tc', 'interface', 'mesh_vpn', { - ifname = 'mesh-vpn', - enabled = vpn_config.limit_enabled, - limit_egress = vpn_config.limit_egress, -}) - -if vpn == 'fastd' then - uci:set('fastd', 'mesh_vpn', 'enabled', vpn_config.enabled) - uci:set('simple-tc', 'mesh_vpn', 'limit_ingress', vpn_config.limit_ingress) -else +if vpn_name ~= 'fastd' then uci:set('fastd', 'mesh_vpn', 'enabled', false) + uci:save('fastd') end -uci:save('fastd') -if vpn == 'tunneldigger' then - uci:set('tunneldigger', 'mesh_vpn', 'enabled', vpn_config.enabled) - - if vpn_config.limit_enabled then - uci:set('tunneldigger', 'mesh_vpn', 'limit_bw_down', vpn_config.limit_ingress) - else - uci:delete('tunneldigger', 'mesh_vpn', 'limit_bw_down') - end -else +if vpn_name ~= 'tunneldigger' then uci:set('tunneldigger', 'mesh_vpn', 'enabled', false) + uci:save('tunneldigger') +end + +vpn.enable(vpn_config.enabled) +if vpn_config.limit_enabled then + vpn.set_limit(vpn_config.limit_ingress, vpn_config.limit_egress) +else + vpn.set_limit(nil, nil) end -uci:save('tunneldigger') -uci:save('simple-tc') diff --git a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn index 019b9afb..58bfa30e 100755 --- a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn +++ b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn @@ -5,11 +5,11 @@ local users = require 'gluon.users' local util = require 'gluon.util' local uci = require('simple-uci').cursor() -local unistd = require 'posix.unistd' +local vpn_core = require 'gluon.mesh-vpn' uci:section('network', 'interface', 'mesh_vpn', { - ifname = 'mesh-vpn', + ifname = vpn_core.get_interface(), proto = 'gluon_mesh', transitive = true, fixed_mtu = true, @@ -35,12 +35,7 @@ uci:save('firewall') -- VPN migration if not uci:get('gluon', 'mesh_vpn') then - local vpn - if unistd.access('/lib/gluon/mesh-vpn/fastd') then - vpn = 'fastd' - elseif unistd.access('/lib/gluon/mesh-vpn/tunneldigger') then - vpn = 'tunneldigger' - end + local vpn, _ = vpn_core.get_active_provider() local fastd_enabled = uci:get('fastd', 'mesh_vpn', 'enabled') local tunneldigger_enabled = uci:get('tunneldigger', 'mesh_vpn', 'enabled') diff --git a/package/gluon-mesh-vpn-core/luasrc/usr/lib/lua/gluon/mesh-vpn.lua b/package/gluon-mesh-vpn-core/luasrc/usr/lib/lua/gluon/mesh-vpn.lua index 99d856c7..dc5f45c0 100644 --- a/package/gluon-mesh-vpn-core/luasrc/usr/lib/lua/gluon/mesh-vpn.lua +++ b/package/gluon-mesh-vpn-core/luasrc/usr/lib/lua/gluon/mesh-vpn.lua @@ -1,7 +1,47 @@ +local uci = require('simple-uci').cursor() + +local util = require 'gluon.util' + local M = {} -function M.get_mesh_vpn_interface() - return 'mesh-vpn' +function M.enabled() + return uci:get_bool('gluon', 'mesh_vpn', 'enabled') +end + +function M.enable(val) + return uci:set('gluon', 'mesh_vpn', 'enabled', val) +end + +function M.get_interface() + return 'mesh-vpn' +end + +function M.get_provider(name) + return require('gluon.mesh-vpn.provider.' .. name) +end + +function M.get_provider_names() + local out = {} + + for _, v in ipairs(util.glob('/lib/gluon/mesh-vpn/provider/*')) do + table.insert(out, v:match('([^/]+)$')) + end + + return out +end + +function M.get_active_provider() + -- Active provider is the provider in use + -- by the currently active site / domain + + for _, name in ipairs(M.get_provider_names()) do + local provider = M.get_provider(name) + if provider.active() then + return name, provider + end + end + + return nil, nil end return M diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/fastd b/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/provider/fastd similarity index 100% rename from package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/fastd rename to package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/provider/fastd diff --git a/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd index 0312b29c..b59ef2c7 100755 --- a/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd +++ b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd @@ -2,6 +2,7 @@ local site = require 'gluon.site' local util = require 'gluon.util' +local vpn_core = require 'gluon.mesh-vpn' local uci = require('simple-uci').cursor() @@ -37,7 +38,7 @@ end uci:section('fastd', 'fastd', 'mesh_vpn', { group = 'gluon-mesh-vpn', syslog_level = syslog_level, - interface = 'mesh-vpn', + interface = vpn_core.get_interface(), mode = 'tap', mtu = site.mesh_vpn.mtu(), secure_handshakes = true, diff --git a/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua new file mode 100644 index 00000000..1d628dc7 --- /dev/null +++ b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua @@ -0,0 +1,36 @@ +local uci = require('simple-uci').cursor() + +local site = require 'gluon.site' +local util = require 'gluon.util' +local vpn_core = require 'gluon.mesh-vpn' + +local M = {} + +function M.public_key() + return util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn')) +end + +function M.enable(val) + uci:set('fastd', 'mesh_vpn', 'enabled', val) + uci:save('fastd') +end + +function M.active() + return site.mesh_vpn.fastd() ~= nil +end + +function M.set_limit(ingress_limit, egress_limit) + uci:delete('simple-tc', 'mesh_vpn') + if ingress_limit ~= nil and egress_limit ~= nil then + uci:section('simple-tc', 'interface', 'mesh_vpn', { + ifname = vpn_core.get_interface(), + enabled = true, + limit_egress = egress_limit, + limit_ingress = ingress_limit, + }) + end + + uci:save('simple-tc') +end + +return M diff --git a/package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/tunneldigger b/package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/provider/tunneldigger similarity index 100% rename from package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/tunneldigger rename to package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/provider/tunneldigger diff --git a/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger index b91288a2..b37bb476 100755 --- a/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger +++ b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger @@ -2,6 +2,7 @@ local site = require 'gluon.site' local util = require 'gluon.util' +local vpn_core = require 'gluon.mesh-vpn' local uci = require('simple-uci').cursor() @@ -23,7 +24,7 @@ end uci:section('tunneldigger', 'broker', 'mesh_vpn', { enabled = enabled, uuid = util.node_id(), - interface = 'mesh-vpn', + interface = vpn_core.get_interface(), bind_interface = 'br-wan', group = 'gluon-mesh-vpn', broker_selection = 'usage', diff --git a/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/lua/gluon/mesh-vpn/provider/tunneldigger.lua b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/lua/gluon/mesh-vpn/provider/tunneldigger.lua new file mode 100644 index 00000000..d324a3cc --- /dev/null +++ b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/lua/gluon/mesh-vpn/provider/tunneldigger.lua @@ -0,0 +1,42 @@ +local uci = require('simple-uci').cursor() + +local site = require 'gluon.site' +local vpn_core = require 'gluon.mesh-vpn' + +local M = {} + +function M.public_key() + return nil +end + +function M.enable(val) + uci:set('tunneldigger', 'mesh_vpn', 'enabled', val) + uci:save('tunneldigger') +end + +function M.active() + return site.mesh_vpn.tunneldigger() ~= nil +end + +function M.set_limit(ingress_limit, egress_limit) + if ingress_limit ~= nil then + uci:set('tunneldigger', 'mesh_vpn', 'limit_bw_down', ingress_limit) + else + uci:delete('tunneldigger', 'mesh_vpn', 'limit_bw_down') + end + + if egress_limit ~= nil then + uci:section('simple-tc', 'interface', 'mesh_vpn', { + ifname = vpn_core.get_interface(), + enabled = true, + limit_egress = egress_limit, + }) + else + uci:delete('simple-tc', 'mesh_vpn') + end + + uci:save('tunneldigger') + uci:save('simple-tc') +end + +return M diff --git a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html index 5f3e9191..87c1179e 100644 --- a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html +++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html @@ -6,14 +6,19 @@ local sysconfig = require 'gluon.sysconfig' local platform = require 'gluon.platform' local util = require "gluon.util" + local has_vpn, vpn = pcall(require, 'gluon.mesh-vpn') local _ = translate local pubkey - local meshvpn_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled") - if meshvpn_enabled then - pubkey = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn')) + if has_vpn and vpn.enabled() then + local _, active_vpn = vpn.get_active_provider() + + if active_vpn ~= nil then + pubkey = active_vpn.public_key() + end + if pubkey == '' then pubkey = nil end