Browse Source

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>
lilik-openwrt-22.03
Nick Hainke 4 years ago
committed by Polynomdivision
parent
commit
3a6949dfaf
11 changed files with 494 additions and 0 deletions
  1. +69
    -0
      net/wg-installer/Makefile
  2. +26
    -0
      net/wg-installer/README.md
  3. +13
    -0
      net/wg-installer/common/wg.sh
  4. +8
    -0
      net/wg-installer/wg-client/config/wgclient.conf
  5. +134
    -0
      net/wg-installer/wg-client/lib/rpcd_ubus.sh
  6. +119
    -0
      net/wg-installer/wg-client/wg-client-installer.sh
  7. +19
    -0
      net/wg-installer/wg-server/config/wginstaller.json
  8. +6
    -0
      net/wg-installer/wg-server/config/wgserver.conf
  9. +22
    -0
      net/wg-installer/wg-server/lib/install_wginstaller_user.sh
  10. +46
    -0
      net/wg-installer/wg-server/lib/wg_functions.sh
  11. +32
    -0
      net/wg-installer/wg-server/wginstaller.sh

+ 69
- 0
net/wg-installer/Makefile View 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
- 0
net/wg-installer/README.md View 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
- 0
net/wg-installer/common/wg.sh View 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
- 0
net/wg-installer/wg-client/config/wgclient.conf View 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
- 0
net/wg-installer/wg-client/lib/rpcd_ubus.sh View 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
- 0
net/wg-installer/wg-client/wg-client-installer.sh View 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
- 0
net/wg-installer/wg-server/config/wginstaller.json View File

@ -0,0 +1,19 @@
{
"wginstaller": {
"description": "WireGuard Installer",
"read": {
"ubus": {
"wginstaller": [ "*" ],
"session": [
"access",
"login"
]
}
},
"write": {
"ubus": {
"wginstaller": [ "*" ]
}
}
}
}

+ 6
- 0
net/wg-installer/wg-server/config/wgserver.conf View 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
- 0
net/wg-installer/wg-server/lib/install_wginstaller_user.sh View 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
- 0
net/wg-installer/wg-server/lib/wg_functions.sh View 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
- 0
net/wg-installer/wg-server/wginstaller.sh View 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…
Cancel
Save