Hi and welcome! Click the button below if you enjoy the software and want to support my work. A lot of coffee is consumed as a software developer you know 😁
Needless to say, this is completely voluntary.
A simple bash script to speed up and simplify the deployment of WireGuard Road Warriors (mobile VPN clients) connecting to a MikroTik firewall running RouterOS.
The script will produce the RouterOS configuration required as well as a QR code to scan with the WireGuard mobile app. This will enable you to deploy a new mobile VPN client within a minute or two, and you don't have to send public keys back and forth between the mobile device and the router.
Here is a small command-line demo showing the WireGuard Tunnel Generator script in action.
Download the script from GitHub and place it inside your home directory.
The script needs three packages in order to operate correctly:
sudo apt install ipcalc-ng wireguard-tools qrencode
ipcalc-ng
is used to validate IP adress input.wireguard-tools
is used to generate private/public key pair.qrencode
is used to encode the WireGuard configuration into a QR code.
The script has only been tested on Debian but might also work on other operating systems.
The script accepts parameters you use to define the WireGuard configuration for each client deployed:
Usage:
./wg-tunnel-generator.sh [options] <mobile_peer_ip>
Options:
<mobile_peer_ip> Mobile peer IP address in CIDR notation, ie. 10.0.0.2/32
-a <subnet,...> One or more IP subnet(s) to be routed through the tunnel
-d <dns,...> One or more DNS server(s) to be used by the mobile client
-e <host[:port]> WireGuard endpoint on the firewall, ie. fw.example.com:13231
-h Print this help and exit
-n <name> Descriptive name for the mobile client
-p <public_key> Public key of the WireGuard interface on the firewall
-v Print verbose debugging information
The only required parameter is <mobile_peer_ip>
, which is the IP address to be assigned to the client; all other parameters (options) have default values that will be used if not overridden by the parameters passed to the script. Read more about default values in the upcoming section.
Example:
./wg-tunnel-generator.sh -n my-phone -a 10.50.0.0/16 -d 1.1.1.1,8.8.8.8 -e vpn.example.com:13231 -p "fb4r8zxzstQ+/GxULwnqW9mqDF3YrBT2SvcEHyXqoWM=" 10.50.50.2/32
The default options above can be modified simply by editing wg-tunnel-generator.sh
. This can be handy if you don't want to pass parameters every time you need to deploy a new road warrior.
Most often the same settings will be used for all mobile clients and the only parameters we need to pass to the script is the name
and the mobile_peer_ip
address.
# Pre-defined parameter values
ALLOWED_IPS="0.0.0.0/0"
DNS="1.0.0.1,1.1.1.1"
ENDPOINT="fw.example.com:13231"
FW_PUBLIC_KEY="0"
NAME="mobile-phone"
To simplify the example in the last section we can change the variables to:
# Pre-defined parameter values
ALLOWED_IPS="10.50.0.0/16"
DNS="1.1.1.1,8.8.8.8"
ENDPOINT="vpn.example.com:13231"
FW_PUBLIC_KEY="fb4r8zxzstQ+/GxULwnqW9mqDF3YrBT2SvcEHyXqoWM"
NAME="mobile-phone"
Now we can run the following command and still get the same result:
./wg-tunnel-generator.sh -n my-phone 10.50.50.2/32
One thing to keep in mind when running the script is whether a WireGuard Interface has been configured on the router or not.
This is important because we only need one interface for the WireGuard endpoint on the router (assuming that all VPN clients are put on the same subnet).
If the interface is created from RouterOS, the private/public key pair is generated automatically. If not, just let the script create the configuration for you.
When the interface is pre-configured you need to get the public key from the configuration in RouterOS.
WinBox:
- Go to WireGuard, open the
wg_mobile
interface in the WireGuard tab and copy the public key.
Terminal:
- Run the command
:put ([/interface/wireguard/get wg_mobile ]->"public-key")
and copy the public key.
Here we assume that the name of the WireGuard interface is
wg_mobile
.
When the interface doesn't exists you can have the script generate the configuration for you; this is the default behavior of the script and is also demonstrated in the example screenshot at the top.
There are two ways to change this behavior:
- Pass the public key as an argument to the script:
-p "fb4r8zxzstQ+/GxULwnqW9mqDF3YrBT2SvcEHyXqoWM="
- Set the variable
FW_PUBLIC_KEY
to the public key you got from the WireGuard interface in RouterOS, for instanceFW_PUBLIC_KEY=fb4r8zxzstQ+/GxULwnqW9mqDF3YrBT2SvcEHyXqoWM=
.
When the script is run there are a few things that are happening.
Every time the script is run we:
- Generate new private/public keys for the mobile client.
- Generate a new shared secret. This is a random string of characters (Base64 encoded).
Every time the script:
- Is run without
-p
, a new private/public key pair is generated. - Is run with
-p
, the existing private/public key pair generated in RouterOS, is used. The same goes when the variableFW_PUBLIC_KEY
is set as described above.
The private and public keys of the firewall is only created once and then used by all clients.
The WireGuard configuration to be imported into the WireGuard client is exported into a configuration file with the name provided by the -n
argument.
As an example, this command:
./wg-tunnel-generator.sh -n my-phone 10.50.50.2/32
Will save the WireGuard configuration in the file ./configs/my-phone.conf
:
[Interface]
Address = 10.50.50.2/32
PrivateKey = 4NhTvZkoPoUyG4Vc6bVA6bnqaH+2pyWioJr5mXiDMFw=
DNS = 1.0.0.1,1.1.1.1
[Peer]
PublicKey = fb4r8zxzstQ+/GxULwnqW9mqDF3YrBT2SvcEHyXqoWM=
Endpoint = fw.example.com:13231
PresharedKey = 0zQbfFxCWf+v3j0uiaS+ozAPDdwRHIQktAjnMcST9wo=
AllowedIPs = 0.0.0.0/0
The configuration in the WireGuard Configuration section above will also be encoded into a QR code using the qrencode
utility.
This QR code will:
- Be printed as text in the terminal for instant use.
- Saved into a PNG image file
./configs/my-phone.png
.
The RouterOS configuration needed in order to get the tunnel up and running will also be available for you.
The configuration will:
- Be printed as text in the terminal for instant use; just copy and paste into RouterOS.
- Saved into a RouterOS Script file
./configs/my-phone.rsc
.
For more information on how to setup a WireGuard Tunnel between a mobile device and MikroTik RouterOS: