Hi everyone
Could I ask for help with script to change NordVPN server to recommended?
https://nordvpn.com/pl/servers/tools/
I found api instruction:
https://blog.sleeplessbeastie.eu/2019/02/18/how-to-use-public-nordvpn-api/
Mikrotik and NordVpn connected together with this tutorial:
https://wiki.mikrotik.com/wiki/IKEv2_EAP_between_NordVPN_and_RouterOS
Thank You very much for your interest in the topic and help
The API returns json data, parsing that in RouterOS is not an easy task.
I am interested myself, but as the topic is really complex I did not yet give it a try.
maybe this will help
https://github.com/Winand/mikrotik-json-parser
what do you thing about this script?
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?limit=1") output=user as-value ]->"data");
:set NewNordvpnAddress [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]];
:set NewNordvpnAddress [:pick $NewNordvpnAddress 11 29];
:if ($CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
v2
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?limit=1") output=user as-value ]->"data");
:local Ikev2Nordvpn [:find $NewNordvpnAddress "ikev2"];
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 29];
:if ($Ikev2Nordvpn > 0 && $CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
v3
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?limit=1") output=user as-value ]->"data");
:local Ikev2Nordvpn [:find $NewNordvpnAddress "ikev2"];
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 29];
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data");
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent\":"] [:find $CurrentNordvpnLoad "}"]] 9 12];
:if ($CurrentNordvpnLoad > 30 && $Ikev2Nordvpn > 0 && $CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
v4
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data");
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent"] [:find $CurrentNordvpnLoad "}"]] 9 12];
:if ($CurrentNordvpnLoad > 20) do={
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?limit=1") output=user as-value ]->"data");
:local Ikev2Nordvpn [:find $NewNordvpnAddress "ikev2"];
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 29];
:if ($Ikev2Nordvpn > 0 && $CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
}
v5
####DESCRIPTION####
#https://api.nordvpn.com/v1/servers/countries
#:local ApiNordvpnCountry 195;
#https://api.nordvpn.com/v1/servers/groups
#:local ApiNordvpnGroup 25;
#MaxLoad is usded to check the actual server load, if the load go over the MaxLoad, the script will change the vpn server
#:local ApiNordvpnMaxLoad 20;
####CONFIG####
:local ApiNordvpnCountry;
:local ApiNordvpnGroup;
:local ApiNordvpnMaxLoad 20;
####SCRIPT####
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data");
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent"] [:find $CurrentNordvpnLoad "}"]] 9 99];
:if ($CurrentNordvpnLoad > $ApiNordvpnMaxLoad) do={
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?filters[servers_groups]=$ApiNordvpnGroup&filters[servers_technologies][identifier]=ikev2&filters[country_id]=$ApiNordvpnCountry&limit=1") output=user as-value ]->"data");
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 99];
:if ($CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
}
v6
####DESCRIPTION####
#ApiNordvpnCountry is used to select a country, if it is empty then the country will be selected automatically
#:local ApiNordvpnCountry 195;
#https://api.nordvpn.com/v1/servers/countries
#ApiNordvpnGroup is used to select server type, if it is empty then will be selected automatically
#:local ApiNordvpnGroup 25;
#https://api.nordvpn.com/v1/servers/groups
#ApiNordvpnMaxLoad is used to define the maximum acceptable load of the current server, after exceeding this value the server will be changed
#:local ApiNordvpnMaxLoad 20;
####CONFIG####
:local ApiNordvpnCountry;
:local ApiNordvpnGroup 15;
:local ApiNordvpnMaxLoad 20;
####SCRIPT####
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address];
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data");
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent"] [:find $CurrentNordvpnLoad "}"]] 9 99];
:if ($CurrentNordvpnLoad > $ApiNordvpnMaxLoad) do={
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?filters[servers_groups]=$ApiNordvpnGroup&filters[country_id]=$ApiNordvpnCountry&filters[servers_technologies][identifier]=ikev2&limit=1") output=user as-value ]->"data");
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 99];
:if ([:len $NewNordvpnAddress] = 0) do={
:log info "NordVPN: no server found for the current configuration";
} else={
:if ($CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress;
}
}
}
You do not need to end every line witch ;.
Its only needed when you have several commands on same line.
thank you for your comments, does it look better now?
####DESCRIPTION####
#ApiNordvpnCountry is used to select a country, if it is empty then the country will be selected automatically
#:local ApiNordvpnCountry 195
#https://api.nordvpn.com/v1/servers/countries
#ApiNordvpnGroup is used to select server type, if it is empty then will be selected automatically
#:local ApiNordvpnGroup 25
#https://api.nordvpn.com/v1/servers/groups
#ApiNordvpnMaxLoad is used to define the maximum acceptable load of the current server, after exceeding this value the server will be changed
#:local ApiNordvpnMaxLoad 20
####CONFIG####
:local ApiNordvpnCountry
:local ApiNordvpnGroup 15
:local ApiNordvpnMaxLoad 20
####SCRIPT####
:if (([:typeof $ApiNordvpnCountry] = "num" || [:len $ApiNordvpnCountry] = 0) && ([:typeof $ApiNordvpnGroup] = "num" || [:len $ApiNordvpnGroup] = 0) && ([:typeof $ApiNordvpnMaxLoad] = "num" || [:len $ApiNordvpnMaxLoad] = 0)) do={
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address]
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data")
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent"] [:find $CurrentNordvpnLoad "}"]] 9 99]
:if ($CurrentNordvpnLoad > $ApiNordvpnMaxLoad) do={
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?filters[servers_groups]=$ApiNordvpnGroup&filters[country_id]=$ApiNordvpnCountry&filters[servers_technologies][identifier]=ikev2&limit=1") output=user as-value ]->"data")
:if ($NewNordvpnAddress = "[]") do={
:log info "NordVPN: server not found for the current configuration"
} else={
:local NewNordvpnLoad [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "nordvpn.com"] [:find $NewNordvpnAddress ",\"status"]] 20 99]
:if ($CurrentNordvpnLoad > $NewNordvpnLoad) do={
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 99]
:if ($CurrentNordvpnAddress != $NewNordvpnAddress) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress
}
}
}
}
} else={
:log info "NordVPN: error! variables must be numbers!"
}
v8
####DESCRIPTION####
#ApiNordvpnCountry is used to select a country, if it is empty then the country will be selected automatically
#:local ApiNordvpnCountry 195
#https://api.nordvpn.com/v1/servers/countries
#ApiNordvpnGroup is used to select server type, if it is empty then will be selected automatically
#:local ApiNordvpnGroup 25
#https://api.nordvpn.com/v1/servers/groups
#ApiNordvpnMaxLoad is used to define the maximum acceptable load of the current server, after exceeding this value the server will be changed
#:local ApiNordvpnMaxLoad 40
####CONFIG####
:local ApiNordvpnCountry
:local ApiNordvpnGroup 15
:local ApiNordvpnMaxLoad 20
####SCRIPT####
:if (([:typeof $ApiNordvpnCountry] = "num" || [:len $ApiNordvpnCountry] = 0) && ([:typeof $ApiNordvpnGroup] = "num" || [:len $ApiNordvpnGroup] = 0) && ([:typeof $ApiNordvpnMaxLoad] = "num" || [:len $ApiNordvpnMaxLoad] = 0)) do={
:local CurrentNordvpnAddress [/ip ipsec peer get [find name=NordVPN] address]
:local CurrentNordvpnLoad ([/tool fetch url=("https://api.nordvpn.com/server/stats/$CurrentNordvpnAddress") output=user as-value ]->"data")
:set CurrentNordvpnLoad [:pick [:pick $CurrentNordvpnLoad [:find $CurrentNordvpnLoad "percent"] [:find $CurrentNordvpnLoad "}"]] 9 99]
:if ($CurrentNordvpnLoad > $ApiNordvpnMaxLoad) do={
:local NewNordvpnAddress ([/tool fetch url=("https://api.nordvpn.com/v1/servers/recommendations\?filters[servers_groups]=$ApiNordvpnGroup&filters[country_id]=$ApiNordvpnCountry&filters[servers_technologies][identifier]=ikev2&limit=1") output=user as-value ]->"data")
:if ($NewNordvpnAddress = "[]") do={
:log info "NordVPN: server not found for the current configuration"
} else={
:local NewNordvpnLoad [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "nordvpn.com"] [:find $NewNordvpnAddress ",\"status"]] 20 99]
:set NewNordvpnAddress [:pick [:pick $NewNordvpnAddress [:find $NewNordvpnAddress "hostname"] [:find $NewNordvpnAddress "\",\"load"]] 11 99]
:if (($CurrentNordvpnAddress != $NewNordvpnAddress) && ($CurrentNordvpnLoad > $NewNordvpnLoad)) do={
/ip ipsec peer set [ find name=NordVPN ] address=$NewNordvpnAddress
}
}
}
} else={
:log info "NordVPN: error! variables must be numbers!"
}
i need hep
i have variables for example:
ch-nl2.nordvpn.com
de655.nordvpn.com
pl85.nordvpn.com
I would like to receive such results:
ch-nl
de
pl
do you have any idea how to do this?
It does not look like the :find command support regex, just string match.
So this does not work:
:put [:find $"ch-nl2.nordvpn.com" "[0-9]"]
It then makes it hard to find on the string where an unknown number starts.
You can loop trough and test number by number from 0-9, but its ugly.
find :find <arg> <arg> <start> return position of substring or array element :put [:find "abc" "a" -1];
This give your output, but its ugly
{
:local info "ch-nl2.nordvpn.com"
:local pos
:for i from=0 to=9 do={
:local test [:find $info $i]
:if ([:typeof $test]="num") do={set $pos $test}
}
:put [:pic $info 0 $pos]
}
ch-nl