luci/protocols/luci-proto-wireguard/root/usr/libexec/rpcd/luci.wireguard
Paul Dee 8a9dbe39d5 luci-proto-wireguard: display interface public key
Signed-off-by: Paul Dee <itsascambutmailmeanyway@gmail.com>
2021-11-11 01:31:43 +01:00

194 lines
4.6 KiB
Lua
Executable file

#!/usr/bin/env lua
local json = require "luci.jsonc"
local util = require "luci.util"
local sys = require "luci.sys"
local io = require "io"
local uci = require "uci"
local fs = require "nixio.fs"
local methods = {
generateKeyPair = {
call = function()
local prv = sys.exec("wg genkey 2>/dev/null"):sub(1, -2)
local pub = sys.exec("echo %s | wg pubkey 2>/dev/null" % util.shellquote(prv)):sub(1, -2)
return {keys = {priv = prv, pub = pub}}
end
},
getPublicAndPrivateKeyFromPrivate = {
args = {privkey = "privkey"},
call = function(args)
local pubkey = sys.exec("echo %s | wg pubkey 2>/dev/null" % util.shellquote(args.privkey)):sub(1, -2)
return {keys = {priv = args.privkey, pub = pubkey}}
end
},
generateQrCode = {
args = {privkey = "privkey", psk = "psk", allowed_ips = {"allowed_ips"}},
call = function(args)
local qr_code
if fs.access("/usr/bin/qrencode") then
local psk = args.psk
local listen_port = args.listen_port
local allowed_ips = args.allowed_ips
local pubkey = sys.exec("echo %s | wg pubkey 2>/dev/null" % util.shellquote(args.privkey)):sub(1, -2)
local client_privkey = sys.exec("wg genkey 2>/dev/null"):sub(1, -2)
local iface_qr = {
"[Interface]",
"PrivateKey = " .. client_privkey,
}
local peer_qr = {
"[Peer]",
"PublicKey = " .. pubkey,
}
if not allowed_ips or next(allowed_ips) == nil then
allowed_ips = {"0.0.0.0/0", "::/0"}
end
table.insert(peer_qr, "AllowedIPs = " .. table.concat(allowed_ips, ", "))
if psk then
table.insert(peer_qr, "PresharedKey = " .. psk)
end
qr_enc = table.concat(iface_qr, "\n") .. "\n\n" .. table.concat(peer_qr, "\n")
qr_code = sys.exec("/usr/bin/qrencode --inline --8bit --type=SVG --output=- %s 2>/dev/null" % util.shellquote(qr_enc))
end
return {qr_code = qr_code}
end
},
getWgInstances = {
call = function()
local data = {}
local last_device = ""
local qr_pubkey = {}
local wg_dump = io.popen("wg show all dump 2>/dev/null")
if wg_dump then
local line
for line in wg_dump:lines() do
local line = string.split(line, "\t")
if not (last_device == line[1]) then
last_device = line[1]
data[line[1]] = {
name = line[1],
public_key = line[3],
listen_port = line[4],
fwmark = line[5],
peers = {}
}
if not line[3] or line[3] == "" or line[3] == "(none)" then
qr_pubkey[line[1]] = ""
else
qr_pubkey[line[1]] = "PublicKey = " .. line[3]
end
else
local peer_name
local cur = uci.cursor()
cur:foreach(
"network",
"wireguard_" .. line[1],
function(s)
if s.public_key == line[2] then
peer_name = s.description
end
end
)
local peer = {
name = peer_name,
public_key = line[2],
endpoint = line[4],
allowed_ips = {},
latest_handshake = line[6],
transfer_rx = line[7],
transfer_tx = line[8],
persistent_keepalive = line[9]
}
if not (line[4] == "(none)") then
local ipkey, ipvalue
for ipkey, ipvalue in pairs(string.split(line[5], ",")) do
if #ipvalue > 0 then
table.insert(peer["allowed_ips"], ipvalue)
end
end
end
table.insert(data[line[1]].peers, peer)
end
end
end
return data
end
}
}
local function parseInput()
local parse = json.new()
local done, err
while true do
local chunk = io.read(4096)
if not chunk then
break
elseif not done and not err then
done, err = parse:parse(chunk)
end
end
if not done then
print(json.stringify({error = err or "Incomplete input"}))
os.exit(1)
end
return parse:get()
end
local function validateArgs(func, uargs)
local method = methods[func]
if not method then
print(json.stringify({error = "Method not found"}))
os.exit(1)
end
if type(uargs) ~= "table" then
print(json.stringify({error = "Invalid arguments"}))
os.exit(1)
end
uargs.ubus_rpc_session = nil
local k, v
local margs = method.args or {}
for k, v in pairs(uargs) do
if margs[k] == nil or (v ~= nil and type(v) ~= type(margs[k])) then
print(json.stringify({error = "Invalid arguments"}))
os.exit(1)
end
end
return method
end
if arg[1] == "list" then
local _, method, rv = nil, nil, {}
for _, method in pairs(methods) do
rv[_] = method.args or {}
end
print((json.stringify(rv):gsub(":%[%]", ":{}")))
elseif arg[1] == "call" then
local args = parseInput()
local method = validateArgs(arg[2], args)
local result, code = method.call(args)
print((json.stringify(result):gsub("^%[%]$", "{}")))
os.exit(code or 0)
end