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 <mail@david-bauer.net>
This commit is contained in:
David Bauer 2020-08-16 18:03:21 +02:00
parent 17dd5abd75
commit 98a1c196ed
12 changed files with 160 additions and 68 deletions

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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')

View File

@ -1,7 +1,47 @@
local uci = require('simple-uci').cursor()
local util = require 'gluon.util'
local M = {}
function M.get_mesh_vpn_interface()
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

View File

@ -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,

View File

@ -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

View File

@ -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',

View File

@ -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

View File

@ -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