Wireguard support - take 2. (#1056)

This commit is contained in:
Tim Wilkinson 2024-01-07 16:17:52 -08:00 committed by GitHub
parent 757ec56ada
commit e486a61cc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 66 deletions

View File

@ -2,9 +2,14 @@
vtunduciport=$(uci get vtun.@options[0].port 2>/dev/null)
vtundport=${vtunduciport:-5525}
nft insert rule ip fw4 input_wan udp dport $vtundport accept comment \"Wireguard\"
if [ "$(/sbin/uci -q get aredn.@tunnel[0].wanonly)" != "0" ]; then
nft insert rule ip fw4 output_wifi udp dport $vtundport reject comment \"Wireguard\"
nft insert rule ip fw4 output_dtdlink udp dport $vtundport reject comment \"Wireguard\"
issupernode=$(uci get aredn.@supernode[0].enable 2>/dev/null)
if [ "$issupernode" = "1" ]; then
vtundport=$(($vtundport+1000))
fi
vtundportend=$(($vtundport+128))
nft insert rule ip fw4 input_wan udp dport $vtundport-$vtundportend accept comment \"Wireguard\"
if [ "$(/sbin/uci -q get aredn.@tunnel[0].wanonly)" != "0" ]; then
nft insert rule ip fw4 output_wifi udp dport $vtundport-$vtundportend reject comment \"Wireguard\"
nft insert rule ip fw4 output_dtdlink udp dport $vtundport-$vtundportend reject comment \"Wireguard\"
fi

View File

@ -1,11 +0,0 @@
#! /bin/sh
if [ "$(/sbin/uci -c /etc/config.mesh -q get wireguard.@wireguard_server[0].public)" = "" -a -f /usr/bin/wg ]; then
private=$(/usr/bin/wg genkey)
public=$(echo $private | /usr/bin/wg pubkey)
touch /etc/config.mesh/wireguard
/sbin/uci -q -c /etc/config.mesh add wireguard wireguard_server
/sbin/uci -q -c /etc/config.mesh set wireguard.@wireguard_server[0].private=$private
/sbin/uci -q -c /etc/config.mesh set wireguard.@wireguard_server[0].public=$public
/sbin/uci -q -c /etc/config.mesh set wireguard.@wireguard_server[0].masksize=26
/sbin/uci -q -c /etc/config.mesh commit wireguard
fi

View File

@ -482,44 +482,40 @@ cm:foreach("vtun", "client",
end
)
local wgclients = 0
local wgport = tonumber(tun_port or 5525)
if is_supernode then
wgport = wgport + 1000
end
cm:foreach("wireguard", "client",
function(s)
if s.enabled == "1" then
local client_priv, client_pub = s.key:match("^(.+=)(.+=)$")
local server_priv, _, _, client_pub = s.key:match("^(.+=)(.+=)(.+=)(.+=)$")
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config wireguard_wgc\n\toption public_key '%s'\n\toption persistent_keepalive '25'\n\tlist allowed_ips '0.0.0.0/0'\n\n",
client_pub)
string.format("config interface 'wgc%d'\n\toption proto 'wireguard'\n\toption private_key '%s'\n\toption nohostroute '1'\n\toption listen_port '%s'\n\tlist addresses '%s'\n\n",
wgclients, server_priv, wgport, s.clientip)
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config wireguard_wgc%d\n\toption public_key '%s'\n\toption persistent_keepalive '25'\n\tlist allowed_ips '0.0.0.0/0'\n\n",
wgclients, client_pub)
wgclients = wgclients + 1
end
wgport = wgport + 1
end
)
if wgclients > 0 then
local private = cm:get("wireguard", "@wireguard_server[0]", "private")
local mask_size = tonumber(cm:get("wireguard", "@wireguard_server[0]", "masksize") or 26)
local ab, c, d = tun_start:match("^(%d+%.%d+%.)(%d+)%.(%d+)$")
c = tonumber(c) + 1
if c > 255 then
c = 0
end
d = nixio.bit.band(tonumber(d), nixio.bit.lshift(255, 32 - mask_size)) + 1
cfg.wireguard_network_config =
string.format("config interface 'wgc'\n\toption proto 'wireguard'\n\toption private_key '%s'\n\toption nohostroute '1'\n\toption listen_port '%s'\n\tlist addresses '%s'\n\n",
private, (tun_port or 5525), (ab .. c .. "." .. d)) ..
cfg.wireguard_network_config
end
local vtunservers = 0
local wgservers = 0
cm:foreach("vtun", "server",
function(s)
if s.enabled == "1" then
if s.netip:match("/") then
if s.netip:match(":") then
local server_pub, client_priv, client_pub = s.passwd:match("^(.+=)(.+=)(.+=)$")
local abc, d, p = s.netip:match("^(%d+%.%d+%.%d+)%.(%d+):(%d+)")
d = tonumber(d) + 1
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config interface 'wgs%d'\n\toption proto 'wireguard'\n\toption private_key '%s'\n\toption nohostroute '1'\n\tlist addresses '%s'\n\n",
wgservers, client_priv, s.netip:match("^(.+)/"))
wgservers, client_priv,(abc .. "." .. d))
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config wireguard_wgs%d\n\toption public_key '%s'\n\toption endpoint_host '%s'\n\toption endpoint_port '%s'\n\toption persistent_keepalive '25'\n\tlist allowed_ips '0.0.0.0/0'\n\n",
wgservers, server_pub, s.host, (tun_port or 5525))
wgservers, server_pub, s.host, p)
wgservers = wgservers + 1
else
cfg.tun_network_config = cfg.tun_network_config ..
@ -938,8 +934,13 @@ if nixio.fs.access("/etc/config.mesh/olsrd", "r") then
do
of:write("\tlist interface 'tun" .. dev .. "'\n")
end
if wgclients + wgservers > 0 then
of:write("\tlist interface 'wgc'\n")
if wgclients > 0 then
for dev = 0, wgclients - 1
do
of:write("\tlist interface 'wgc" .. dev .. "'\n")
end
end
if wgservers > 0 then
for dev = 0, wgservers - 1
do
of:write("\tlist interface 'wgs" .. dev .. "'\n")

