Creating Secure Private Networks With ZeroTier VPN
Create a secure private network with ZeroTier VPN. It helps safely connect to your machines from all over the world, and manage the network with REST API.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
Connecting remotely to computers remains a challenge. The industry’s response to that is VPN. ZeroTier is a popular VPN platform for creating secure private networks. It helps safely connect to your machines from anywhere in the world and safely access servers in the cloud. It enables intranet applications for external users. Last but not least, it can be used to provide remote assistance to family and friends, while keeping them safe from bad wolves out there.
Best of all, ZeroTier is free for up to 50 connected machines. Ability to manage it with REST API and scripts makes it particularly interesting for advanced users.
What Does It Do?
Brief introduction into what VPN is about and how it can be useful.
If you already know what VPN is, you can go straight to the tutorial.
What is VPN is becoming increasingly unclear these days. For many, VPN is something used for anonymous file-sharing or a remedy for overly restrictive DRM protections of streaming platforms. But is that all? Far from it!
Experienced gamers surely know Hamachi. Many years ago it was used to play multi-user LAN games over the internet. Hamachi, also a VPN platform, allowed the creation of local networks over the internet.
VPN’s primary use is the creation of safe private networks over an inherently unsafe medium such as public internet. All other things, such as providing a level of privacy or fooling DRM restrictions, are just side-effects of this primary function.
Whenever I need access to my home PC while on travel, I face a big dilemma. My computer has to run software which enables such connection. It has to run a remote-access daemon such as Windows RDP or VNC server. Router ports have to be opened. Firewall rules have to be relaxed. It introduces risks and attack vectors, which rogue parties can use to gain access.
VPN server steps in as an intermediate trusted party. Network members connect to the VPN server using a secure and encrypted connection. Because the connection is initiated by the client, there is no need to open ports or run anything listening permanently. VPN server assigns connected clients with local-range IP addresses. The server routes all traffic between machines as they talk to each other, using a secure encrypted channel. Simple, yet secure and fast.
From the user’s perspective, this feels like good old LAN: safe, secure, and fully isolated from outside access. Network members can be scattered all over the world yet they act as if connected to the same local network.
Why ZeroTier?
If you have a Linux server at your disposal, it’s actually not so hard to run your own VPN, as there are many commercial VPN products. Many of us use corporate VPN for remote work. Even Hamachi is still there, only with a five-computers restriction on the free plan. ZeroTier is yet another such platform.
I like ZeroTier for its spartan simplicity. For me, it’s been the easiest VPN platform to set up. Equally important is their generous free plan, which allows connecting up to 50 computers. An additional benefit for computer geeks is ZeroTier API. The platform can be managed and controlled using REST API. This allows scripting and automation of connections, deployments, tests, etc.
Installation and Configuration
To create private network using ZeroTier, you need to:
- Sign up at https://www.zerotier.com/
- Log in
- Click CREATE NETWORK button
Your first virtual private network has been created.
The UI is sturdy and simple. I hope it stays that way.
You will need the assigned network identifier to connect clients to the network. As you can see, you can create multiple networks. This can be very useful. For example, one network for work, another for family or friends, so that your uncle won’t attempt logging in to your VPS.
Now it’s time to connect your devices: computers, tablets, etc. Install ZeroTier client on each one of them. All popular platforms are supported: Linux, MacOS, Windows, Android, iOS, and even FreeBSD. Find the software on https://www.zerotier.com/download/.
Installation on Linux is easy:
curl -s https://install.zerotier.com | sudo bash
Once installed, use zerotier-cli
to connect. On other platforms, there are usually some GUI. Check documentation for details. You will need the identifier of the network which you’ve just created:
sudo zerotier-cli join <networkid>
You should see 200 join OK
. Your computer has joined the network. But it still needs to be authorized to use the network. Otherwise, it wouldn’t be quite secure. ;-)
Go back to https://my.zerotier.com and click on the listed network. You will see the details of the network. Scroll down, to find the list of connected clients. Your just connected client should be there, for example:
Check the checkbox on the left, and the client is now authorized to use the network. Give the client a unique friendly name, such as home-pc
or mom
. Wait a few seconds, and a local IP address should be assigned to the connected client. This is the address to use when connecting to this computer from another machine on the same private network.
Repeat the same on every other computer or device which you want to be part of the network. It can be your VPS, your family computers, RaspberryPI in the basement, iPad, or anything you want to access securely. All connected machines can run different operating systems, yet they will be able to connect to each other using ZeroTier.
You have just built your first virtual private network.
What Can I Do With It?
Take note of the IP address of the computer you want to connect to. Now ping
it, and it responds. The thrill of it! From here, anything is possible, such as:
Remote Desktop Access
Assume that your computers run Windows. Enable Remote Desktop on them. Now you can connect to your Windows desktops using the RDP client. Enter the IP address assigned by ZeroTier and connect safely and securely, even if you are on another continent. No RDP ports had to be opened on the internet router. The computer remains safe from login attempts from the outside. Similarly, on Linux machines, you can install a VNC server and enjoy safe access to desktop sessions.
Shell Access
On Linux and Mac machines, I usually enable SSH, a.k.a. secure shell. Now I can remotely log on, transfer files, and execute commands using ssh
and scp
straight from the terminal. All it takes on Linux is to run
sudo apt install openssh-server sudo ufw enable ssh
and your machine is ready for incoming SSH connections.
Intranet Applications
You can run intranet web applications on your connected computers, such as team wiki or department discussion forum. All members of your private network can access it safely, without the inherent risk of exposing the internal website to the outside world. Quite useful for businesses big and small.
Networked Devices
You can access network printers and other devices. Anything that can be done on LAN, can be done with VPN, no matter where you are.
Enjoy!
ZeroTier API
Time for the real deal. ZeroTier network can be managed using REST API, documented at https://docs.zerotier.com/central/v1/. Also, ZeroTier client software, running on your computer, can be controlled using REST API described at https://docs.zerotier.com/service/v1. ZeroTier GUI and CLI themselves use this API to do their job.
This opens amazing possibilities. You can automate your processes, create your own UI for managing the network, pull information about ZeroTier nodes straight into your own applications, etc.
I personally use ZeroTier API to simplify access to my family network. Being “the computer guy” of the family, I often need to connect and help. I use SSH and VNC connections over the ZeroTier network to run periodic checks and updates, resolve problems, etc.
To connect to mom’s computer using ssh (yes, she runs Linux) I need her IP address. I can look it up on the ZeroTier account page. But it would be nice if ZeroTier helped me figure it out automatically. Ideally, I’d like to run a command like this:
zerotier mom
and this would:
- Determine whether my ZeroTier network is available
- Determine whether her computer is online
- Determine its IP address
- Connect using
ssh
- Tell me if anything went wrong
This is where ZeroTier API comes in handy.
ZeroTier API Token
First, you need an API token associated with your account. Log on to https://my.zerotier.com. Go to account settings and create a new token. Store the token safely, as it won’t be displayed again! If you lose it, you will have to create a new token.
The token has to be passed with API requests in the Authorization
header. For example, if your token is 88205430e4bd
, you need to pass the following HTTP header with each ZeroTier API request.
Authorization: bearer 88205430e4bd
Executing API Requests
Let’s start with ZeroTier network status. To retrieve it, use the following endpoint:
https://my.zerotier.com/api/v1/status
Use curl
and jq
to execute API request and parse the received JSON response:
curl -s -X GET -H "Authorization: bearer 88205430e4bd" "https://my.zerotier.com/api/v1/status" | jq
Example output:
{
"online": true,
"apiVersion": "1",
"user": {
"id": "80e468ce-c8a7-41da-a068-37c27af38370",
"type": "User",
"displayName": "Tomasz Waraksa",
"email": "tomasz@waraksa.net"
}
}
Use jq filters to extract specific fields from the response. For example, to extract API version, user name, and e-mail, use the following script:
TOKEN="88205430e4bd"
ENDPOINT="https://my.zerotier.com/api/v1/status"
STATUS=$(curl -s -X GET -H "Authorization: bearer $TOKEN" $ENDPOINT)
MESSAGE=echo $STATUS | jq -r '. | "API: v.\(.apiVersion)\nUser: \(.user.displayName)\nE-mail: \(.user.email)"'
echo $MESSAGE
Everything you can see and do within ZeroTier website, you can do with API. This includes:
- Listing your networks
- Listing clients connected to networks
- Determining IP addresses of connected clients
This is exactly what I needed for building my zerotier mom
command.
Retrieving Network Status and Client Details
I wrote a bash script that retrieves information about my ZeroTier network and connected clients. Save it in the zerotier-status
file, and remember to add execute permission.
Run the script without any parameters to display the status of the API, your default network, and list of clients connected to it.
zerotier-status
Run it with the client name, to retrieve the current IP address of the specified client:
zerotier-status home-pc
Code: zerotier-status Shell Script
#!/usr/bin/env bash
# zerotier-status
# bash script for retrieving status of ZeroTier network and connected clients
ZEROTIER_API="https://my.zerotier.com/api/v1"
ZEROTIER_API_TOKEN="your-api-token"
# Execute ZeroTier API request
# $1 endpoint
request () {
local endpoint="$1"
local response=$(curl -s -X GET -H "Authorization: bearer $ZEROTIER_API_TOKEN" "$ZEROTIER_API/$endpoint" | jq)
echo $response
}
# Retrieves ZeroTier API status
status () {
request "status" | jq -r '. | "API: v.\(.apiVersion)\nUser: \(.user.displayName)\n \(.user.email)"'
}
# Retrieves list of networks
networks () {
local response=$(request "network")
echo "$response" | jq -r '.[] | "\(.id) \(.config.name)"'
}
# Retrieves identifier of the first network
network () {
local response=$(request "network")
local network_id=$(echo "$response" | jq -r '.[0] | "\(.id)"')
echo $network_id
}
# Retrieves list of clients currently logged into the specified network
# $1 Network identifier
clients () {
local network_id="$1"
# request "network/$network_id/member" | jq
request "network/$network_id/member" | jq -r '.[] | select(.physicalAddress | . != null) | "\(.name) \(.config.ipAssignments[0])"'
}
# Retrieves IP address of a client connected to the specified network
# $1 Network identifier
# $2 Client name
ipOfClient () {
local network_id="$1"
local name="$2"
local all=$(clients "$network_id" "$name")
local found=$(echo "$all" | grep "$name")
local arr=($found)
echo ${arr[1]}
}
# If run with client name, returns client's IP address,
# otherwise shows the whereabouts of your ZeroTier private network.
CLIENT="$1"
if [ "$CLIENT" == "" ]; then
echo "ZeroTier"
echo "-------------------------------"
status
echo
echo "Network"
echo "-------------------------------"
NETWORK_ID=$(network)
echo "$NETWORK_ID"
echo
echo "Clients"
echo "-------------------------------"
clients "$NETWORK_ID"
echo
else
NETWORK_ID=$(network)
ipOfClient "$NETWORK_ID" "$CLIENT"
fi
Connecting to ZeroTier Clients
I’ve created another script, named zerotier
, which uses the previous script to determine client IP and connect using ssh. Place them both somewhere in the path. Connecting to home PC is now as easy as:
zerotier home-pc
This will connect to my home PC using the account I’m currently logged in with. You can also connect using different accounts present on the remote machine, for example:
zerotier home-pc tomasz
The script can also be used to display network status and restart the ZeroTier daemon, if there’s any problem:
zerotier status zerotier restart
Run the script without parameters to see the help. Enjoy!
Code: ZeroTier Shell Script
#!/usr/bin/env bash
# zerotier
# bash script for connecting to ZeroTier clients using ssh
# ZeroTier client to connect or command to execute is passed as first parameter
CLIENT="$1"
COMMAND="$1"
# User account to login as is passed as second parameter.
# If not specified, current account is used, unless
# you have defined below another default account for that machine
LOGIN="$2"
# Default accounts used to log into clients
declare -A USERS
USERS=(
["jan-pc"]="jan"
["mary-pc"]="mary"
["bob-pc"]="bob"
)
if [ "$CLIENT" == "" ]; then
echo "Connects to ZeroTier client in your private network using SSH"
echo
echo "Syntax:"
echo
echo " zerotier <client> <user>"
echo " zerotier <command>"
echo
echo " client: Name of ZeroTier network client to log into"
echo " user: Account to login as"
echo " command: Command to execute:"
echo " restart Restarts ZeroTier daemon"
echo " status Displays status of ZeroTier network"
echo
elif [ "$COMMAND" == "restart" ]; then
echo "Restarting ZeroTier ..."
sudo systemctl restart zerotier-one
echo "Done."
elif [ "$COMMAND" == "status" ]; then
zerotier-status
else
# Determine account to log in as.
# It can be passed explicitly as second parameter.
# If not present, check if defined above.
# Finally, if none defined, assume currently logged in user.
[[ "$LOGIN" == "" ]] && LOGIN="${USERS[$CLIENT]}"
LOGIN="${LOGIN:-$USER}"
echo "Connecting to ZeroTier client $CLIENT ..."
echo "Fetching IP address ..."
IP=$(zerotier-status "$CLIENT")
if [ "$IP" == "" ]; then
echo "Client $CLIENT is invalid or currently not connected"
else
echo "Establishing SSH connection $LOGIN@$IP ..."
ssh $LOGIN@$IP
fi
fi
Disclaimer
This article is not promoting any of the described products, services, or vendors. We don't have any commercial interest nor associations with them. We're not trying to suggest that these products or services are best for you, nor promising that your experience will be the same.
Published at DZone with permission of Tomasz Waraksa. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments