Determine External IP Address With RouterOS


I regularly wanted to log my external IP address to my syslog server. Since my router (MikroTik RB2011UAS-2HnD-IN) lives behind a NAT firewall, I needed a way to determine the external IP address on my RouterOS device.

My setup looks like this: Client ↔ Switch ↔ Router ↔ Cable Modem ↔ Internet

Solution

I started from the forum post “Find External IP” in the MikroTik forum, replaced the remote server part with my own PHP script running on my root server on the internet and schedule the script every 30 minutes.

PHP-Part

The PHP script is pretty simple and straight forward. It just prints the variable REMOTE_ADDR to the client and logs the remote address to a local file.

<?php
header("Content-Type: text/html");
header("Expires: Tue, 16 Nov 2013 08:00:00 GMT");
header("Last-Modified: " . gmdate('D, d M Y H:i:s') . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

$r_ip = $_SERVER['REMOTE_ADDR'];

if (isset($_GET['who']))
  {
    $r_who = $_GET['who'];
    $r_who = preg_replace("/[^a-zA-Z0-9]+/", "", $r_who);
  }
else
  { $r_who = '-'; }

print "$r_ip";

$filename = '<<PATH_TO_LOCAL_FILE>>/publicip.txt';
$fh = fopen($filename, 'a') or exit("ERROR: Can not open file $filename.\n");
fwrite($fh, sprintf('[%s] %s %s%s', date('Y-m-d H:i:s'), $r_ip, $r_who, "\n"));
fclose($fh);
?>

RouterOS Script

The script on the router can query the above PHP script and determine it’s external, probably masqueraded, IP address.

The address is written to a local file “mypublicip.txt” which is overwritten at each run. The gathered address is then written to the system log on level info and set to the address-list named “external-ip” which could e.g. be used in firewall rules.

# Set needed variables
:global ExtIpListName "external-ip"
:global ExtIp ""
:global ExtIpOld ""

# Get IP and save it to "mypublicip.txt"
/tool fetch url="http://<<YOU_SERVER_NAME.COM>>/mypublicip.php?who=<<SOURCE_LABEL>>" mode=http dst-path=mypublicip.txt
# Save IP from "mypublicip.txt" to variable
:global ExtIp [file get mypublicip.txt contents]

:if ([:len [/ip firewall address-list find list="$ExtIpListName"]] > 0) do={
 :set ExtIpOld [/ip firewall address-list get [/ip firewall address-list find list="$ExtIpListName"] address];
 :if ($ExtIpOld != $ExtIp) do={
 /ip firewall address-list set [/ip firewall address-list find list="$ExtIpListName" address="$ExtIpOld"] address="$ExtIp"
 :log info "External IP relpaced from $ExtIpOld to $ExtIp."
 } else={
 :log info "External IP $ExtIp not changed."
 };
} else={
 /ip firewall address-list add list="$ExtIpListName" address="$ExtIp" comment="script generated"
 :log info "New external IP $ExtIp added."
};