mirror of https://github.com/aredn/aredn.git
Wireguard tunnel support (#968)
* Wireguard tunnel support * Fix wireguard firewall rules * Add Wireguard tunnels to LQM * Filter vlans on main bridge * If you paste a tunnel config into any field, it will auto-populate all fields correctly * Fix bad password keyword * Fix bad feeds change * Fix bad merge
This commit is contained in:
parent
fb174ad66d
commit
bf3aa67f78
|
@ -14,6 +14,7 @@ CONFIG_PACKAGE_ATH_SPECTRAL=n
|
||||||
CONFIG_PACKAGE_ethtool=m
|
CONFIG_PACKAGE_ethtool=m
|
||||||
CONFIG_PACKAGE_iperf3=m
|
CONFIG_PACKAGE_iperf3=m
|
||||||
CONFIG_PACKAGE_libustream-mbedtls=m
|
CONFIG_PACKAGE_libustream-mbedtls=m
|
||||||
|
CONFIG_PACKAGE_kmod-wireguard=m
|
||||||
CONFIG_PACKAGE_vtun=m
|
CONFIG_PACKAGE_vtun=m
|
||||||
CONFIG_PACKAGE_wireguard=m
|
CONFIG_PACKAGE_wireguard=m
|
||||||
CONFIG_PACKAGE_wireguard-tools=m
|
CONFIG_PACKAGE_wireguard-tools=m
|
||||||
|
|
|
@ -86,7 +86,7 @@ CONFIG_PACKAGE_kmod-usb-storage=m
|
||||||
CONFIG_PACKAGE_kmod-usb-storage-uas=m
|
CONFIG_PACKAGE_kmod-usb-storage-uas=m
|
||||||
CONFIG_PACKAGE_kmod-usb-uhci=m
|
CONFIG_PACKAGE_kmod-usb-uhci=m
|
||||||
CONFIG_PACKAGE_kmod-usb-xhci-hcd=m
|
CONFIG_PACKAGE_kmod-usb-xhci-hcd=m
|
||||||
CONFIG_PACKAGE_kmod-wireguard=m
|
CONFIG_PACKAGE_kmod-wireguard=y
|
||||||
CONFIG_PACKAGE_libblkid=m
|
CONFIG_PACKAGE_libblkid=m
|
||||||
CONFIG_PACKAGE_libcomerr=m
|
CONFIG_PACKAGE_libcomerr=m
|
||||||
CONFIG_PACKAGE_libcurl=y
|
CONFIG_PACKAGE_libcurl=y
|
||||||
|
@ -150,8 +150,8 @@ CONFIG_PACKAGE_tcpdump-mini=m
|
||||||
CONFIG_PACKAGE_ubi-utils=y
|
CONFIG_PACKAGE_ubi-utils=y
|
||||||
CONFIG_PACKAGE_uhttpd=y
|
CONFIG_PACKAGE_uhttpd=y
|
||||||
CONFIG_PACKAGE_vtun=y
|
CONFIG_PACKAGE_vtun=y
|
||||||
CONFIG_PACKAGE_wireguard=m
|
CONFIG_PACKAGE_wireguard=y
|
||||||
CONFIG_PACKAGE_wireguard-tools=m
|
CONFIG_PACKAGE_wireguard-tools=y
|
||||||
CONFIG_PACKAGE_wpad-mini=y
|
CONFIG_PACKAGE_wpad-mini=y
|
||||||
CONFIG_PACKAGE_xinetd=n
|
CONFIG_PACKAGE_xinetd=n
|
||||||
CONFIG_PACKAGE_zlib=m
|
CONFIG_PACKAGE_zlib=m
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
src-git arednpackages https://github.com/kn6plv/aredn_packages;working
|
src-git arednpackages https://github.com/aredn/aredn_packages;develop
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
/etc/config.mesh/aliases.dmz
|
/etc/config.mesh/aliases.dmz
|
||||||
/etc/config.mesh/aliases.nat
|
/etc/config.mesh/aliases.nat
|
||||||
/etc/config.mesh/vtun
|
/etc/config.mesh/vtun
|
||||||
|
/etc/config.mesh/wireguard
|
||||||
/etc/config.mesh/network_tun
|
/etc/config.mesh/network_tun
|
||||||
/etc/config.mesh/aredn
|
/etc/config.mesh/aredn
|
||||||
/etc/config.mesh/xlink
|
/etc/config.mesh/xlink
|
||||||
|
|
|
@ -38,3 +38,6 @@ include /etc/config.mesh/xlink
|
||||||
|
|
||||||
### Tunnels devices
|
### Tunnels devices
|
||||||
include /etc/config.mesh/network_tun
|
include /etc/config.mesh/network_tun
|
||||||
|
|
||||||
|
### Wireguard
|
||||||
|
<wireguard_network_config>
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
||||||
if [ "$MESHFW_TUNNELS_ENABLED" != "1" ]; then
|
if [ "$MESHFW_TUNNELS_ENABLED" != "1" -a "$MESHFW_WG_TUNNELS_ENABLED" != "1" ]; then
|
||||||
exit 0;
|
exit 0;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -66,14 +66,17 @@ nft add chain ip fw4 reject_to_vpn
|
||||||
nft insert rule ip fw4 forward iifname "tun*" jump forward_vpn
|
nft insert rule ip fw4 forward iifname "tun*" jump forward_vpn
|
||||||
nft add rule ip fw4 input iifname "tun*" jump input_vpn
|
nft add rule ip fw4 input iifname "tun*" jump input_vpn
|
||||||
nft add rule ip fw4 output oifname "tun*" jump accept_vpn # instead of creating a output_vpn chain
|
nft add rule ip fw4 output oifname "tun*" jump accept_vpn # instead of creating a output_vpn chain
|
||||||
nft add rule ip fw4 input_vpn icmp type echo-request counter accept
|
nft insert rule ip fw4 forward iifname "wg*" jump forward_vpn
|
||||||
nft add rule ip fw4 input_vpn tcp dport 2222 counter accept
|
nft add rule ip fw4 input iifname "wg*" jump input_vpn
|
||||||
nft add rule ip fw4 input_vpn tcp dport 8080 counter accept
|
nft add rule ip fw4 output oifname "wg*" jump accept_vpn # instead of creating a output_vpn chain
|
||||||
nft add rule ip fw4 input_vpn tcp dport 80 counter accept
|
nft add rule ip fw4 input_vpn icmp type echo-request accept
|
||||||
nft add rule ip fw4 input_vpn udp dport 698 counter accept
|
nft add rule ip fw4 input_vpn tcp dport 2222 accept
|
||||||
nft add rule ip fw4 input_vpn tcp dport 23 counter accept
|
nft add rule ip fw4 input_vpn tcp dport 8080 accept
|
||||||
nft add rule ip fw4 input_vpn tcp dport 9090 counter accept
|
nft add rule ip fw4 input_vpn tcp dport 80 accept
|
||||||
nft add rule ip fw4 input_vpn udp dport 161 counter accept
|
nft add rule ip fw4 input_vpn udp dport 698 accept
|
||||||
|
nft add rule ip fw4 input_vpn tcp dport 23 accept
|
||||||
|
nft add rule ip fw4 input_vpn tcp dport 9090 accept
|
||||||
|
nft add rule ip fw4 input_vpn udp dport 161 accept
|
||||||
nft add rule ip fw4 input_vpn ct status dnat accept comment \"!vtun: Accept port redirections\"
|
nft add rule ip fw4 input_vpn ct status dnat accept comment \"!vtun: Accept port redirections\"
|
||||||
nft add rule ip fw4 input_vpn jump reject_vpn
|
nft add rule ip fw4 input_vpn jump reject_vpn
|
||||||
nft insert rule ip fw4 forward_vpn jump forwarding_vpn_rule
|
nft insert rule ip fw4 forward_vpn jump forwarding_vpn_rule
|
||||||
|
@ -92,6 +95,12 @@ nft add rule ip fw4 reject_vpn oifname "tun*" reject
|
||||||
nft add rule ip fw4 reject_vpn iifname "tun*" reject
|
nft add rule ip fw4 reject_vpn iifname "tun*" reject
|
||||||
nft add rule ip fw4 accept_to_vpn oifname "tun*" accept
|
nft add rule ip fw4 accept_to_vpn oifname "tun*" accept
|
||||||
nft add rule ip fw4 reject_to_vpn oifname "tun*" reject
|
nft add rule ip fw4 reject_to_vpn oifname "tun*" reject
|
||||||
|
nft add rule ip fw4 accept_vpn oifname "wg*" accept
|
||||||
|
nft add rule ip fw4 accept_vpn iifname "wg*" accept
|
||||||
|
nft add rule ip fw4 reject_vpn oifname "wg*" reject
|
||||||
|
nft add rule ip fw4 reject_vpn iifname "wg*" reject
|
||||||
|
nft add rule ip fw4 accept_to_vpn oifname "wg*" accept
|
||||||
|
nft add rule ip fw4 reject_to_vpn oifname "wg*" reject
|
||||||
nft insert rule ip fw4 forward_dtdlink jump accept_to_vpn
|
nft insert rule ip fw4 forward_dtdlink jump accept_to_vpn
|
||||||
nft insert rule ip fw4 forward_wifi jump accept_to_vpn
|
nft insert rule ip fw4 forward_wifi jump accept_to_vpn
|
||||||
nft insert rule ip fw4 forward_lan jump accept_to_vpn
|
nft insert rule ip fw4 forward_lan jump accept_to_vpn
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
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\"
|
||||||
|
fi
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /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
|
|
@ -55,6 +55,13 @@ then
|
||||||
else
|
else
|
||||||
export MESHFW_TUNNELS_ENABLED=0
|
export MESHFW_TUNNELS_ENABLED=0
|
||||||
fi
|
fi
|
||||||
|
# Is Wireguard 'enabled'
|
||||||
|
if [ -x "/usr/bin/wg" ]
|
||||||
|
then
|
||||||
|
export MESHFW_WG_TUNNELS_ENABLED=1
|
||||||
|
else
|
||||||
|
export MESHFW_WG_TUNNELS_ENABLED=0
|
||||||
|
fi
|
||||||
|
|
||||||
# Lets execute each include file
|
# Lets execute each include file
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ function canonical_hostname(hostname)
|
||||||
end
|
end
|
||||||
|
|
||||||
local cursor = uci.cursor()
|
local cursor = uci.cursor()
|
||||||
|
local cursorm = uci.cursor("/etc/config.mesh")
|
||||||
|
|
||||||
local myhostname = canonical_hostname(info.get_nvram("node") or "localnode")
|
local myhostname = canonical_hostname(info.get_nvram("node") or "localnode")
|
||||||
local myip = cursor:get("network", "wifi", "ipaddr")
|
local myip = cursor:get("network", "wifi", "ipaddr")
|
||||||
|
@ -377,6 +377,49 @@ function lqm()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Wireguard
|
||||||
|
cursorm:foreach("wireguard", "client",
|
||||||
|
function(s)
|
||||||
|
if s.enabled == "1" then
|
||||||
|
local a, b, c, d = s.clientip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
|
||||||
|
stations[#stations + 1] = {
|
||||||
|
type = "Tunnel",
|
||||||
|
device = "wgc",
|
||||||
|
signal = nil,
|
||||||
|
ip = s.clientip,
|
||||||
|
mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d),
|
||||||
|
tx_packets = 0,
|
||||||
|
tx_fail = 0,
|
||||||
|
tx_retries = 0,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
local wgs = 0
|
||||||
|
cursorm:foreach("vtun", "server",
|
||||||
|
function(s)
|
||||||
|
if s.enabled == "1" and s.netip:match("/") then
|
||||||
|
local a, b, c, d, m = s.netip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)/(%d+)$")
|
||||||
|
local d = nixio.bit.band(d, nixio.bit.lshift(255, 32 - m)) + 1
|
||||||
|
stations[#stations + 1] = {
|
||||||
|
type = "Tunnel",
|
||||||
|
device = "wgs" .. wgs,
|
||||||
|
signal = nil,
|
||||||
|
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||||
|
mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d),
|
||||||
|
tx_packets = 0,
|
||||||
|
tx_fail = 0,
|
||||||
|
tx_retries = 0,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
|
}
|
||||||
|
wgs = wgs + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
-- DtD
|
-- DtD
|
||||||
for _, entry in ipairs(arps)
|
for _, entry in ipairs(arps)
|
||||||
do
|
do
|
||||||
|
|
|
@ -70,6 +70,7 @@ end
|
||||||
-- helpers end
|
-- helpers end
|
||||||
|
|
||||||
local c = uci.cursor()
|
local c = uci.cursor()
|
||||||
|
local cm = uci.cursor("/etc/config.mesh")
|
||||||
|
|
||||||
-- validate args
|
-- validate args
|
||||||
local auto = false
|
local auto = false
|
||||||
|
@ -116,7 +117,9 @@ local cfg = {
|
||||||
wan_network_config = "",
|
wan_network_config = "",
|
||||||
dtdlink_network_config = "",
|
dtdlink_network_config = "",
|
||||||
wifi_network_config = "",
|
wifi_network_config = "",
|
||||||
olsrd_dtd_interface_mode = "ether"
|
olsrd_dtd_interface_mode = "ether",
|
||||||
|
tun_network_config = "",
|
||||||
|
wireguard_network_config = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function expand_vars(lines)
|
function expand_vars(lines)
|
||||||
|
@ -187,7 +190,7 @@ end
|
||||||
|
|
||||||
-- Supernode options
|
-- Supernode options
|
||||||
|
|
||||||
local is_supernode = (uci.cursor("/etc/config.mesh"):get("aredn", "@supernode[0]", "enable") == "1")
|
local is_supernode = (cm:get("aredn", "@supernode[0]", "enable") == "1")
|
||||||
if is_supernode then
|
if is_supernode then
|
||||||
cfg.olsrd_dtd_interface_mode = "isolated"
|
cfg.olsrd_dtd_interface_mode = "isolated"
|
||||||
end
|
end
|
||||||
|
@ -295,7 +298,7 @@ if do_basic then
|
||||||
list[port:gsub("%..*$", "")] = true
|
list[port:gsub("%..*$", "")] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local config = "config device\n option name 'br0'\n option type 'bridge'\n"
|
local config = "config device\n option name 'br0'\n option type 'bridge'\n option vlan_filtering '1'\n"
|
||||||
for port, _ in pairs(list)
|
for port, _ in pairs(list)
|
||||||
do
|
do
|
||||||
config = config .. " list ports '" .. port .. "'\n"
|
config = config .. " list ports '" .. port .. "'\n"
|
||||||
|
@ -415,10 +418,14 @@ if do_basic then
|
||||||
end
|
end
|
||||||
|
|
||||||
if not wireless then
|
if not wireless then
|
||||||
|
if #ports == 0 then
|
||||||
|
config = config .. " option bridge_empty '1'\n"
|
||||||
|
else
|
||||||
for _, port in ipairs(ports)
|
for _, port in ipairs(ports)
|
||||||
do
|
do
|
||||||
config = config .. " list ports '" .. port .. "'\n"
|
config = config .. " list ports '" .. port .. "'\n"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
config = config .. " option name '" .. ports[1] .. "'\n"
|
config = config .. " option name '" .. ports[1] .. "'\n"
|
||||||
if not ports[1]:match("^wlan") then
|
if not ports[1]:match("^wlan") then
|
||||||
|
@ -454,13 +461,86 @@ if do_basic then
|
||||||
cfg[net .. "_network_config"] = config
|
cfg[net .. "_network_config"] = config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Generate the tunnel configurations
|
||||||
|
local tun_port = cm:get("vtun", "@options[0]", "port")
|
||||||
|
if tun_port then
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. "config options\n\toption port '" .. tun_port .. "'\n\n"
|
||||||
|
end
|
||||||
|
local tun_start = cm:get("vtun", "@network[0]", "start")
|
||||||
|
local tun_dns = cm:get("vtun", "@network[0]", "dns")
|
||||||
|
if tun_start or tun_dns then
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. "config network\n"
|
||||||
|
if tun_start then
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. "\toption start '" .. tun_start .. "'\n"
|
||||||
|
end
|
||||||
|
if tun_dns then
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. "\toption dns '" .. tun_dns .. "'\n"
|
||||||
|
end
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. "\n"
|
||||||
|
end
|
||||||
|
cm:foreach("vtun", "client",
|
||||||
|
function(s)
|
||||||
|
if s.enabled == "1" then
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config .. string.format("config client\n\toption enabled '1'\n\toption node '%s'\n\toption passwd '%s'\n\toption clientip '%s'\n\toption serverip '%s'\n\toption netip '%s'\n\n",
|
||||||
|
s.node, s.passwd, s.clientip, s.serverip, s.netip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
local wgclients = 0
|
||||||
|
cm:foreach("wireguard", "client",
|
||||||
|
function(s)
|
||||||
|
if s.enabled == "1" then
|
||||||
|
local client_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)
|
||||||
|
wgclients = wgclients + 1
|
||||||
|
end
|
||||||
|
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 wgservers = 0
|
||||||
|
cm:foreach("vtun", "server",
|
||||||
|
function(s)
|
||||||
|
if s.enabled == "1" then
|
||||||
|
if s.netip:match("/") then
|
||||||
|
local server_pub, client_priv, client_pub = s.passwd:match("^(.+=)(.+=)(.+=)$")
|
||||||
|
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("^(.+)/"))
|
||||||
|
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 = wgservers + 1
|
||||||
|
else
|
||||||
|
cfg.tun_network_config = cfg.tun_network_config ..
|
||||||
|
string.format("config server\n\toption enabled '1'\n\toption host '%s'\n\toption node '%s'\n\toption passwd '%s'\n\toption clientip '%s'\n\toption serverip '%s'\n\toption netip '%s'\n\n",
|
||||||
|
s.host, s.node, s.passwd, s.clientip, s.serverip, s.netip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
remove_all("/tmp/new_config")
|
remove_all("/tmp/new_config")
|
||||||
nixio.fs.mkdir("/tmp/new_config")
|
nixio.fs.mkdir("/tmp/new_config")
|
||||||
|
|
||||||
for file in nixio.fs.glob("/etc/config.mesh/*")
|
for file in nixio.fs.glob("/etc/config.mesh/*")
|
||||||
do
|
do
|
||||||
local bfile = nixio.fs.basename(file)
|
local bfile = nixio.fs.basename(file)
|
||||||
if not (bfile:match("^_setup") or bfile:match("^firewall.user") or bfile:match("^olsrd")) then
|
if not (bfile:match("^_setup") or bfile:match("^firewall.user") or bfile:match("^olsrd") or bfile == "vtun") then
|
||||||
local f = io.open("/tmp/new_config/" .. bfile, "w")
|
local f = io.open("/tmp/new_config/" .. bfile, "w")
|
||||||
if f then
|
if f then
|
||||||
f:write(expand_vars(read_all(file)))
|
f:write(expand_vars(read_all(file)))
|
||||||
|
@ -469,6 +549,9 @@ if do_basic then
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tunnels
|
||||||
|
write_all("/tmp/new_config/vtun", expand_vars("<tun_network_config>"))
|
||||||
|
|
||||||
-- make it official
|
-- make it official
|
||||||
for file in nixio.fs.glob("/etc/config/*")
|
for file in nixio.fs.glob("/etc/config/*")
|
||||||
do
|
do
|
||||||
|
|
|
@ -63,11 +63,13 @@ if uci_conf_file == "olsrd6" then
|
||||||
end
|
end
|
||||||
|
|
||||||
local cursor = uci.cursor()
|
local cursor = uci.cursor()
|
||||||
|
local cursorm = uci.cursor("/etc/config.mesh")
|
||||||
|
|
||||||
local names = {}
|
local names = {}
|
||||||
local hosts = {}
|
local hosts = {}
|
||||||
local services = {}
|
local services = {}
|
||||||
local tunnels = {}
|
local tunnels = {}
|
||||||
|
local wgtunnels = {}
|
||||||
|
|
||||||
function ip_to_hostname(ip)
|
function ip_to_hostname(ip)
|
||||||
if ip and ip ~= "" and ip ~= "none" then
|
if ip and ip ~= "" and ip ~= "none" then
|
||||||
|
@ -304,13 +306,22 @@ if nixio.fs.stat("/etc/local/mesh-firewall/02-vtund") then
|
||||||
maxclients = 10
|
maxclients = 10
|
||||||
end
|
end
|
||||||
tunnum = 50 + maxclients
|
tunnum = 50 + maxclients
|
||||||
cursor:foreach("vtun", "server",
|
local wgtunnum = 0
|
||||||
|
if cursor:get("wireguard", "@client[0]", "name") then
|
||||||
|
tunnels[#tunnels + 1] = "wgc"
|
||||||
|
end
|
||||||
|
cursorm:foreach("vtun", "server",
|
||||||
function(section)
|
function(section)
|
||||||
if section.enabled == "1" then
|
if section.enabled == "1" then
|
||||||
|
if section.netip:match("/") then
|
||||||
|
tunnels[#tunnels + 1] = "wgs" .. wgtunnum
|
||||||
|
wgtunnum = wgtunnum + 1
|
||||||
|
else
|
||||||
tunnels[#tunnels + 1] = "tun" .. tunnum
|
tunnels[#tunnels + 1] = "tun" .. tunnum
|
||||||
tunnum = tunnum + 1
|
tunnum = tunnum + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ require("uci")
|
||||||
|
|
||||||
local html = aredn.html
|
local html = aredn.html
|
||||||
|
|
||||||
local cursor = uci.cursor();
|
local cursor = uci.cursor("/etc/config.mesh");
|
||||||
|
|
||||||
local node = aredn.info.get_nvram("node")
|
local node = aredn.info.get_nvram("node")
|
||||||
if node == "" then
|
if node == "" then
|
||||||
|
@ -70,6 +70,11 @@ if os.getenv("REQUEST_METHOD") == "POST" then
|
||||||
parms = request:formvalue()
|
parms = request:formvalue()
|
||||||
end
|
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
|
||||||
|
|
||||||
-- helpers start
|
-- helpers start
|
||||||
|
|
||||||
local cli_err = {}
|
local cli_err = {}
|
||||||
|
@ -102,6 +107,22 @@ function get_active_tun()
|
||||||
return tuns
|
return tuns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_active_wgtun()
|
||||||
|
local tuns = {}
|
||||||
|
local f = io.popen("/usr/bin/wg show all latest-handshakes")
|
||||||
|
if f then
|
||||||
|
for line in f:lines()
|
||||||
|
do
|
||||||
|
local k,v = line:match("^%S+%s+(%S+)%s+(%S+)%s*$")
|
||||||
|
if k then
|
||||||
|
tuns[k] = tonumber(v) -- time in seconds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
return tuns
|
||||||
|
end
|
||||||
|
|
||||||
function is_tunnel_active(ip, tunnels)
|
function is_tunnel_active(ip, tunnels)
|
||||||
for _, aip in ipairs(tunnels)
|
for _, aip in ipairs(tunnels)
|
||||||
do
|
do
|
||||||
|
@ -112,6 +133,15 @@ function is_tunnel_active(ip, tunnels)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function is_wgtunnel_active(key, wgtunnels)
|
||||||
|
local key = key:match("^.*=(.*=)$")
|
||||||
|
local v = wgtunnels[key]
|
||||||
|
if v and v + wireguard_alive_time > os.time() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function get_server_network_address()
|
function get_server_network_address()
|
||||||
local server_net = cursor:get("vtun", "@network[0]", "start")
|
local server_net = cursor:get("vtun", "@network[0]", "start")
|
||||||
if not server_net then
|
if not server_net then
|
||||||
|
@ -127,11 +157,25 @@ function get_server_network_address()
|
||||||
return { a, b, c, d }
|
return { a, b, c, d }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_wireguard_network_address(netw)
|
||||||
|
local c = netw[3] + 1
|
||||||
|
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 }
|
||||||
|
end
|
||||||
|
|
||||||
function get_server_dns()
|
function get_server_dns()
|
||||||
local dns = cursor:get("vtun", "@network[0]", "dns")
|
local dns = cursor:get("vtun", "@network[0]", "dns")
|
||||||
return dns and dns or ""
|
return dns and dns or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_wireguard_public()
|
||||||
|
local wg = cursor:get("wireguard", "@wireguard_server[0]", "public")
|
||||||
|
return wg or ""
|
||||||
|
end
|
||||||
|
|
||||||
-- helper end
|
-- helper end
|
||||||
|
|
||||||
-- load client info from uci
|
-- load client info from uci
|
||||||
|
@ -153,6 +197,25 @@ function get_client_info()
|
||||||
)
|
)
|
||||||
parms.client_num = c
|
parms.client_num = c
|
||||||
end
|
end
|
||||||
|
-- wireguard
|
||||||
|
local gci_vars = { "enabled", "name", "key", "clientip", "contact" }
|
||||||
|
function get_wgclient_info()
|
||||||
|
local c = 0
|
||||||
|
cursor:foreach("wireguard", "client",
|
||||||
|
function(section)
|
||||||
|
for _, var in ipairs(gci_vars)
|
||||||
|
do
|
||||||
|
local key = "wgclient" .. c .. "_" .. var
|
||||||
|
parms[key] = section[var]
|
||||||
|
if not parms[key] then
|
||||||
|
parms[key] = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
c = c + 1
|
||||||
|
end
|
||||||
|
)
|
||||||
|
parms.wgclient_num = c
|
||||||
|
end
|
||||||
|
|
||||||
if parms.button_reboot then
|
if parms.button_reboot then
|
||||||
os.execute("reboot >/dev/null 2>&1")
|
os.execute("reboot >/dev/null 2>&1")
|
||||||
|
@ -186,24 +249,30 @@ if parms.button_reset then
|
||||||
cursor:delete("vtun", "@options[0]", "port")
|
cursor:delete("vtun", "@options[0]", "port")
|
||||||
cursor:delete("vtun", "@network[0]", "start")
|
cursor:delete("vtun", "@network[0]", "start")
|
||||||
cursor:delete("vtun", "@network[0]", "dns")
|
cursor:delete("vtun", "@network[0]", "dns")
|
||||||
cursor:commit("vtun")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get vtun network address
|
-- get vtun network address
|
||||||
local netw = get_server_network_address()
|
local netw = get_server_network_address()
|
||||||
|
local netwg = get_wireguard_network_address(netw)
|
||||||
local dns = get_server_dns()
|
local dns = get_server_dns()
|
||||||
|
local wireguard_public = get_wireguard_public()
|
||||||
|
|
||||||
-- if RESET or FIRST TIME load client/servers from file into parms
|
-- if RESET or FIRST TIME load client/servers from file into parms
|
||||||
if parms.button_reset or not parms.reload then
|
if parms.button_reset or not parms.reload then
|
||||||
cursor:revert("vtun")
|
cursor:revert("vtun")
|
||||||
get_client_info()
|
get_client_info()
|
||||||
|
get_wgclient_info()
|
||||||
parms.server_net1 = netw[3]
|
parms.server_net1 = netw[3]
|
||||||
parms.server_net2 = netw[4]
|
parms.server_net2 = netw[4]
|
||||||
parms.dns = dns
|
parms.dns = dns
|
||||||
-- initialzie the "add" entries to clear them
|
parms.wireguard_public = wireguard_public
|
||||||
|
-- initialize the "add" entries to clear them
|
||||||
parms.client_add_enabled = "0"
|
parms.client_add_enabled = "0"
|
||||||
parms.client_add_name = ""
|
parms.client_add_name = ""
|
||||||
parms.client_add_passwd = ""
|
parms.client_add_passwd = ""
|
||||||
|
parms.wgclient_add_enabled = "0"
|
||||||
|
parms.wgclient_add_name = ""
|
||||||
|
parms.wgclient_add_key = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local list = {}
|
local list = {}
|
||||||
|
@ -246,6 +315,9 @@ do
|
||||||
err(val .. " this client must be added or cleared out before saving changes")
|
err(val .. " this client must be added or cleared out before saving changes")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
if passwd == "" then
|
||||||
|
err("A client password is required")
|
||||||
|
end
|
||||||
if passwd:match("[^%w@]") then
|
if passwd:match("[^%w@]") then
|
||||||
err("The password cannot contain non-alphanumeric characters (#" .. client_num .. ")")
|
err("The password cannot contain non-alphanumeric characters (#" .. client_num .. ")")
|
||||||
end
|
end
|
||||||
|
@ -255,9 +327,6 @@ do
|
||||||
if name == "" then
|
if name == "" then
|
||||||
err("A client name is required")
|
err("A client name is required")
|
||||||
end
|
end
|
||||||
if passwd == "" then
|
|
||||||
err("A client password is required")
|
|
||||||
end
|
|
||||||
|
|
||||||
if val == "_add" and #cli_err > 0 and cli_err[#cli_err]:match("^" .. val .. " ") then
|
if val == "_add" and #cli_err > 0 and cli_err[#cli_err]:match("^" .. val .. " ") then
|
||||||
break
|
break
|
||||||
|
@ -281,9 +350,79 @@ do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
parms.client_num = client_num
|
parms.client_num = client_num
|
||||||
|
|
||||||
|
-- wireguard
|
||||||
|
local vars = { "enabled", "name", "key", "clientip", "contact" }
|
||||||
|
local wgclient_num = 0
|
||||||
|
for val = 0, parms.wgclient_num
|
||||||
|
do
|
||||||
|
if val == tonumber(parms.wgclient_num) then
|
||||||
|
val = "_add"
|
||||||
|
end
|
||||||
|
for _ = 1,1
|
||||||
|
do
|
||||||
|
for _, var in ipairs(vars)
|
||||||
|
do
|
||||||
|
local varname = "wgclient" .. val .. "_" .. var
|
||||||
|
if var == "enabled" and not parms[varname] then
|
||||||
|
parms[varname] = "0"
|
||||||
|
elseif not parms[varname] then
|
||||||
|
parms[varname] = ""
|
||||||
|
elseif var == "contact" then
|
||||||
|
parms[varname] = parms[varname]:gsub("^%s+", ""):gsub("%s+$", ""):sub(1,210):gsub('"',"""):gsub("'","'"):gsub("<","<"):gsub(">",">")
|
||||||
|
else
|
||||||
|
parms[varname] = parms[varname]:gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
end
|
||||||
|
if val ~= "_add" and parms[varname] == "" and var == "enabled" then
|
||||||
|
parms[varname] = "0"
|
||||||
|
end
|
||||||
|
_G[var] = parms[varname]
|
||||||
|
end
|
||||||
|
|
||||||
|
if val == "_add" and not ((enabled ~= "0" or name ~= "" or contact ~= "") and (parms.wgclient_add or parms.button_save)) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if val == "_add" and parms.button_save then
|
||||||
|
err(val .. " this wireguard client must be added or cleared out before saving changes")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if name == "" then
|
||||||
|
err("A client name is required")
|
||||||
|
end
|
||||||
|
|
||||||
|
if val == "_add" and #cli_err > 0 and cli_err[#cli_err]:match("^" .. val .. " ") then
|
||||||
|
break
|
||||||
|
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
|
||||||
|
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 .. "_contact"] = contact
|
||||||
|
|
||||||
|
-- commit the data from this client
|
||||||
|
wgclient_num = wgclient_num + 1
|
||||||
|
|
||||||
|
-- clear out the ADD values
|
||||||
|
if val == "_add" then
|
||||||
|
for _, var in ipairs(vars)
|
||||||
|
do
|
||||||
|
parms["wgclient_add_" .. var] = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
parms.wgclient_num = wgclient_num
|
||||||
|
|
||||||
|
|
||||||
-- SAVE the server network numbers and dns into the UCI
|
-- SAVE the server network numbers and dns into the UCI
|
||||||
netw[3] = parms.server_net1
|
netw[3] = parms.server_net1
|
||||||
netw[4] = parms.server_net2
|
netw[4] = parms.server_net2
|
||||||
|
@ -343,6 +482,22 @@ do
|
||||||
enabled_count = enabled_count + 1
|
enabled_count = enabled_count + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- wireguard
|
||||||
|
for i = 0,wgclient_num-1
|
||||||
|
do
|
||||||
|
local clientx = "wgclient" .. i
|
||||||
|
local client_x = "client_" .. i
|
||||||
|
|
||||||
|
if not cursor:get("wireguard", client_x) then
|
||||||
|
cursor:set("wireguard", client_x, 'client')
|
||||||
|
end
|
||||||
|
|
||||||
|
cursor:set("wireguard", client_x, "enabled", parms[clientx .. "_enabled"])
|
||||||
|
cursor:set("wireguard", client_x, "name", parms[clientx .. "_name"])
|
||||||
|
cursor:set("wireguard", client_x, "contact", parms[clientx .. "_contact"])
|
||||||
|
cursor:set("wireguard", client_x, "key", parms[clientx .. "_key"])
|
||||||
|
cursor:set("wireguard", client_x, "clientip", parms[clientx .. "_clientip"])
|
||||||
|
end
|
||||||
|
|
||||||
local maxclients = tonumber(cursor:get("aredn", "@tunnel[0]", "maxclients"))
|
local maxclients = tonumber(cursor:get("aredn", "@tunnel[0]", "maxclients"))
|
||||||
if not maxclients then
|
if not maxclients then
|
||||||
|
@ -355,16 +510,15 @@ end
|
||||||
-- save configuration (commit)
|
-- save configuration (commit)
|
||||||
if parms.button_save and #cli_err == 0 then
|
if parms.button_save and #cli_err == 0 then
|
||||||
cursor:commit("vtun")
|
cursor:commit("vtun")
|
||||||
write_all("/etc/config.mesh/vtun", read_all("/etc/config/vtun"))
|
cursor:commit("wireguard")
|
||||||
if os.execute("/etc/init.d/olsrd restart > /dev/null 2>&1") ~= 0 then
|
os.execute("/usr/local/bin/node-setup -a mesh > /dev/null 2>&1")
|
||||||
err2("Problem restarting olsrd")
|
os.execute("/etc/init.d/olsrd restart > /dev/null 2>&1")
|
||||||
end
|
os.execute("/etc/init.d/vtundsrv restart > /dev/null 2>&1")
|
||||||
if os.execute("/etc/init.d/vtundsrv restart > /dev/null 2>&1") ~= 0 then
|
os.execute("/etc/init.d/network restart > /dev/null 2>&1")
|
||||||
err2("Problem restaring vtundsrv")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local active_tun = get_active_tun()
|
local active_tun = get_active_tun()
|
||||||
|
local active_wgtun = get_active_wgtun()
|
||||||
|
|
||||||
-- generate the page
|
-- generate the page
|
||||||
|
|
||||||
|
@ -377,7 +531,7 @@ html.print("<form id=vpn method=post action=/cgi-bin/vpn enctype='multipart/form
|
||||||
-- navigation bar
|
-- navigation bar
|
||||||
html.navbar_admin("vpn")
|
html.navbar_admin("vpn")
|
||||||
|
|
||||||
html.print("<table width=790>")
|
html.print("<table width=850>")
|
||||||
|
|
||||||
-- control buttons
|
-- control buttons
|
||||||
html.print("<tr><td align=center>")
|
html.print("<tr><td align=center>")
|
||||||
|
@ -430,11 +584,13 @@ if config == "mesh" then
|
||||||
-- print vpn clients
|
-- print vpn clients
|
||||||
html.print("<table cellpadding=0 cellspacing=0>")
|
html.print("<table cellpadding=0 cellspacing=0>")
|
||||||
|
|
||||||
html.print("<br /><tr class=tun_network_row><td colspan=6 align=center valign=top>Tunnel Server Network: ")
|
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(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("<br /><hr>Tunnel Server DNS Name: ")
|
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='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>")
|
||||||
html.print("<table cellpadding=0 cellspacing=0>")
|
html.print("<table cellpadding=0 cellspacing=0>")
|
||||||
|
@ -462,9 +618,6 @@ if config == "mesh" then
|
||||||
do
|
do
|
||||||
_G[var] = parms["client" .. val .. "_" .. var]
|
_G[var] = parms["client" .. val .. "_" .. var]
|
||||||
end
|
end
|
||||||
if val == "_add" and #list > 1 then
|
|
||||||
html.print("<tr class=tun_client_add_row><td height=10></td></tr>")
|
|
||||||
end
|
|
||||||
html.print("<tr class='tun_client_list2 tun_client_row'>")
|
html.print("<tr class='tun_client_list2 tun_client_row'>")
|
||||||
html.print("<td class='tun_client_center_item' rowspan='2'>")
|
html.print("<td class='tun_client_center_item' rowspan='2'>")
|
||||||
html.print("<input type='checkbox' name='client" .. val .. "_enabled' value='1'")
|
html.print("<input type='checkbox' name='client" .. val .. "_enabled' value='1'")
|
||||||
|
@ -480,11 +633,12 @@ if config == "mesh" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()'")
|
||||||
end
|
end
|
||||||
html.print(" title='client name'></td>")
|
html.print(" title='client name'></td>")
|
||||||
html.print("<td><input type=text size=25 name=client" .. val .. "_passwd value='" .. passwd .. "' ")
|
html.print("<td>")
|
||||||
|
html.print("<input type=text size=25 name=client" .. val .. "_passwd value='" .. passwd .. "' title='client password' ")
|
||||||
if val ~= "_add" then
|
if val ~= "_add" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()'")
|
||||||
end
|
end
|
||||||
html.print(" title='client password'></td>")
|
html.print("</td>")
|
||||||
|
|
||||||
-- handle rollover of netw
|
-- handle rollover of netw
|
||||||
local net
|
local net
|
||||||
|
@ -498,8 +652,8 @@ if config == "mesh" then
|
||||||
end
|
end
|
||||||
local lastnet = netw[4] + net * 4
|
local lastnet = netw[4] + net * 4
|
||||||
local fullnet = netw[1] .. "." .. netw[2] .. "." .. netw[3] .. "." .. lastnet
|
local fullnet = netw[1] .. "." .. netw[2] .. "." .. netw[3] .. "." .. lastnet
|
||||||
html.print("<td rowspan='2' class='tun_client_center_item'> " .. fullnet)
|
html.print("<td rowspan='2' class='tun_client_center_item'>")
|
||||||
html.print("<input type=hidden name=client" .. val .. "_netip value='" .. fullnet .. "'/></td>")
|
html.print("<input style='width:90px;background-color:transparent;border:0;text-align:center;' readonly type=text size=16 name=client" .. val .. "_netip value='" .. fullnet .. "'/></td>")
|
||||||
html.print("<td rowspan='2' class='tun_client_center_item' align=center> ")
|
html.print("<td rowspan='2' class='tun_client_center_item' align=center> ")
|
||||||
if val ~= "_add" and is_tunnel_active(fullnet, active_tun) then
|
if val ~= "_add" and is_tunnel_active(fullnet, active_tun) then
|
||||||
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
|
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
|
||||||
|
@ -510,7 +664,9 @@ if config == "mesh" then
|
||||||
if val == "_add" then
|
if val == "_add" then
|
||||||
html.print("<td rowspan='2' class='tun_client_center_item'><input type=submit name=client_add value=Add title='Add this client'></td>")
|
html.print("<td rowspan='2' class='tun_client_center_item'><input type=submit name=client_add value=Add title='Add this client'></td>")
|
||||||
else
|
else
|
||||||
html.print("<td rowspan='2' class='tun_client_center_item tun_client_mailto'><a href='mailto:?subject=AREDN%20Tunnel%20Connection&body=Your%20connection%20details:%0D%0AName:%20" .. name .. "%0D%0APassword:%20" .. passwd .. "%0D%0ANetwork:%20" .. fullnet .. "%0D%0AServer%20address:%20" .. dns .. "' target='_blank'><img class='tun_client_mailto_img' src='/email.png' title='Email details' /></a></td>")
|
html.print("<td rowspan='2' class='tun_client_center_item tun_client_mailto' id=client" .. val .. "_email>")
|
||||||
|
html.print("<a href='mailto:?subject=AREDN%20Tunnel%20Connection&body=Your%20connection%20details:%0D%0AName:%20" .. name .. "%0D%0APassword:%20" .. passwd .. "%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
|
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=client" .. val .. "_contact value='" .. contact .."'")
|
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=client" .. val .. "_contact value='" .. contact .."'")
|
||||||
if val ~= "" and val ~= "_add" then
|
if val ~= "" and val ~= "_add" then
|
||||||
|
@ -521,8 +677,78 @@ if config == "mesh" then
|
||||||
-- display any errors
|
-- display any errors
|
||||||
while #cli_err > 0 and cli_err[1]:match("^" .. val .. " ")
|
while #cli_err > 0 and cli_err[1]:match("^" .. val .. " ")
|
||||||
do
|
do
|
||||||
html.print("<tr class=tun_client_error_row><th colspan=4>" .. err:gsub("^%S+ ", "") .. "</th></tr>")
|
html.print("<tr class=tun_client_error_row><th colspan=4>" .. cli_err[1]:gsub("^%S+ ", "") .. "</th></tr>")
|
||||||
cli_err:remove(1)
|
table.remove(cli_err)
|
||||||
|
end
|
||||||
|
|
||||||
|
html.print("<tr><td colspan=4 height=4></td></tr>")
|
||||||
|
cnum = cnum + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Wireguard
|
||||||
|
html.print("<tr><th colspan=6></th></tr>")
|
||||||
|
html.print("<tr><th colspan=6 style='padding: 30px 0 0 0'>Allow the following clients to connect to this Wireguard server:</th></tr>")
|
||||||
|
html.print("<tr><th colspan=6><hr></th></tr>")
|
||||||
|
html.print("<tr><th>Enabled?</th><th>Client</th><th>Key</th><th>Client</th><th>Active </td><th>Action</th></tr>")
|
||||||
|
|
||||||
|
local keys = { "enabled", "name", "contact", "key" }
|
||||||
|
local cnum = 1
|
||||||
|
for val = 0, wgclient_num
|
||||||
|
do
|
||||||
|
if val == wgclient_num then
|
||||||
|
val = "_add"
|
||||||
|
end
|
||||||
|
for _, var in ipairs(keys)
|
||||||
|
do
|
||||||
|
_G[var] = parms["wgclient" .. val .. "_" .. var]
|
||||||
|
end
|
||||||
|
html.print("<tr class='tun_client_list2 tun_client_row'>")
|
||||||
|
html.print("<td class='tun_client_center_item' rowspan='2'>")
|
||||||
|
html.print("<input type='checkbox' name='wgclient" .. val .. "_enabled' value='1'")
|
||||||
|
if val ~= "_add" then
|
||||||
|
html.print(" onChange='form.submit()'")
|
||||||
|
end
|
||||||
|
if enabled == "1" then
|
||||||
|
html.print(" checked='checked'")
|
||||||
|
end
|
||||||
|
html.print(" title='enable this client'></td>")
|
||||||
|
html.print("<td><input type=text size=40 name=wgclient" .. val .. "_name value='" .. (name or "") .. "'")
|
||||||
|
if val ~= "_add" then
|
||||||
|
html.print(" onChange='form.submit()'")
|
||||||
|
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("</td>")
|
||||||
|
|
||||||
|
local fullnet = netwg[1] .. "." .. netwg[2] .. "." .. netwg[3] .. "." .. (netwg[4] + 1 + cnum) .. "/" .. netwg[5]
|
||||||
|
html.print("<td rowspan='2' class='tun_client_center_item'>")
|
||||||
|
html.print("<input style='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("<td rowspan='2' class='tun_client_center_item' align=center> ")
|
||||||
|
if val ~= "_add" and is_wgtunnel_active(key, active_wgtun) 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' />")
|
||||||
|
end
|
||||||
|
html.print("</td>")
|
||||||
|
if val == "_add" 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("<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 "") .."'")
|
||||||
|
if val ~= "" and val ~= "_add" then
|
||||||
|
html.print(" onChange='form.submit()'")
|
||||||
|
end
|
||||||
|
html.print(" title='client contact info'></td></tr>")
|
||||||
|
|
||||||
|
-- display any errors
|
||||||
|
while #cli_err > 0 and cli_err[1]:match("^" .. val .. " ")
|
||||||
|
do
|
||||||
|
html.print("<tr class=tun_client_error_row><th colspan=4>" .. cli_err[1]:gsub("^%S+ ", "") .. "</th></tr>")
|
||||||
|
table.remove(cli_err)
|
||||||
end
|
end
|
||||||
|
|
||||||
html.print("<tr><td colspan=4 height=4></td></tr>")
|
html.print("<tr><td colspan=4 height=4></td></tr>")
|
||||||
|
@ -535,6 +761,7 @@ if config == "mesh" then
|
||||||
end
|
end
|
||||||
html.print("</table><p style='font-size:8px'>Tunnel v" .. VPNVER .. "</p>")
|
html.print("</table><p style='font-size:8px'>Tunnel v" .. VPNVER .. "</p>")
|
||||||
hide("<input type=hidden name=client_num value=" .. parms.client_num .. ">")
|
hide("<input type=hidden name=client_num value=" .. parms.client_num .. ">")
|
||||||
|
hide("<input type=hidden name=wgclient_num value=" .. parms.wgclient_num .. ">")
|
||||||
|
|
||||||
-- add hidden forms fields
|
-- add hidden forms fields
|
||||||
for _, h in ipairs(hidden)
|
for _, h in ipairs(hidden)
|
||||||
|
|
|
@ -45,7 +45,7 @@ require("uci")
|
||||||
|
|
||||||
local html = aredn.html
|
local html = aredn.html
|
||||||
|
|
||||||
local cursor = uci.cursor();
|
local cursor = uci.cursor("/etc/config.mesh");
|
||||||
|
|
||||||
local node = aredn.info.get_nvram("node")
|
local node = aredn.info.get_nvram("node")
|
||||||
if node == "" then
|
if node == "" then
|
||||||
|
@ -74,6 +74,9 @@ if os.getenv("REQUEST_METHOD") == "POST" then
|
||||||
parms = request:formvalue()
|
parms = request:formvalue()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- wireguard
|
||||||
|
local wireguard_alive_time = 300 -- 5 minutes
|
||||||
|
|
||||||
-- helpers start
|
-- helpers start
|
||||||
|
|
||||||
local hidden = {}
|
local hidden = {}
|
||||||
|
@ -106,6 +109,22 @@ function get_active_tun()
|
||||||
return tuns
|
return tuns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_active_wgtun()
|
||||||
|
local tuns = {}
|
||||||
|
local f = io.popen("/usr/bin/wg show all latest-handshakes")
|
||||||
|
if f then
|
||||||
|
for line in f:lines()
|
||||||
|
do
|
||||||
|
local k,v = line:match("^%S+%s+(%S+)%s+(%S+)%s*$")
|
||||||
|
if k then
|
||||||
|
tuns[k] = tonumber(v) -- time in seconds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
return tuns
|
||||||
|
end
|
||||||
|
|
||||||
function is_tunnel_active(ip, tunnels)
|
function is_tunnel_active(ip, tunnels)
|
||||||
for _, aip in ipairs(tunnels)
|
for _, aip in ipairs(tunnels)
|
||||||
do
|
do
|
||||||
|
@ -116,6 +135,15 @@ function is_tunnel_active(ip, tunnels)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function is_wgtunnel_active(key, wgtunnels)
|
||||||
|
local key = key:match("^(.*=).*=.*=$")
|
||||||
|
local v = wgtunnels[key]
|
||||||
|
if v and v + wireguard_alive_time > os.time() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-- helpers end
|
-- helpers end
|
||||||
|
|
||||||
local gci_vars = { "enabled", "host", "passwd", "netip", "contact" }
|
local gci_vars = { "enabled", "host", "passwd", "netip", "contact" }
|
||||||
|
@ -242,7 +270,11 @@ do
|
||||||
err(val .. " this connection must be added or cleared out before saving changes")
|
err(val .. " this connection must be added or cleared out before saving changes")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if passwd:match("[^%w@]") then
|
if netip:match("/") then
|
||||||
|
if not passwd:match("^.+=.+=.+=$") then
|
||||||
|
err("The password is not a wireguard key")
|
||||||
|
end
|
||||||
|
elseif passwd:match("[^%w@]") then
|
||||||
err("The password cannot contain non-alphanumeric characters (#" .. conn_num .. ")")
|
err("The password cannot contain non-alphanumeric characters (#" .. conn_num .. ")")
|
||||||
end
|
end
|
||||||
if host == "" then
|
if host == "" then
|
||||||
|
@ -326,23 +358,51 @@ end
|
||||||
-- save the connections the uci vtun file
|
-- save the connections the uci vtun file
|
||||||
if parms.button_save and #conn_err == 0 then
|
if parms.button_save and #conn_err == 0 then
|
||||||
cursor:commit("vtun")
|
cursor:commit("vtun")
|
||||||
write_all("/etc/config.mesh/vtun", read_all("/etc/config/vtun"))
|
os.execute("/usr/local/bin/node-setup -a mesh > /dev/null 2>&1")
|
||||||
if os.execute("/etc/init.d/olsrd restart > /dev/null 2>&1") ~= 0 then
|
os.execute("/etc/init.d/olsrd restart > /dev/null 2>&1")
|
||||||
err2("Problem restarting olsrd")
|
os.execute("/etc/init.d/vtund restart > /dev/null 2>&1")
|
||||||
end
|
os.execute("/etc/init.d/network restart > /dev/null 2>&1")
|
||||||
if os.execute("/etc/init.d/vtund restart > /dev/null 2>&1") ~= 0 then
|
|
||||||
err2("Problem restaring vtund")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local active_tun = get_active_tun()
|
local active_tun = get_active_tun()
|
||||||
|
local active_wgtun = get_active_wgtun()
|
||||||
|
|
||||||
-- generate page
|
-- generate page
|
||||||
http_header()
|
http_header()
|
||||||
html.header(node .. " setup", true)
|
html.header(node .. " setup", false)
|
||||||
|
|
||||||
html.print("<body><center>")
|
html.print([[
|
||||||
|
<script>
|
||||||
|
function configPaste(e) {
|
||||||
|
const txt = e.clipboardData.getData("text/plain");
|
||||||
|
if (!txt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const config = {};
|
||||||
|
txt.split("\n").forEach(line => {
|
||||||
|
if (line.startsWith("Password: ")) {
|
||||||
|
config.passwd = line.substring(10);
|
||||||
|
}
|
||||||
|
else if (line.startsWith("Network: ")) {
|
||||||
|
config.network = line.substring(9);
|
||||||
|
}
|
||||||
|
else if (line.startsWith("Server address: ")) {
|
||||||
|
config.server = line.substring(16);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!(config.passwd && config.network && config.server)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.forms[0].conn_add_host.value = config.server;
|
||||||
|
document.forms[0].conn_add_passwd.value = config.passwd;
|
||||||
|
document.forms[0].conn_add_netip.value = config.network;
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
]])
|
||||||
|
|
||||||
|
html.print("</head><body><center>")
|
||||||
html.alert_banner()
|
html.alert_banner()
|
||||||
|
|
||||||
html.print("<form method=post action=/cgi-bin/vpnc enctype='multipart/form-data'>")
|
html.print("<form method=post action=/cgi-bin/vpnc enctype='multipart/form-data'>")
|
||||||
|
@ -440,12 +500,16 @@ if config == "mesh" then
|
||||||
html.print("<td><input type=text size=25 name=conn" .. val .. "_host value='" .. host .. "'")
|
html.print("<td><input type=text size=25 name=conn" .. val .. "_host value='" .. host .. "'")
|
||||||
if val ~= "_add" then
|
if val ~= "_add" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()'")
|
||||||
|
else
|
||||||
|
html.print(" onPaste='configPaste(event)'")
|
||||||
end
|
end
|
||||||
html.print(" title='connection name'></td>")
|
html.print(" title='connection name'></td>")
|
||||||
|
|
||||||
html.print("<td><input type=text size=20 name=conn" .. val .. "_passwd value='" .. passwd .. "' ")
|
html.print("<td><input type=text size=20 name=conn" .. val .. "_passwd value='" .. passwd .. "' ")
|
||||||
if val ~= "_add" then
|
if val ~= "_add" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()'")
|
||||||
|
else
|
||||||
|
html.print(" onPaste='configPaste(event)'")
|
||||||
end
|
end
|
||||||
html.print(" title='connection password'")
|
html.print(" title='connection password'")
|
||||||
html.print("></td>")
|
html.print("></td>")
|
||||||
|
@ -453,6 +517,8 @@ if config == "mesh" then
|
||||||
html.print("<td><input type=text size=14 name=conn" .. val .. "_netip value='" .. netip .. "'")
|
html.print("<td><input type=text size=14 name=conn" .. val .. "_netip value='" .. netip .. "'")
|
||||||
if val ~= "_add" then
|
if val ~= "_add" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()'")
|
||||||
|
else
|
||||||
|
html.print(" onPaste='configPaste(event)'")
|
||||||
end
|
end
|
||||||
html.print(" title='connection network'></td>")
|
html.print(" title='connection network'></td>")
|
||||||
|
|
||||||
|
@ -460,7 +526,7 @@ if config == "mesh" then
|
||||||
html.print("<td class='tun_client_center_item' rowspan='2'> ")
|
html.print("<td class='tun_client_center_item' rowspan='2'> ")
|
||||||
|
|
||||||
if val ~= "_add" then
|
if val ~= "_add" then
|
||||||
if is_tunnel_active(netip, active_tun) then
|
if is_tunnel_active(netip, active_tun) or is_wgtunnel_active(passwd, active_wgtun) then
|
||||||
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
|
html.print("<img class='tun_client_active_img' src='/connected.png' title='Connected' />")
|
||||||
else
|
else
|
||||||
html.print("<img class='tun_client_inactive_img' src='/disconnected.png' title='Not connected' />")
|
html.print("<img class='tun_client_inactive_img' src='/disconnected.png' title='Not connected' />")
|
||||||
|
@ -480,7 +546,7 @@ if config == "mesh" then
|
||||||
html.print("</tr>")
|
html.print("</tr>")
|
||||||
html.print("<tr class='tun_client_list1 tun_client_row tun_loading_css_comment'><td colspan='3' align='right'>Contact Info/Comment (Optional): <input type=text maxlength='50' size=40 name=conn" .. val .. "_contact value='" .. contact .. "'")
|
html.print("<tr class='tun_client_list1 tun_client_row tun_loading_css_comment'><td colspan='3' align='right'>Contact Info/Comment (Optional): <input type=text maxlength='50' size=40 name=conn" .. val .. "_contact value='" .. contact .. "'")
|
||||||
if val == "_add" or val == "" then
|
if val == "_add" or val == "" then
|
||||||
html.print(" onChange='form.submit()'")
|
html.print(" onChange='form.submit()' onPaste='configPaste(event)'")
|
||||||
end
|
end
|
||||||
html.print(" title='client contact info'></td>")
|
html.print(" title='client contact info'></td>")
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,11 @@ Index: openwrt/feeds/packages/net/iperf3/files/iperf.firewall
|
||||||
+++ openwrt/feeds/packages/net/iperf3/files/iperf.firewall
|
+++ openwrt/feeds/packages/net/iperf3/files/iperf.firewall
|
||||||
@@ -0,0 +1,9 @@
|
@@ -0,0 +1,9 @@
|
||||||
+#!/bin/sh
|
+#!/bin/sh
|
||||||
+nft insert rule ip fw4 input_wifi udp dport 5201 counter accept
|
+nft insert rule ip fw4 input_wifi udp dport 5201 accept
|
||||||
+nft insert rule ip fw4 input_wifi tcp dport 5201 counter accept
|
+nft insert rule ip fw4 input_wifi tcp dport 5201 accept
|
||||||
+nft insert rule ip fw4 input_dtdlink udp dport 5201 counter accept
|
+nft insert rule ip fw4 input_dtdlink udp dport 5201 accept
|
||||||
+nft insert rule ip fw4 input_dtdlink tcp dport 5201 counter accept
|
+nft insert rule ip fw4 input_dtdlink tcp dport 5201 accept
|
||||||
+if [ "$MESHFW_TUNNELS_ENABLED" == "1" ]; then
|
+if [ "$MESHFW_TUNNELS_ENABLED" == "1" -o "$MESHFW_WG_TUNNELS_ENABLED" == "1" ]; then
|
||||||
+ nft insert rule ip fw4 input_vpn udp dport 5201 counter accept
|
+ nft insert rule ip fw4 input_vpn udp dport 5201 accept
|
||||||
+ nft insert rule ip fw4 input_vpn tcp dport 5201 counter accept
|
+ nft insert rule ip fw4 input_vpn tcp dport 5201 accept
|
||||||
+fi
|
+fi
|
||||||
|
|
Loading…
Reference in New Issue