Att lastbalansera med MikroTik RouterOS7?

Hmm, ja … jag vet, MikroTik RouterOS är inte gjort för lastbalansering, men … visst kan man 🙂 … eller kanske inte lastbalansera men i alla fall lastdela mellan två enheter så att varannan ny anslutning går mot server 1 och varannan mot server 2.

Det är ingen hemlighet, jag har byggt två NTP-, eller tidsservrar om man så vill, jag har två så varför inte dessutom ha en automagisk redundans? Jag har dock bara en väg in för dem, det innebär att man måste kunna nå båda via samma publika IP-adress … och samma destinationsport dessutom, port 123/UDP.

Som steg 1 så är det inte så svårt att dela trafiken, om jag i brandväggen väljer fliken ”mangle” så kan jag ganska enkelt märka vartannat paket (Per Connection Classifier, PCC), baserat på källans IP-adress, och taggar paketet med ett namn. I mina NAT-inställningar för respektive NAT-regel, en regel för trafik mot NTP-1 och en regel mot NTP-2, så använder jag dessa taggar som villkor för att NAT skall genomföras. Och voila, den enklaste av enkla lastdelningar är skapad …

… men hur fasen skall man göra för att ta bort taggningen under mangle för NTP-2 när just NTP-2 inte längre fungerar?

In kommer NetWatch, ett litet behändigt verktyg som man lätt hittar under Tools i sin WinBox, verktyget för gui-baserat management av RouterOS.

I NetWatch kan välja några enkla modeller för att se om en tjänst eller service fungerar och baserat på om man får svar eller ej så kan man köra skript, detta var precis vad jag letade efter.

För att förstå skripten nedan gäller följande.

Mangle, märkning för trafik mot NTP-1, kommentar: ntp-srv1
Mangle, märkning för trafik mot NTP-2, kommentar: ntp-srv2

NAT mot NTP-1, kommentar: NTP -> .11
NAT mot NTP-2, kommentar: NTP -> .12

NetWatch, skript för NTP-1 uppe:

:local host "192.168.123.11";
:local natComment "NTP -> .11";
:local mangleComment "ntp_srv1";
:local tempComment "TEMP NTP redirect ntp_srv1->.12";

# wait to ensure host is stable
:delay 15s;
:local r [/ping $host count=3];
:if ($r = 0) do={
:log warning ("Netwatch: " . $host . " still unreachable after delay; aborting Up actions");
:return;
}

# remove temporary redirect if present
:local tmpIds [/ip firewall nat find comment~"$tempComment"];
:if ([:len $tmpIds] > 0) do={

/ip firewall nat remove $tmpIds;
:log info ("Netwatch: removed TEMP redirect (ids=" . $tmpIds . ")");
} else={
:log info ("Netwatch: no TEMP redirect found for removal");
}

# enable original NAT rule
:local natIds [/ip firewall nat find comment~"$natComment"];
:if ([:len $natIds] > 0) do={

/ip firewall nat enable $natIds;
:log info ("Netwatch: enabled NAT '" . $natComment . "' (ids=" . $natIds . ")");
} else={
:log warning ("Netwatch: no NAT rule found for comment '" . $natComment . "'");
}

# enable mangle rule so new connections can be marked to ntp_srv1
:local mIds [/ip firewall mangle find comment~"$mangleComment"];
:if ([:len $mIds] > 0) do={

/ip firewall mangle enable $mIds;
:log info ("Netwatch: enabled mangle '" . $mangleComment . "' (ids=" . $mIds . ")");
} else={
:log warning ("Netwatch: no mangle rule found for comment '" . $mangleComment . "'");
}
:log info ("Netwatch: " . $host . " UP — restoration complete");

NetWatch, skript för NTP-1 nere:

:local host "192.168.123.11";
:local natComment "NTP -> .11";
:local mangleComment "ntp_srv1";
:local tempComment "TEMP NTP redirect ntp_srv1->.12";

# short re-check to avoid transient flaps
:delay 5s;
:local r [/ping $host count=3];
:if ($r > 0) do={
  :log info ("Netwatch: " . $host . " responded during delay; aborting Down actions");
  :return;
}

# disable original NAT rule (if present)
:local natIds [/ip firewall nat find comment~"$natComment"];
:if ([:len $natIds] > 0) do={
  /ip firewall nat disable $natIds;
  :log warning ("Netwatch: disabled NAT '" . $natComment . "' (ids=" . $natIds . ")");
} else={
  :log warning ("Netwatch: no NAT rule found for comment '" . $natComment . "'");
}

# disable mangle rule so new connections are not marked to ntp_srv1
:local mIds [/ip firewall mangle find comment~"$mangleComment"];
:if ([:len $mIds] > 0) do={
  /ip firewall mangle disable $mIds;
  :log warning ("Netwatch: disabled mangle '" . $mangleComment . "' (ids=" . $mIds . ")");
} else={
  :log warning ("Netwatch: no mangle rule found for comment '" . $mangleComment . "'");
}

# add temporary redirect so existing connections with connection-mark=ntp_srv1 go to .12
:local tmpIds [/ip firewall nat find comment~"$tempComment"];
:if ([:len $tmpIds] = 0) do={
  /ip firewall nat add chain=dstnat protocol=udp dst-port=123 connection-mark=ntp_srv1 action=dst-nat to-addresses=192.168.123.12 to-ports=123 comment="$tempComment";
  :log warning ("Netwatch: added TEMP redirect for ntp_srv1 -> 192.168.123.12");
} else={
  :log info ("Netwatch: TEMP redirect already present (ids=" . $tmpIds . ")");
}

