Mikrotik RouterOS + PHP script on the site. Empowerment
In the days of ROS 5.x, there was a need to raise a tunnel to a router with a white dynamic address. In ROS 5, we did not specify a name, but an IP address. Option 2: DDNS service, the implementation of which we will consider briefly and the second of which will be the story.
There was an idea to make a center where the routers would report their addresses, and read the addresses of others. It was decided to go the path of least resistance - a site on the PHP.
At the moment, a couple of simple things have been implemented.
Implemented through a script request specifying your (router) name and password:
The name and password are needed so that no one can disguise as you and does not initiate the connection of your router to your own or cannot read the address of your router. Through the fetch utility, we open the desired script on the server and pass the name and password through GET. The script through $ _SERVER ['REMOTE_ADDR'] receives the external address of the router and writes it to the database.
Again, through the same utility, we call the web script:
dst-path = "adr.txt" - indicate that the received data is saved to a file. On the web page itself, we have a purely text with the address of the requested router:
$ query = "SELECT address FROM table_routers WHERE ((id = '$ _ GET [i]') AND (password = '$ _ GET [p]'))";
$ adr = mysql_query ($ query) or die (mysql_error ());
$ router = mysql_fetch_assoc ($ adr);
echo $ router [address];
: global routeradr [/ file get adr.txt contents] - assign the value of the file content to the global variable. Then this variable can be applied according to need and desire.
Everything is the same as in the previous script, but we import the file into the router config, and then delete this file.
Why is this necessary? For example, you inattentively cut off access to a router in a firewall. Then you can add a script for this router on the site with which you indicate the corrected firewall rules. Following the schedule, the router connects to the site, where the PHP looks to see if there are any untransmitted scripts in the database for this router:
First, we check whether the password and router number are set correctly (so that no one else can read your script, maybe you can change the passwords in the config there), and then we look at which script is in the queue of the routers that were not transferred for this router.
This method does not solve the emerging problems, it helps to prevent them. That is, you must first “lay the straws” and hammer in the scheduler once every X minutes / hours the router checks for new scripts for it.
This method is also good when the router has a gray IP, and access to it must be obtained from outside. We hammer in the script for raising the VPN tunnel to our white IP address and after a specified time we have access to the device even for 10 NATs.
Here is such a short story. I will once comments and ideas what else can be screwed to such a service. The plans still have some statistics - so that the router merges a couple of its parameters into the database, for example, temperature, processor load, and others.
As a bonus, a piece of ready-made scripts, which I wrote about at the beginning, getting ip with the host name and adding it to the IPsec policy.
The plus is that it works in a bunch of Mikrotik + soap dishes that support ddns and ipsec (Dlink 804 for example). The script that extracts the IP address from the remote peer name of the remote peer and inserts it into the desired policy:
And the script that substitutes the current ip on the remote side in the ipsec policy:
There was an idea to make a center where the routers would report their addresses, and read the addresses of others. It was decided to go the path of least resistance - a site on the PHP.
At the moment, a couple of simple things have been implemented.
Announcement of your address
Implemented through a script request specifying your (router) name and password:
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/adr.php\?i=$number&p=$pass" mode=http
The name and password are needed so that no one can disguise as you and does not initiate the connection of your router to your own or cannot read the address of your router. Through the fetch utility, we open the desired script on the server and pass the name and password through GET. The script through $ _SERVER ['REMOTE_ADDR'] receives the external address of the router and writes it to the database.
Reading someone else's address
Again, through the same utility, we call the web script:
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/getadr.php\?i=$number&p=$pass" mode=http dst-path="adr.txt"
:global routeradr [/file get adr.txt contents]
dst-path = "adr.txt" - indicate that the received data is saved to a file. On the web page itself, we have a purely text with the address of the requested router:
$ query = "SELECT address FROM table_routers WHERE ((id = '$ _ GET [i]') AND (password = '$ _ GET [p]'))";
$ adr = mysql_query ($ query) or die (mysql_error ());
$ router = mysql_fetch_assoc ($ adr);
echo $ router [address];
: global routeradr [/ file get adr.txt contents] - assign the value of the file content to the global variable. Then this variable can be applied according to need and desire.
Reading a script from the database
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/getscript.php\?i=$number&p=$pass" mode=http dst-path="script.rsc"
import file-name=script.rsc
/file remove script.rsc
Everything is the same as in the previous script, but we import the file into the router config, and then delete this file.
Why is this necessary? For example, you inattentively cut off access to a router in a firewall. Then you can add a script for this router on the site with which you indicate the corrected firewall rules. Following the schedule, the router connects to the site, where the PHP looks to see if there are any untransmitted scripts in the database for this router:
SELECT id FROM table_routers WHERE ((id='$_GET[i]') AND (password='$_GET[p]'))
$adr=mysql_query($query) or die (mysql_error());
$router=mysql_fetch_assoc($adr);
$query="SELECT script, id FROM table_scripts WHERE ((router='$router[id]') AND (executed='N')) ORDER BY id ASC LIMIT 1";
First, we check whether the password and router number are set correctly (so that no one else can read your script, maybe you can change the passwords in the config there), and then we look at which script is in the queue of the routers that were not transferred for this router.
This method does not solve the emerging problems, it helps to prevent them. That is, you must first “lay the straws” and hammer in the scheduler once every X minutes / hours the router checks for new scripts for it.
This method is also good when the router has a gray IP, and access to it must be obtained from outside. We hammer in the script for raising the VPN tunnel to our white IP address and after a specified time we have access to the device even for 10 NATs.
Here is such a short story. I will once comments and ideas what else can be screwed to such a service. The plans still have some statistics - so that the router merges a couple of its parameters into the database, for example, temperature, processor load, and others.
As a bonus, a piece of ready-made scripts, which I wrote about at the beginning, getting ip with the host name and adding it to the IPsec policy.
The plus is that it works in a bunch of Mikrotik + soap dishes that support ddns and ipsec (Dlink 804 for example). The script that extracts the IP address from the remote peer name of the remote peer and inserts it into the desired policy:
:local nname RHost1;
:log info "start $nname";
:local newip [:resolve "rmotehost1.zapto.org"];
:local curip [/ip ipsec policy get [/ip ipsec policy find comment=$nname] sa-dst-address];
:log info "newip = $newip";
:log info "currentip = $curip";
:if ($newip != $curip) do={
:log info "ip $nname is $curip not $newip";
/ip ipsec policy set [/ip ipsec policy find comment=$nname] sa-dst-address=$newip;
:log info "end $nname";
}
And the script that substitutes the current ip on the remote side in the ipsec policy:
:global lastip
:local wanip
:local wanif "pppoe-out1"
:if ([ :typeof $lastip ] = nil ) do={ :global lastip "0" }
:local wanip [ /ip address get [/ip address find interface=$wanif ] address ]
:if ([ :typeof $wanip ] = nil ) do={
:log info ("WANIP: no ip address on $wanif .")
} else= {
:for i from=( [:len $wanip] - 1) to=0 do={
:if ( [:pick $wanip $i] = "/") do={
:set wanip [:pick $wanip 0 $i];
:log info ("wan ip now is $wanip")
}
}
:if ($wanip != $lastip) do={
:log info ("Renew ipsec Policy: $wanif -> $wanip")
#Подставляем в политику ipsec
/ip ipsec policy set 0 sa-src-address=$wanip
:global lastip $wanip
}
}