Community discussions

MikroTik App
 
User avatar
Amm0
Forum Guru
Forum Guru
Topic Author
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

HOWTO: Import ZeroTier Members into Mikrotik DNS using $ZT2DNS

Tue Feb 27, 2024 7:20 am

I have a bash scripts that used `jq` and `awk` to create DNS host files using the ZeroTier API to extract ZT member name and IPs (see bottom). I "ported" the linux-style one to Mikrotik script today, thought I share since imagine other have similar need to get hostname from the list of zerotier members, automatically.

Calling ZeroTier's API is actually now possible with the new JSON support in RouterOS 7.13+ – older versions will NOT work with script. The code uses /tool/fetch with a user's API token to get a JSON array of ZeroTier members. That's converted to an scripting array using new ":deserialize from=json", and then looped to add static DNS entries to Mikrotik, checking if name already exists.

First, to use ZeroTier API, you need to create a "API Access Tokens" at bottom of https://my.zerotier.com/account . You'll want to keep this someplace safe, but you'll need to use that in the "token=" variable in the script below. You'll also need the ZeroTier "Network ID" for the network you want to "export" DNS entries from. Only one network can be extracted at a time. If network= is not provided, the first running ZeroTier interface is used.

To use it... next add the following function to /system/scripts or scheduler or cut-and-paste it to test:
:global ZT2DNS do={
    :if ($1="help") do={
        :put "\$ZT2DNS - updates static DNS on Mikrotik from a ZeroTier network"
        :put "  usage: \$ZT2DNS token=<api_token> [network=<network_id>] [suffix=<dns_domain>]"
        :put "     <api_token> is 'API Access Tokens' from https://my.zerotier.com/account "
        :put "     <network_id> is ZeroTier network ID to use. Default: first running ZT interface"
        :put "     <suffix> added to name= in DNS entries, must include any leading dot. Default: \"\""
        :return [:nothing]
    }
    :if ([:typeof $token]!="str") do={:error "token= must be specific with a ZeroTier API token"}
    :local ztnet $token 
    :if ([:typeof $network]="str") do={
        :set ztnet $network
    } else={:set ztnet [/zerotier/interface/get ([/zerotier/interface/find running]->0) network]} 
    :local dnssuffix $suffix
    :local ztmembers [:deserialize from=json ([/tool/fetch url="https://api.zerotier.com/api/v1/network/$ztnet/member" http-header-field="Authorization: token $token" as-value output=user]->"data")]
    :foreach k,v in=$ztmembers do={
        :foreach ip in=($v->"config"->"ipAssignments") do={
            :if ([:len [/ip/dns/static/find name="$($v->"name")$dnssuffix"]]=0) do={
                /ip/dns/static/add address=$ip name="$($v->"name")$dnssuffix"
                :put "/ip/dns/static add address=$ip name=$($v->"name")$dnssuffix"
            } else={:put "# skip: $ip with name $($v->"name")$dnssuffix"}
        } 
    }
}
# v1.2

And full example to call function is:
$ZT2DNS token="OcKJlkasdkjaasdfSDFASD"  suffix=".example.com" network="123abc456cba"
This last line can be added after the script if used script/scheduler with your ZeroTier network id and token – but it's this last line that actually "calls" the above function to fetch DNS records from ZeroTier.

There is a help screen using "$ZT2DNS help" that described the parameters – only token= is required strictly required:
[admin@Mikrotik] > $ZT2DNS help

$ZT2DNS - updates static DNS on Mikrotik from a ZeroTier network

usage: $ZT2DNS token=<api_token> [network=<network_id>] [suffix=<dns_domain>]
<api_token> is 'API Access Tokens' from https://my.zerotier.com/account
<network_id> is ZeroTier network ID to use. Default: first running ZT interface
<suffix> is appended to name= in DNS entries, must include any leading dot (optional)

LMK if you have problem/issues. My old script below has worked, but with new JSON support in 7.13...it's now possible to easily do on Mikrotik itself.


---
FWIW, my less sophisticated version using Linux tools almost makes Mikrotik scripting look friendly (and requires jq [& awk] packages), but this has worked for me to get DNS records for Mikrotik from a ZeroTier network. I manually run it as needed but above Mikrotik script could be /system/scheduler on the Mikrotik itself to update periodically.
ZT_TOKEN=zerotier-API-token-FROM-my.zerotier.com-AccountPage
ZT_NET=zt-network-id
curl -X GET -H "Authorization: token $ZT_TOKEN" https://api.zerotier.com/api/v1/network/$ZT_NET/member |
jq -r '(.[] | [.config.ipAssignments[], .name]) | @tsv' |
awk 'length($1)>0 && length($2)>0 { print "/ip/dns/static add address="$1" name="$2".zt" } '

Who is online

Users browsing this forum: Ahrefs [Bot], GoogleOther [Bot], Jhonny, jonmansey and 48 guests