För NTP-2, uppe:

:local host "192.168.123.12";
:local natComment "NTP -> .12";
:local mangleComment "ntp_srv2";
:local tempComment "TEMP NTP redirect ntp_srv2->.11";

# wait to ensure host is stable
:delay 15s;
:local r [/ping $host count=3];
:if ($r = 0) do={
  :log warning ("Netwatch: " . $host . " still unreachable after delay; aborting Up actions");
  :return;
}

# remove temporary redirect if present
:local tmpIds [/ip firewall nat find comment~"$tempComment"];
:if ([:len $tmpIds] > 0) do={
  /ip firewall nat remove $tmpIds;
  :log info ("Netwatch: removed TEMP redirect (ids=" . $tmpIds . ")");
} else={
  :log info ("Netwatch: no TEMP redirect found for removal");
}

# enable original NAT rule
:local natIds [/ip firewall nat find comment~"$natComment"];
:if ([:len $natIds] > 0) do={
  /ip firewall nat enable $natIds;
  :log info ("Netwatch: enabled NAT '" . $natComment . "' (ids=" . $natIds . ")");
} else={
  :log warning ("Netwatch: no NAT rule found for comment '" . $natComment . "'");
}

# enable mangle rule so new connections can be marked to ntp_srv2
:local mIds [/ip firewall mangle find comment~"$mangleComment"];
:if ([:len $mIds] > 0) do={
  /ip firewall mangle enable $mIds;
  :log info ("Netwatch: enabled mangle '" . $mangleComment . "' (ids=" . $mIds . ")");
} else={
  :log warning ("Netwatch: no mangle rule found for comment '" . $mangleComment . "'");
}

:log info ("Netwatch: " . $host . " UP — restoration complete");

… och slutligen för NTP-2, nere:

:local host "192.168.123.12";
:local natComment "NTP -> .12";
:local mangleComment "ntp_srv2";
:local tempComment "TEMP NTP redirect ntp_srv2->.11";

# brief re-check to avoid transient flaps
:delay 5s;
:local r [/ping $host count=3];
:if ($r > 0) do={
  :log info ("Netwatch: " . $host . " responded during delay; aborting Down actions");
  :return;
}

# disable original NAT rule (if present)
:local natIds [/ip firewall nat find comment~"$natComment"];
:if ([:len $natIds] > 0) do={
  /ip firewall nat disable $natIds;
  :log warning ("Netwatch: disabled NAT '" . $natComment . "' (ids=" . $natIds . ")");
} else={
  :log warning ("Netwatch: no NAT rule found for comment '" . $natComment . "'");
}

# disable mangle rule so new connections are not marked to ntp_srv2
:local mIds [/ip firewall mangle find comment~"$mangleComment"];
:if ([:len $mIds] > 0) do={
  /ip firewall mangle disable $mIds;
  :log warning ("Netwatch: disabled mangle '" . $mangleComment . "' (ids=" . $mIds . ")");
} else={
  :log warning ("Netwatch: no mangle rule found for comment '" . $mangleComment . "'");
}

# add temporary redirect so existing connections with connection-mark=ntp_srv2 go to .11
:local tmpIds [/ip firewall nat find comment~"$tempComment"];
:if ([:len $tmpIds] = 0) do={
  /ip firewall nat add chain=dstnat protocol=udp dst-port=123 connection-mark=ntp_srv2 action=dst-nat to-addresses=192.168.123.11 to-ports=123 comment="$tempComment";
  :log warning ("Netwatch: added TEMP redirect for ntp_srv2 -> 192.168.123.11");
} else={
  :log info ("Netwatch: TEMP redirect already present (ids=" . $tmpIds . ")");
}

Detta fungerar jättebra om den ena servern verkligen är uppe eller helt nere, jag fortsätter leta efter möjligheter att kolla efter svar på IP-port 123/UDP men än så länge har jag inte hittar hur …

Ha det gott,
Anders

Nordh Tech
Privacy Overview

GDPR och kakor (cookies)

Den 25 maj 2018 började dataskyddsförordningen (GDPR) att gälla i Sverige och övriga EU.

Det innebär bland annat att inget företag eller organisation får spara personuppgifter som inte behövs för att leverera det du bett om och att du har rätt att ”bli glömd” så snart du ber om det.

För din kontakt med Nordh.Tech innebär det inte så mycket.

Vi sparar en kaka (cookie) vilket innebär en liten textfil med information om vad du gjort när du surfar hos oss, vi gör det för att kunna få statistik rörande vad du gjort när du besöker oss och för att vi skall kunna ge dig nytt innehåll och inte till exempel behöva fråga dig var gång du besöker oss om du godkänner våra GDPR-villkor eller att det sparas en ”kaka” på din dator.

Vi sparar också din epostadress för att kunna skicka dig vårt nyhetsbrev eller hantera din inloggning i vårt forum, om du bett om det vill säga. Då du prenumererar på nyhetsbrevet eller begär inloggning till vårt forum anger du också ditt förnamn eller inloggningsnamn men här kan du ange vilket namn som helst. Vissa anger även efternamn men dessa raderas så att endast förnamnet kommer att användas i hälsningsfrasen i varje nyhetsbrev.

Hoppas detta gör att du kan känna dig trygg med ditt besök hos mig här på Internet.