
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
