wg-installer: add wg-installer
This tool can be used to automatically create wireguard tunnels. Using rpcd a new wireguard interface is created on the server where the client can connect to. Wiregurad server automatically installs a user and associated ACL to use the wireguard-installer-server features. The user is called wginstaller and so is the password. Get Usage: wg-client-installer get_usage --ip 127.0.0.1 --user wginstaller --password wginstaller Register Interface: wg-client-installer register --ip 127.0.0.1 --user wginstaller --password wginstaller --bandwidth 10 --mtu 1400 Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
parent
d29ec52a58
commit
3a6949dfaf
11 changed files with 494 additions and 0 deletions
69
net/wg-installer/Makefile
Normal file
69
net/wg-installer/Makefile
Normal file
|
@ -0,0 +1,69 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=wg-installer
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_MAINTAINER:=Nick Hainke <vincent@systemli.org>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
Build/Compile=
|
||||
|
||||
define Package/wg-installer/Default
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=WireGuard Installer
|
||||
URL:=https://github.com/Freifunk-Spalter/
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+kmod-wireguard +owipcalc
|
||||
endef
|
||||
|
||||
define Package/wg-installer-server
|
||||
$(call Package/wg-installer/Default)
|
||||
TITLE+= (server)
|
||||
DEPENDS:=+rpcd +uhttpd +uhttpd-mod-ubus +owipcalc
|
||||
endef
|
||||
|
||||
define Package/wg-installer-server/install
|
||||
$(INSTALL_DIR) $(1)/usr/share/wginstaller/
|
||||
$(INSTALL_BIN) ./wg-server/lib/install_wginstaller_user.sh $(1)/usr/share/wginstaller/install_wginstaller_user.sh
|
||||
$(INSTALL_BIN) ./wg-server/lib/wg_functions.sh $(1)/usr/share/wginstaller/wg_functions.sh
|
||||
$(INSTALL_BIN) ./common/wg.sh $(1)/usr/share/wginstaller/wg.sh
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/libexec/rpcd/
|
||||
$(INSTALL_BIN) ./wg-server/wginstaller.sh $(1)/usr/libexec/rpcd/wginstaller
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./wg-server/config/wginstaller.json $(1)/usr/share/rpcd/acl.d/
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./wg-server/config/wgserver.conf $(1)/etc/config/wgserver
|
||||
endef
|
||||
|
||||
define Package/wg-installer-server/postinst
|
||||
#!/bin/sh
|
||||
if [ -z $${IPKG_INSTROOT} ] ; then
|
||||
. /usr/share/wginstaller/install_wginstaller_user.sh
|
||||
fi
|
||||
endef
|
||||
|
||||
define Package/wg-installer-client
|
||||
$(call Package/wg-installer/Default)
|
||||
TITLE+= (client)
|
||||
DEPENDS:=+curl +wireguard-tools
|
||||
endef
|
||||
|
||||
define Package/wg-installer-client/install
|
||||
$(INSTALL_DIR) $(1)/usr/share/wginstaller/
|
||||
$(INSTALL_BIN) ./wg-client/lib/rpcd_ubus.sh $(1)/usr/share/wginstaller/rpcd_ubus.sh
|
||||
$(INSTALL_BIN) ./common/wg.sh $(1)/usr/share/wginstaller/wg.sh
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) ./wg-client/wg-client-installer.sh $(1)/usr/bin/wg-client-installer
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./wg-client/config/wgclient.conf $(1)/etc/config/wgclient
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,wg-installer-server))
|
||||
$(eval $(call BuildPackage,wg-installer-client))
|
26
net/wg-installer/README.md
Normal file
26
net/wg-installer/README.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
## Wireguard Installer
|
||||
|
||||
This tool can be used to automatically create wireguard tunnels. Using rpcd a new wireguard interface is created on the server where the client can connect to.
|
||||
|
||||
## Installation
|
||||
|
||||
For Server
|
||||
|
||||
opkg install wireguard-installer-server
|
||||
|
||||
For Client
|
||||
|
||||
opkg install wireguard-installer-client
|
||||
|
||||
Wiregurad server automatically installs a user and associated ACL to use the wireguard-installer-server features.
|
||||
The user is called wginstaller and so is the password.
|
||||
|
||||
## Usage
|
||||
|
||||
Get Usage Statistics
|
||||
|
||||
wg-client-installer get_usage --ip 127.0.0.1 --user wginstaller --password wginstaller
|
||||
|
||||
Register Tunnel Interface
|
||||
|
||||
wg-client-installer register --ip 127.0.0.1 --user wginstaller --password wginstaller --bandwidth 10
|
13
net/wg-installer/common/wg.sh
Normal file
13
net/wg-installer/common/wg.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
next_port () {
|
||||
local port_start=$1
|
||||
local port_end=$2
|
||||
|
||||
ports=$(wg show all listen-port | awk '{print $2}')
|
||||
|
||||
for i in $(seq $port_start $port_end); do
|
||||
if ! echo $ports | grep -q "$i"; then
|
||||
echo $i
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
8
net/wg-installer/wg-client/config/wgclient.conf
Normal file
8
net/wg-installer/wg-client/config/wgclient.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
config client
|
||||
option wg_key '/root/wg.key'
|
||||
option wg_pub '/root/wg.pub'
|
||||
option base_prefix '2000::/64'
|
||||
option port_start '51820'
|
||||
option port_end '52820'
|
||||
option try_insecure '1'
|
||||
option try_http '1'
|
134
net/wg-installer/wg-client/lib/rpcd_ubus.sh
Normal file
134
net/wg-installer/wg-client/lib/rpcd_ubus.sh
Normal file
|
@ -0,0 +1,134 @@
|
|||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
query_gw () {
|
||||
local ip=$1
|
||||
local req=$2
|
||||
|
||||
# first try https
|
||||
ret=$(curl https://$ip/ubus -d "$req") 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo $ret
|
||||
return 0
|
||||
fi
|
||||
|
||||
# try with --insecure
|
||||
if [ $(uci get wgclient.@client[0].try_insecure) == '1' ]; then
|
||||
ret=$(curl --insecure https://$ip/ubus -d "$req") 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo $ret
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# try with http
|
||||
if [ $(uci get wgclient.@client[0].try_http) == '1' ]; then
|
||||
ret=$(curl http://$ip/ubus -d "$req") 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo $ret
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
request_token () {
|
||||
local ip=$1
|
||||
local user=$2
|
||||
local password=$3
|
||||
|
||||
json_init
|
||||
json_add_string "jsonrpc" "2.0"
|
||||
json_add_int "id" "1"
|
||||
json_add_string "method" "call"
|
||||
json_add_array "params"
|
||||
json_add_string "" "00000000000000000000000000000000"
|
||||
json_add_string "" "session"
|
||||
json_add_string "" "login"
|
||||
json_add_object
|
||||
json_add_string "username" $user
|
||||
json_add_string "password" $password
|
||||
json_close_object
|
||||
json_close_array
|
||||
req=$(json_dump)
|
||||
ret=$(query_gw $ip "$req") 2>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
json_load "$ret"
|
||||
json_get_vars result result
|
||||
json_select result
|
||||
json_select 2
|
||||
json_get_var ubus_rpc_session ubus_rpc_session
|
||||
echo $ubus_rpc_session
|
||||
}
|
||||
|
||||
wg_rpcd_get_usage () {
|
||||
local token=$1
|
||||
local ip=$2
|
||||
local secret=$3
|
||||
|
||||
json_init
|
||||
json_add_string "jsonrpc" "2.0"
|
||||
json_add_int "id" "1"
|
||||
json_add_string "method" "call"
|
||||
json_add_array "params"
|
||||
json_add_string "" $token
|
||||
json_add_string "" "wginstaller"
|
||||
json_add_string "" "get_usage"
|
||||
json_add_object
|
||||
json_close_object
|
||||
json_close_array
|
||||
req=$(json_dump)
|
||||
ret=$(query_gw $ip "$req") 2>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# return values
|
||||
json_load "$ret"
|
||||
json_get_vars result result
|
||||
json_select result
|
||||
json_select 2
|
||||
json_get_var num_interfaces num_interfaces
|
||||
echo "num_interfaces: ${num_interfaces}"
|
||||
}
|
||||
|
||||
wg_rpcd_register () {
|
||||
local token=$1
|
||||
local ip=$2
|
||||
local uplink_bw=$3
|
||||
local mtu=$4
|
||||
local public_key=$5
|
||||
|
||||
json_init
|
||||
json_add_string "jsonrpc" "2.0"
|
||||
json_add_int "id" "1"
|
||||
json_add_string "method" "call"
|
||||
json_add_array "params"
|
||||
json_add_string "" $token
|
||||
json_add_string "" "wginstaller"
|
||||
json_add_string "" "register"
|
||||
json_add_object
|
||||
json_add_int "uplink_bw" $uplink_bw
|
||||
json_add_int "mtu" $mtu
|
||||
json_add_string "public_key" $public_key
|
||||
json_close_object
|
||||
json_close_array
|
||||
req=$(json_dump)
|
||||
ret=$(query_gw $ip "$req") 2>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
json_load "$ret"
|
||||
json_get_vars result result
|
||||
json_select result
|
||||
json_select 2
|
||||
json_get_var pubkey pubkey
|
||||
json_get_var gw_ip gw_ip
|
||||
json_get_var port port
|
||||
echo "pubkey: ${pubkey}"
|
||||
echo "gw_ip: ${gw_ip}"
|
||||
echo "port: ${port}"
|
||||
}
|
119
net/wg-installer/wg-client/wg-client-installer.sh
Normal file
119
net/wg-installer/wg-client/wg-client-installer.sh
Normal file
|
@ -0,0 +1,119 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /usr/share/wginstaller/rpcd_ubus.sh
|
||||
. /usr/share/wginstaller/wg.sh
|
||||
|
||||
CMD=$1
|
||||
shift
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
echo "help"
|
||||
shift 1
|
||||
;;
|
||||
-i | --ip)
|
||||
IP=$2
|
||||
shift 2
|
||||
;;
|
||||
--user)
|
||||
USER=$2
|
||||
shift 2
|
||||
;;
|
||||
--password)
|
||||
PASSWORD=$2
|
||||
shift 2
|
||||
;;
|
||||
--bandwidth)
|
||||
BANDWIDTH=$2
|
||||
shift 2
|
||||
;;
|
||||
--mtu)
|
||||
WG_MTU=$2
|
||||
shift 2
|
||||
;;
|
||||
'')
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
escape_ip () {
|
||||
local gw_ip=$1
|
||||
|
||||
# ipv4 processing
|
||||
ret_ip=$(echo $gw_ip | tr '.' '_')
|
||||
|
||||
# ipv6 processing
|
||||
ret_ip=$(echo $ret_ip | tr ':' '_')
|
||||
ret_ip=$(echo $ret_ip | cut -d '[' -f 2)
|
||||
ret_ip=$(echo $ret_ip | cut -d ']' -f 1)
|
||||
|
||||
echo $ret_ip
|
||||
}
|
||||
|
||||
register_client_interface () {
|
||||
local pubkey=$1
|
||||
local gw_ip=$2
|
||||
local gw_port=$3
|
||||
local endpoint=$4
|
||||
local mtu_client=$5
|
||||
|
||||
gw_key=$(uci get wgclient.@client[0].wg_key)
|
||||
interface_name="gw_$(escape_ip $endpoint)"
|
||||
port_start=$(uci get wgclient.@client[0].port_start)
|
||||
port_end=$(uci get wgclient.@client[0].port_end)
|
||||
base_prefix=$(uci get wgclient.@client[0].base_prefix)
|
||||
|
||||
port=$(next_port $port_start $port_end)
|
||||
ifname="wg_$port"
|
||||
|
||||
offset=$(($port - $port_start))
|
||||
client_ip=$(owipcalc $base_prefix add $offset next 128)
|
||||
client_ip_assign="${client_ip}/128"
|
||||
|
||||
echo "Installing Interface With:"
|
||||
echo "Endpoint ${endpoint}"
|
||||
echo "Client IP ${client_ip}"
|
||||
echo "Port ${port}"
|
||||
echo "Pubkey ${pubkey}"
|
||||
|
||||
ip link add dev $ifname type wireguard
|
||||
|
||||
ip -6 a a dev $ifname $client_ip
|
||||
wg set $ifname listen-port $port private-key $gw_key peer $pubkey allowed-ips ::/0 endpoint "${endpoint}:${gw_port}"
|
||||
ip link set up dev $ifname
|
||||
ip link set mtu $mtu_client dev $ifname # configure mtu here!
|
||||
}
|
||||
|
||||
# rpc login
|
||||
token="$(request_token $IP $USER $PASSWORD)"
|
||||
if [ $? != 0 ]; then
|
||||
echo "failed to register token"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# now call procedure
|
||||
case $CMD in
|
||||
"get_usage")
|
||||
wg_rpcd_get_usage $token $IP
|
||||
;;
|
||||
"register")
|
||||
gw_pub=$(uci get wgclient.@client[0].wg_pub)
|
||||
gw_pub_string=$(cat $gw_pub)
|
||||
register_output=$(wg_rpcd_register $token $IP $BANDWIDTH $WG_MTU $gw_pub_string)
|
||||
if [ $? != 0 ]; then
|
||||
echo "Failed to Register!"
|
||||
exit 1
|
||||
fi
|
||||
pubkey=$(echo $register_output | awk '{print $2}')
|
||||
ip_addr=$(echo $register_output | awk '{print $4}')
|
||||
port=$(echo $register_output | awk '{print $6}')
|
||||
client_ip=$(echo $register_output | awk '{print $8}')
|
||||
register_client_interface $pubkey $ip_addr $port $IP $WG_MTU
|
||||
;;
|
||||
*) echo "Usage: wg-client-installer [cmd] --ip [2001::1] --user wginstaller --password wginstaller" ;;
|
||||
esac
|
19
net/wg-installer/wg-server/config/wginstaller.json
Normal file
19
net/wg-installer/wg-server/config/wginstaller.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"wginstaller": {
|
||||
"description": "WireGuard Installer",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"wginstaller": [ "*" ],
|
||||
"session": [
|
||||
"access",
|
||||
"login"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"wginstaller": [ "*" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
net/wg-installer/wg-server/config/wgserver.conf
Normal file
6
net/wg-installer/wg-server/config/wgserver.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
config server
|
||||
option port_start '51820'
|
||||
option port_end '52820'
|
||||
option base_prefix '2002::/64'
|
||||
option wg_key '/root/wg.key'
|
||||
option wg_pub '/root/wg.pub'
|
22
net/wg-installer/wg-server/lib/install_wginstaller_user.sh
Normal file
22
net/wg-installer/wg-server/lib/install_wginstaller_user.sh
Normal file
|
@ -0,0 +1,22 @@
|
|||
#!/bin/sh
|
||||
|
||||
# do not override already existing user!!!
|
||||
[ "$(uci show rpcd | grep wginstaller)" ] && exit 0
|
||||
|
||||
# install wginstaller user with standard credentials
|
||||
# user: wginstaller
|
||||
# password: wginstaller
|
||||
uci add rpcd login
|
||||
uci set rpcd.@login[-1].username='wginstaller'
|
||||
|
||||
password=$(uhttpd -m wginstaller)
|
||||
uci set rpcd.@login[-1].password=$password
|
||||
uci add_list rpcd.@login[-1].read='wginstaller'
|
||||
uci add_list rpcd.@login[-1].write='wginstaller'
|
||||
uci commit rpcd
|
||||
|
||||
# restart rpcd
|
||||
/etc/init.d/rpcd restart
|
||||
|
||||
# restart uhttpd
|
||||
/etc/init.d/uhttpd restart
|
46
net/wg-installer/wg-server/lib/wg_functions.sh
Normal file
46
net/wg-installer/wg-server/lib/wg_functions.sh
Normal file
|
@ -0,0 +1,46 @@
|
|||
. /usr/share/libubox/jshn.sh
|
||||
. /usr/share/wginstaller/wg.sh
|
||||
|
||||
wg_get_usage () {
|
||||
num_interfaces = $(wg show interfaces | wc -w)
|
||||
json_init
|
||||
json_add_int "num_interfaces" $num_interfaces
|
||||
echo $(json_dump)
|
||||
}
|
||||
|
||||
wg_register () {
|
||||
local uplink_bw=$1
|
||||
local mtu=$2
|
||||
local public_key=$3
|
||||
|
||||
base_prefix=$(uci get wgserver.@server[0].base_prefix)
|
||||
port_start=$(uci get wgserver.@server[0].port_start)
|
||||
port_end=$(uci get wgserver.@server[0].port_end)
|
||||
|
||||
port=$(next_port $port_start $port_end)
|
||||
ifname="wg_$port"
|
||||
|
||||
offset=$(($port - $port_start))
|
||||
gw_ip=$(owipcalc $base_prefix add $offset next 128) # gateway ip
|
||||
gw_ip_assign="${gw_ip}/128"
|
||||
|
||||
gw_key=$(uci get wgserver.@server[0].wg_key)
|
||||
gw_pub=$(uci get wgserver.@server[0].wg_pub)
|
||||
wg_server_pubkey=$(cat $gw_pub)
|
||||
|
||||
# create wg tunnel
|
||||
ip link add dev $ifname type wireguard
|
||||
wg set $ifname listen-port $port private-key $gw_key peer $public_key allowed-ips ::0/0
|
||||
ip -6 a a $gw_ip_assign dev $ifname
|
||||
ip -6 a a fe80::1/64 dev $ifname
|
||||
ip link set up dev $ifname
|
||||
ip link set mtu $mtu dev $ifname
|
||||
|
||||
# craft return address
|
||||
json_init
|
||||
json_add_string "pubkey" $wg_server_pubkey
|
||||
json_add_string "gw_ip" $gw_ip_assign
|
||||
json_add_int "port" $port
|
||||
|
||||
echo $(json_dump)
|
||||
}
|
32
net/wg-installer/wg-server/wginstaller.sh
Normal file
32
net/wg-installer/wg-server/wginstaller.sh
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. /usr/share/wginstaller/wg_functions.sh
|
||||
|
||||
case "$1" in
|
||||
list)
|
||||
cmd='{ "get_usage": {},'
|
||||
cmd=$(echo $cmd ' "register": {"uplink_bw":"10", "mtu":"1400", "public_key": "xyz"} }')
|
||||
echo $cmd
|
||||
;;
|
||||
call)
|
||||
case "$2" in
|
||||
get_usage)
|
||||
read input
|
||||
logger -t "wginstaller" "call" "$2" "$input"
|
||||
wg_get_usage
|
||||
;;
|
||||
register)
|
||||
read input
|
||||
logger -t "wginstaller" "call" "$2" "$input"
|
||||
|
||||
json_load "$input"
|
||||
json_get_var uplink_bw uplink_bw
|
||||
json_get_var mtu mtu
|
||||
json_get_var public_key public_key
|
||||
|
||||
wg_register $uplink_bw $mtu $public_key
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
Loading…
Reference in a new issue