View File

@ -71,9 +71,8 @@ if os.getenv("REQUEST_METHOD") == "POST" then
end
-- wireguard
local wireguard_mask_size = tonumber(cursor:get("wireguard", "@wireguard_server[0]", "masksize") or 26)
local wireguard_max = nixio.bit.lshift(1, 32 - wireguard_mask_size)
local wireguard_alive_time = 300 -- 5 minutes
local active_wgtun = {}
-- helpers start
@ -133,9 +132,8 @@ function is_tunnel_active(ip, tunnels)
return false
end
function is_wgtunnel_active(key, wgtunnels)
local key = key:match("^.*=(.*=)$")
local v = wgtunnels[key]
function is_wgtunnel_active(client_pub)
local v = active_wgtun[client_pub]
if v and v + wireguard_alive_time > os.time() then
return true
end
@ -162,8 +160,7 @@ function get_wireguard_network_address(netw)
if c > 255 then
c = 0
end
local d = nixio.bit.band(netw[4], nixio.bit.lshift(255, 32 - wireguard_mask_size))
return { netw[1], netw[2], c, d, wireguard_mask_size }
return { netw[1], netw[2], c, netw[4] }
end
function get_server_dns()
@ -171,11 +168,6 @@ function get_server_dns()
return dns and dns or ""
end
function get_wireguard_public()
local wg = cursor:get("wireguard", "@wireguard_server[0]", "public")
return wg or ""
end
-- helper end
-- load client info from uci
@ -255,7 +247,6 @@ end
local netw = get_server_network_address()
local netwg = get_wireguard_network_address(netw)
local dns = get_server_dns()
local wireguard_public = get_wireguard_public()
-- if RESET or FIRST TIME load client/servers from file into parms
if parms.button_reset or not parms.reload then
@ -265,7 +256,6 @@ if parms.button_reset or not parms.reload then
parms.server_net1 = netw[3]
parms.server_net2 = netw[4]
parms.dns = dns
parms.wireguard_public = wireguard_public
-- initialize the "add" entries to clear them
parms.client_add_enabled = "0"
parms.client_add_name = ""
@ -397,15 +387,18 @@ do
end
if key == "" then
local priv = capture("/usr/bin/wg genkey"):match("(%S+)")
local pub = capture("echo " .. priv .. " | /usr/bin/wg pubkey"):match("(%S+)")
key = priv .. pub
local privS = capture("/usr/bin/wg genkey"):match("(%S+)")
local pubS = capture("echo " .. privS .. " | /usr/bin/wg pubkey"):match("(%S+)")
local privC = capture("/usr/bin/wg genkey"):match("(%S+)")
local pubC = capture("echo " .. privC .. " | /usr/bin/wg pubkey"):match("(%S+)")
key = privS .. pubS .. privC .. pubC
end
parms["wgclient" .. wgclient_num .. "_enabled"] = enabled
parms["wgclient" .. wgclient_num .. "_name"] = name:upper()
parms["wgclient" .. wgclient_num .. "_key"] = key
parms["wgclient" .. wgclient_num .. "_clientip"] = clientip
parms["wgclient" .. wgclient_num .. "_port"] = port
parms["wgclient" .. wgclient_num .. "_contact"] = contact
-- commit the data from this client
@ -508,7 +501,7 @@ if parms.button_save and #cli_err == 0 then
end
local active_tun = get_active_tun()
local active_wgtun = get_active_wgtun()
active_wgtun = get_active_wgtun()
-- generate the page
@ -577,10 +570,9 @@ if config == "mesh" then
html.print("<br /><tr class=tun_network_row><td colspan=6 valign=top><div style='display:inline-block;width:175px;padding-left:50px'>Tunnel Server Network:</div>")
html.print(netw[1] .. "." .. netw[2] .. ".<input type='text' name='server_net1' size='3' maxlen='3' value='" .. netw[3] .. "' onChange='form.submit()' title='from 0-255' >.<input type='text' name='server_net2' size='3' maxlen='3' value='" .. netw[4] .. "' onChange='form.submit()' title='from 0-255 in multiples of 4. (ie. 0,4,8,12,16...252)' >")
html.print("<br /><div style='display:inline-block;width:175px;padding:2px 0 0 50px'>Wireguard Server Network:</div>")
html.print(netwg[1] .. "." .. netwg[2] .. "." .. netwg[3] .. "." .. netwg[4] .. "/" .. netwg[5])
html.print(netwg[1] .. "." .. netwg[2] .. "." .. netwg[3] .. "." .. netwg[4])
html.print("<br /><hr>Tunnel Server DNS Name: ")
html.print("<input type='text' name='dns' size='30' value='" .. dns .. "' onChange='form.submit()' ></td></tr>")
html.print("<input type='hidden' name='wireguard_public' value='" .. wireguard_public .. "'>")
html.print("</table>")
html.print("<table cellpadding=0 cellspacing=0>")
@ -643,7 +635,7 @@ if config == "mesh" then
local lastnet = netw[4] + net * 4
local fullnet = netw[1] .. "." .. netw[2] .. "." .. netw[3] .. "." .. lastnet
html.print("<td rowspan='2' class='tun_client_center_item'>")
html.print("<input style='min-width:90px;background-color:transparent;border:0;text-align:center;' readonly type=text size=16 name=client" .. val .. "_netip value='" .. fullnet .. "'/></td>")
html.print("<input style='min-width:90px;background-color:transparent;border:0;text-align:center;' readonly type=text size=20 name=client" .. val .. "_netip value='" .. fullnet .. "'/></td>")
html.print("<td rowspan='2' class='tun_client_center_item' align=center>&nbsp;")
if val ~= "_add" and is_tunnel_active(fullnet, active_tun) then
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
@ -682,7 +674,11 @@ if config == "mesh" then
html.print("<tr><th>Enabled?</th><th>Client</th><th>Key</th><th>Client</th><th>Active&nbsp;</td><th>Action</th></tr>")
local keys = { "enabled", "name", "contact", "key" }
local cnum = 1
local cnum = 0
local wg_port = tonumber(cursor:get("vtun", "@options[0]", "port") or 5525)
if cursor:get("aredn", "@supernode[0]", "enable") == "1" then
wg_port = wg_port + 1000
end
for val = 0, wgclient_num
do
if val == wgclient_num then
@ -708,14 +704,15 @@ if config == "mesh" then
end
html.print(" title='client name'></td>")
html.print("<td>")
html.print("<input type=" .. (val == '_add' and 'hidden' or 'text') .. " readonly size=25 oncopy='return false' name=wgclient" .. val .. "_key value='" .. key .. "' title='client key'>")
html.print("<input type=" .. (val == '_add' and 'hidden' or 'text') .. " readonly size=25 oncopy='return false' onmousedown='return false' name=wgclient" .. val .. "_key value='" .. key .. "' title='client key'>")
html.print("</td>")
local fullnet = netwg[1] .. "." .. netwg[2] .. "." .. netwg[3] .. "." .. (netwg[4] + 1 + cnum) .. "/" .. netwg[5]
local fullnet = netwg[1] .. "." .. netwg[2] .. "." .. netwg[3] .. "." .. (netwg[4] + 2 * cnum) .. ":" .. (wg_port + val)
html.print("<td rowspan='2' class='tun_client_center_item'>")
html.print("<input style='min-width:90px;background-color:transparent;border:0;text-align:center;' readonly type=text size=16 name=wgclient" .. val .. "_clientip value='" .. fullnet:match("^(.+)/") .. "'/></td>")
html.print("<input style='min-width:90px;background-color:transparent;border:0;text-align:center;' readonly type=text size=20 name=wgclient" .. val .. "_clientip value='" .. fullnet .. "'/></td>")
html.print("<td rowspan='2' class='tun_client_center_item' align=center>&nbsp;")
if val ~= "_add" and is_wgtunnel_active(key, active_wgtun) then
local _, server_pub, client_priv, client_pub = key:match("^(.+=)(.+=)(.+=)(.+=)$")
if val ~= "_add" and is_wgtunnel_active(client_pub) then
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
else
html.print("<img class='tun_client_inactive_img' src='/disconnected.png' title='Not connected' />")
@ -725,7 +722,7 @@ if config == "mesh" then
html.print("<td rowspan='2' class='tun_client_center_item'><input type=submit name=wgclient_add value=Add title='Add this client'></td>")
else
html.print("<td rowspan='2' class='tun_client_center_item tun_client_mailto' id=wgclient" .. val .. "_email>")
html.print("<a href='mailto:?subject=AREDN%20Tunnel%20Connection&body=Your%20connection%20details:%0D%0AName:%20" .. name .. "%0D%0APassword:%20" .. wireguard_public .. key .. "%0D%0ANetwork:%20" .. fullnet .. "%0D%0AServer%20address:%20" .. dns .. "' target='_blank'>")
html.print("<a href='mailto:?subject=AREDN%20Tunnel%20Connection&body=Your%20connection%20details:%0D%0AName:%20" .. name .. "%0D%0APassword:%20" .. (server_pub .. client_priv .. client_pub) .. "%0D%0ANetwork:%20" .. fullnet .. "%0D%0AServer%20address:%20" .. dns .. "' target='_blank'>")
html.print("<img class='tun_client_mailto_img' src='/email.png' title='Email details' /></a></td>")
end
html.print("</tr><tr class='tun_client_list1 tun_client_row tun_loading_css_comment'><td colspan='2' align='right'>Contact Info/Comment (Optional): <input type=text maxlength='50' size=40 name=wgclient" .. val .. "_contact value='" .. (contact or "") .."'")

View File

@ -270,7 +270,7 @@ do
err(val .. " this connection must be added or cleared out before saving changes")
break
end
if netip:match("/") then
if netip:match(":") then
if not passwd:match("^.+=.+=.+=$") then
err("The password is not a wireguard key")
end