OPNsense HA Umsetzung: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| (2 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
| + | =Plan= | ||
| + | {{#drawio:ha-opnsense-kit}} | ||
| + | == Platzhalter in diesem Artikel == | ||
| + | {| class="wikitable" | ||
| + | ! Platzhalter !! Bedeutung !! Beispiel | ||
| + | |- | ||
| + | | '''HS''' || Drittes Oktett des Schulungsnetzes (WAN), wird vom Trainer vorgegeben || 4 | ||
| + | |- | ||
| + | | '''X''' || Deine Teilnehmernummer, wird vom Trainer vorgegeben || 13 | ||
| + | |} | ||
| + | |||
| + | * Beispiel für X=13 und HS=4: WAN Master 192.168.4.53, WAN Backup 192.168.4.73, WAN-VIP 192.168.4.33, VHID 13 | ||
| + | * '''Alle Passwörter in diesem Artikel sind Laborwerte und dürfen so niemals in eine produktive Umgebung übernommen werden.''' | ||
| − | |||
| − | |||
=Wichtig= | =Wichtig= | ||
| − | * | + | * Die Netzwerkkarten für LAN und WAN müssen '''im Hypervisor''' in den Promiscuous-Modus geschaltet werden – nicht in OPNsense. |
| − | * | + | ** VirtualBox: Maschine => Ändern => Netzwerk => Adapter => Erweitert => Promiscuous-Modus: '''Alle erlauben''' |
| + | ** Proxmox: Bridge ohne MAC-Filter bzw. entsprechende Bridge-Einstellung | ||
| + | * Das gilt sowohl für den Master als auch für das Backup. | ||
;Begründung | ;Begründung | ||
| − | *CARP verwendet virtuelle MAC-Adressen für die gemeinsame VIP. In virtualisierten Umgebungen werden Frames mit diesen MAC-Adressen vom Hypervisor standardmäßig verworfen, da sie nicht der echten VM-NIC zugeordnet sind. Ohne aktivierten Promiscuous-Modus erreichen CARP-Advertisements den Partner nicht, was zu Fehldetektion, unerwünschtem Failover und HA-Inkonsistenzen führt. | + | * CARP verwendet virtuelle MAC-Adressen für die gemeinsame VIP. In virtualisierten Umgebungen werden Frames mit diesen MAC-Adressen vom Hypervisor standardmäßig verworfen, da sie nicht der echten VM-NIC zugeordnet sind. Ohne aktivierten Promiscuous-Modus erreichen CARP-Advertisements den Partner nicht, was zu Fehldetektion, unerwünschtem Failover und HA-Inkonsistenzen führt. |
= Vorbereitung = | = Vorbereitung = | ||
* Zwei OPNsense-Installationen mit jeweils mind. 3 Netzwerkkarten | * Zwei OPNsense-Installationen mit jeweils mind. 3 Netzwerkkarten | ||
| + | * Auf beiden Maschinen muss die '''gleiche OPNsense-Version''' laufen | ||
* Die Anzahl der Netzwerkkarten muss auf beiden Maschinen gleich sein | * Die Anzahl der Netzwerkkarten muss auf beiden Maschinen gleich sein | ||
| − | + | * '''Die Reihenfolge und Anzahl der Netzwerkschnittstellen muss auf beiden Maschinen identisch sein!''' | |
* Empfehlung für beide Maschinen: | * Empfehlung für beide Maschinen: | ||
| − | ** LAN | + | ** em0: LAN |
| − | ** WAN | + | ** em1: WAN |
| − | ** SYN | + | ** em2: SYN |
| − | + | * Am Anfang sollten so wenige Dienste wie möglich laufen | |
| − | * Am Anfang sollten so wenige | ||
| − | == IP Adressen der Master Firewall == | + | == IP-Adressen der Master Firewall == |
* em0 (LAN): 192.168.1.1/24 | * em0 (LAN): 192.168.1.1/24 | ||
* em1 (WAN): 192.168.HS.X+40/24 | * em1 (WAN): 192.168.HS.X+40/24 | ||
* em2 (SYN): 100.64.64.1/30 | * em2 (SYN): 100.64.64.1/30 | ||
| − | == IP Adressen der Backup Firewall == | + | == IP-Adressen der Backup Firewall == |
| − | |||
* em0 (LAN): 192.168.1.2/24 | * em0 (LAN): 192.168.1.2/24 | ||
* em1 (WAN): 192.168.HS.X+60/24 | * em1 (WAN): 192.168.HS.X+60/24 | ||
* em2 (SYN): 100.64.64.2/30 | * em2 (SYN): 100.64.64.2/30 | ||
| + | |||
| + | == Übersicht == | ||
| + | {| class="wikitable" | ||
| + | ! !! Master (opns-ha1) !! Backup (opns-ha2) !! VIP !! VHID | ||
| + | |- | ||
| + | | LAN (em0) || 192.168.1.1 || 192.168.1.2 || 192.168.1.3 || 100 | ||
| + | |- | ||
| + | | WAN (em1) || 192.168.HS.X+40 || 192.168.HS.X+60 || 192.168.HS.X+20 || X | ||
| + | |- | ||
| + | | SYN (em2) || 100.64.64.1 || 100.64.64.2 || – || – | ||
| + | |} | ||
| + | |||
| + | * Die VHID muss nur innerhalb einer Broadcast-Domäne eindeutig sein, der Wertebereich ist 1 bis 255. | ||
| + | * Da sich alle Teilnehmer das WAN-Segment teilen, wird dort die Teilnehmernummer X verwendet (1 bis 13). | ||
| + | * Das LAN ist pro Teilnehmer ein eigenes, isoliertes Segment. Dort steht deshalb bei allen Teilnehmern fest die 100. Der Abstand zum WAN-Bereich ist Absicht: dreistellig = LAN, zweistellig = WAN. | ||
= Firewall Regeln (beide Firewalls) = | = Firewall Regeln (beide Firewalls) = | ||
| − | |||
* Auf allen Schnittstellen '''außer''' dem SYN-Interface muss das Protokoll CARP akzeptiert werden | * Auf allen Schnittstellen '''außer''' dem SYN-Interface muss das Protokoll CARP akzeptiert werden | ||
| − | * Dazu muss im Menü '''Firewall => Rules => {WAN, LAN}''' Allow- | + | * Dazu muss im Menü '''Firewall => Rules => {WAN, LAN}''' je eine Allow-Regel erstellt werden, die auf das CARP-Protokoll matcht |
* Für das SYN-Interface kann man eine Standard-Allow-Regel erstellen, die alles erlaubt | * Für das SYN-Interface kann man eine Standard-Allow-Regel erstellen, die alles erlaubt | ||
= Virtuelle IPs (Master Firewall) = | = Virtuelle IPs (Master Firewall) = | ||
| − | |||
* Die virtuellen IPs werden von den Knoten des HA-Clusters geteilt, sobald ein Ausfall erkannt wird | * Die virtuellen IPs werden von den Knoten des HA-Clusters geteilt, sobald ein Ausfall erkannt wird | ||
* Somit wird dafür gesorgt, dass die virtuelle IP immer erreichbar ist | * Somit wird dafür gesorgt, dass die virtuelle IP immer erreichbar ist | ||
* Die virtuelle IP wird '''nur''' auf der Master Firewall eingestellt und an die Backups mitgeteilt | * Die virtuelle IP wird '''nur''' auf der Master Firewall eingestellt und an die Backups mitgeteilt | ||
| − | * Dazu muss man im Menü '''Interfaces => Virtual IPs => Settings''' | + | * Dazu muss man im Menü '''Interfaces => Virtual IPs => Settings''' an allen Schnittstellen bis auf das SYN-Interface die gewünschten IPs vergeben |
* Über das '''[+]''' auf der rechten Seite muss man folgende Einträge machen: | * Über das '''[+]''' auf der rechten Seite muss man folgende Einträge machen: | ||
| Zeile 54: | Zeile 79: | ||
| Interface || WAN | | Interface || WAN | ||
|- | |- | ||
| − | | Address || 192.168. | + | | Address || 192.168.HS.X+20/24 |
|- | |- | ||
| Virtual Password || radler | | Virtual Password || radler | ||
| Zeile 77: | Zeile 102: | ||
| Virtual Password || radler | | Virtual Password || radler | ||
|- | |- | ||
| − | | VHID Group || | + | | VHID Group || 100 |
|- | |- | ||
| Advertising Frequency || 1 | | Advertising Frequency || 1 | ||
| Zeile 85: | Zeile 110: | ||
= Source NAT (Master Firewall) = | = Source NAT (Master Firewall) = | ||
| − | + | * Da die virtuelle IP für ausgehende Verbindungen benutzt werden soll, muss die automatische Regelgenerierung ausgeschaltet werden | |
| − | * Da die virtuelle IP für ausgehende Verbindungen benutzt werden soll, muss die automatische | + | * Im Menü '''Firewall => NAT => Outbound''' muss die Option "Manual outbound NAT rule generation" ausgewählt werden |
| − | * Im Menü '''Firewall => NAT => Outbound''' muss die Option "Manual outbound NAT rule | + | * Dann die folgende Regel erstellen: |
| − | * Dann die | ||
** Interface: WAN | ** Interface: WAN | ||
** Source address: LAN net | ** Source address: LAN net | ||
| − | ** Translation / target: 192.168.HS.20 | + | ** Translation / target: '''Virtual WAN IP (192.168.HS.X+20)''' aus der Auswahlliste |
| + | ;Achtung | ||
| + | * Als Ziel muss der VIP-Eintrag aus der Auswahlliste gewählt werden, nicht das Netz 192.168.HS.0/24. Trägt man ein ganzes Netz ein, baut OPNsense daraus einen NAT-Pool. | ||
= High Availability Konfiguration (Master Firewall) = | = High Availability Konfiguration (Master Firewall) = | ||
| − | + | * Die eigentliche HA-Einstellung erfolgt über das Menü '''System => High Availability => Settings''': | |
| − | * Die eigentliche HA Einstellung erfolgt über das Menü '''System => High Availability => Settings''': | ||
{| class="wikitable" | {| class="wikitable" | ||
! Parameter !! Wert | ! Parameter !! Wert | ||
| Zeile 115: | Zeile 140: | ||
| Services || Aliases, Firewall Rules, NAT, Virtual IPs | | Services || Aliases, Firewall Rules, NAT, Virtual IPs | ||
|} | |} | ||
| + | |||
| + | * "Verify peer" bleibt deaktiviert, weil die Web-GUI der Gegenstelle ein selbstsigniertes Zertifikat verwendet. | ||
= High Availability Konfiguration (Backup Firewall) = | = High Availability Konfiguration (Backup Firewall) = | ||
| − | |||
* Hier darf im Menü '''System => High Availability => Settings''' nur folgendes eingestellt werden: | * Hier darf im Menü '''System => High Availability => Settings''' nur folgendes eingestellt werden: | ||
{| class="wikitable" | {| class="wikitable" | ||
| Zeile 138: | Zeile 164: | ||
| Services || Nothing selected | | Services || Nothing selected | ||
|} | |} | ||
| + | |||
| + | * '''Synchronize Config''' muss auf dem Backup leer bleiben. Trägt man hier den Master ein, schieben sich beide Knoten gegenseitig ihre Konfiguration zu. | ||
| + | |||
| + | = Client im LAN = | ||
| + | * Der Windows-Client (192.168.1.50) muss als '''Gateway''' und als '''DNS-Server''' die LAN-VIP '''192.168.1.3''' erhalten – nicht die 192.168.1.1 | ||
| + | * Wird die echte IP des Masters eingetragen, ist der Client beim Ausfall des Masters trotz funktionierendem Cluster offline | ||
| + | * Bei Verwendung eines DHCP-Servers muss dieser die VIP als Gateway und DNS verteilen | ||
= Endergebnis = | = Endergebnis = | ||
==Master== | ==Master== | ||
| − | *System | + | * System |
| − | **High Availability | + | ** High Availability |
| − | ***Status | + | *** Status |
| + | * Hier müssen beide Spalten gefüllt sein und auf beiden Knoten die gleichen Dienste erscheinen: | ||
{| class="wikitable" | {| class="wikitable" | ||
| Zeile 174: | Zeile 208: | ||
==Slave== | ==Slave== | ||
| − | *System | + | * System |
| − | **High Availability | + | ** High Availability |
| − | ***Status | + | *** Status |
| − | + | * Auf der Backup-Firewall erscheint hier die Warnung, dass die XMLRPC-Konfiguration unvollständig sei. | |
| + | * Diese Meldung kann ignoriert werden: Das Backup empfängt nur passiv, deshalb sind die XMLRPC-Felder dort absichtlich leer und werden fälschlicherweise als "unvollständig" markiert. Solange die Master-Firewall auf Version 24.7 eingestellt ist und die Daten erfolgreich überträgt, arbeitet der Cluster technisch einwandfrei. | ||
| + | |||
| + | = Failover testen = | ||
| + | * Auf dem Client einen Dauerping nach draußen starten: | ||
| + | ping -t 192.168.HS.254 | ||
| + | * Auf dem '''Master''': System => High Availability => Status => '''Enter persistent CARP maintenance mode''' | ||
| + | * Erwartetes Verhalten: | ||
| + | ** Das Backup wechselt für beide VHIDs von BACKUP auf MASTER | ||
| + | ** Der Ping läuft weiter oder verliert maximal ein bis zwei Pakete | ||
| + | * Kontrolle auf beiden Knoten: | ||
| + | ifconfig em0 ; ifconfig em1 | ||
| + | * Zurückschalten über '''Leave persistent CARP maintenance mode''' auf dem Master | ||
| + | * Zweiter Test: Master hart ausschalten (VM stoppen) und das gleiche Verhalten prüfen | ||
| + | |||
=Debugging= | =Debugging= | ||
| − | == | + | |
| − | * | + | == Vorgehen == |
| − | * | + | * Von unten nach oben prüfen: erst CARP (Layer 2/3), dann pfsync (States), dann XMLRPC (Konfiguration) |
| − | ** | + | * Ein Cluster kann sauber synchronisieren und trotzdem kein Failover können – und umgekehrt |
| − | **** | + | |
| − | * | + | == Schritt 1: CARP-Status == |
| − | + | * Auf beiden Knoten: | |
| + | ifconfig em0 ; ifconfig em1 | ||
| + | * Erwartetes Bild: | ||
| + | {| class="wikitable" | ||
| + | ! Knoten !! LAN (vhid 100) !! WAN (vhid X) | ||
| + | |- | ||
| + | | Master || MASTER, advskew 0 || MASTER, advskew 0 | ||
| + | |- | ||
| + | | Backup || BACKUP, advskew 100 || BACKUP, advskew 100 | ||
| + | |} | ||
| + | * In der GUI: '''Interfaces => Virtual IPs => Status''' | ||
| + | * CARP global ein-/ausgeschaltet: | ||
| + | sysctl net.inet.carp.allow | ||
| + | * Ausführlichere CARP-Meldungen im Log einschalten: | ||
| + | sysctl net.inet.carp.log=2 | ||
| + | |||
| + | == Schritt 2: Beide Knoten sind MASTER (Split Brain) == | ||
| + | * Das häufigste Fehlerbild im Labor. Beide Knoten sehen den Partner nicht und übernehmen die VIP. | ||
| + | * Prüfen, ob die Advertisements des Partners überhaupt ankommen: | ||
| + | tcpdump -n -i em1 proto 112 | ||
| + | tcpdump -n -i em0 proto 112 | ||
| + | * Man muss die Pakete '''beider''' Knoten sehen (Quelle = jeweils die echte Interface-IP) | ||
| + | {| class="wikitable" | ||
| + | ! Beobachtung !! Ursache | ||
| + | |- | ||
| + | | Nur eigene Pakete sichtbar || Promiscuous-Modus im Hypervisor fehlt | ||
| + | |- | ||
| + | | Gar keine Pakete sichtbar || VIP nicht angelegt oder Interface down | ||
| + | |- | ||
| + | | Pakete kommen an, trotzdem beide MASTER || CARP-Allow-Regel auf dem Interface fehlt | ||
| + | |- | ||
| + | | Pakete mit fremder VHID || Anderer Teilnehmer nutzt die gleiche VHID | ||
| + | |} | ||
| + | * Weitere Ursachen bei Split Brain: | ||
| + | ** Unterschiedliches '''Virtual Password''' auf den beiden Knoten | ||
| + | ** Unterschiedliche '''VHID''' auf den beiden Knoten | ||
| + | ** Unterschiedliche '''Advertising Frequency''' | ||
| + | |||
| + | == Schritt 3: Kein Failover trotz korrektem Status == | ||
| + | * Demotion-Zähler prüfen – ist er größer als 0, bleibt der Knoten absichtlich BACKUP: | ||
| + | sysctl net.inet.carp.demotion | ||
| + | * Ursachen für einen erhöhten Zähler: ein Interface ist down, ein Dienst startet nicht sauber, der Knoten befindet sich noch im Maintenance Mode | ||
| + | * Maintenance Mode verlassen: '''System => High Availability => Status => Leave persistent CARP maintenance mode''' | ||
| + | |||
| + | == Schritt 4: Sicht des Clients == | ||
| + | * Auf dem Windows-Client prüfen, welche MAC hinter dem Gateway steckt: | ||
| + | arp -a | ||
| + | * Die LAN-VIP muss auf eine virtuelle MAC zeigen, nicht auf die echte NIC des Masters: | ||
| + | 192.168.1.3 00-00-5e-00-01-64 | ||
| + | * Das letzte Byte ist die VHID in hex – 0x64 = 100 | ||
| + | * Steht dort eine 08:00:27:... Adresse, arbeitet der Client an CARP vorbei direkt mit einer echten Firewall-IP | ||
| + | * Nach einem Failover darf sich der ARP-Eintrag '''nicht''' ändern – genau das ist der Sinn der virtuellen MAC | ||
| + | |||
| + | == Schritt 5: Zustandssynchronisation (pfsync) == | ||
| + | * Läuft der pfsync-Verkehr über das SYN-Netz? | ||
| + | tcpdump -n -i em2 proto 240 | ||
| + | * Anzahl der States auf beiden Knoten vergleichen – die Werte müssen ähnlich sein: | ||
| + | pfctl -s state | wc -l | ||
| + | * Ist die Zahl auf dem Backup dauerhaft 0, überträgt pfsync nicht: | ||
| + | ** '''Synchronize Peer IP''' zeigt auf die falsche Adresse | ||
| + | ** Die Allow-Regel auf dem SYN-Interface fehlt | ||
| + | ** SYN-Interface auf einem der Knoten nicht aktiviert | ||
| + | |||
| + | == Schritt 6: Konfigurationssynchronisation (XMLRPC) == | ||
| + | * Auf der Master-Firewall: '''System => Log Files => General''', im Filter-Feld '''xmlrpc''' eingeben | ||
| + | * Gesucht wird ein Eintrag wie: '''[OK] Configuration synchronized to''' https://100.64.64.2:443 | ||
| + | * Manuell anstoßen: '''System => High Availability => Status => Synchronize and reconfigure all (Push)''' | ||
| + | * Gleichzeitig auf dem Backup mitlesen: | ||
| + | tail -f /var/log/configd/latest.log | ||
| + | {| class="wikitable" | ||
| + | ! Meldung !! Ursache | ||
| + | |- | ||
| + | | Connection refused || Web-GUI des Backups nicht erreichbar oder falscher Port | ||
| + | |- | ||
| + | | Authentication failed || Falsches Passwort unter "Remote System Password" | ||
| + | |- | ||
| + | | Certificate verify failed || "Verify peer" ist aktiviert, Zertifikat ist selbstsigniert | ||
| + | |- | ||
| + | | Endlose Sync-Schleife || Auf dem Backup ist "Synchronize Config" gefüllt – muss leer sein | ||
| + | |} | ||
| + | |||
| + | == Schritt 7: Ausgehende Verbindungen == | ||
| + | * Prüfen, mit welcher Quelladresse der Client nach draußen geht: | ||
| + | tcpdump -n -i em1 host 192.168.HS.254 | ||
| + | * Es muss die Virtual WAN IP (192.168.HS.X+20) erscheinen, nicht die echte IP des Masters | ||
| + | * Erscheint die echte IP: Outbound-NAT steht noch auf automatisch, oder in der manuellen Regel wurde als Target nicht die VIP gewählt | ||
| + | |||
| + | == Nützliche Befehle im Überblick == | ||
| + | {| class="wikitable" | ||
| + | ! Befehl !! Zweck | ||
| + | |- | ||
| + | | ifconfig em0 ; ifconfig em1 || CARP-Rolle und VIPs anzeigen | ||
| + | |- | ||
| + | | tcpdump -n -i em1 proto 112 || CARP-Advertisements mitlesen | ||
| + | |- | ||
| + | | tcpdump -n -i em2 proto 240 || pfsync-Verkehr mitlesen | ||
| + | |- | ||
| + | | pfctl -s state {{!}} wc -l || Anzahl der Firewall-States | ||
| + | |- | ||
| + | | sysctl net.inet.carp.demotion || Demotion-Zähler | ||
| + | |- | ||
| + | | sysctl net.inet.carp.log=2 || Ausführliches CARP-Logging | ||
| + | |- | ||
| + | | tail -f /var/log/configd/latest.log || Konfigurationssync mitlesen | ||
| + | |- | ||
| + | | configctl filter reload || Regelwerk neu laden | ||
| + | |} | ||
| + | |||
==Netzwerkschnittstellen== | ==Netzwerkschnittstellen== | ||
| − | === | + | === Master === |
| − | |||
em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 | em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 | ||
description: LAN (lan) | description: LAN (lan) | ||
| Zeile 194: | Zeile 348: | ||
ether 08:00:27:c4:a2:6f | ether 08:00:27:c4:a2:6f | ||
inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255 | inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255 | ||
| − | '''inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid | + | '''inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid 100''' |
| − | '''carp: MASTER vhid | + | '''carp: MASTER vhid 100 advbase 1 advskew 0''' |
'''peer 224.0.0.18 peer6 ff02::12''' | '''peer 224.0.0.18 peer6 ff02::12''' | ||
media: Ethernet autoselect (1000baseT <full-duplex>) | media: Ethernet autoselect (1000baseT <full-duplex>) | ||
| Zeile 206: | Zeile 360: | ||
ether 08:00:27:61:6f:6d | ether 08:00:27:61:6f:6d | ||
inet 192.168.HS.X+40 netmask 0xffffff00 broadcast 192.168.HS.255 | inet 192.168.HS.X+40 netmask 0xffffff00 broadcast 192.168.HS.255 | ||
| − | '''inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X | + | '''inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X''' |
'''carp: MASTER vhid X advbase 1 advskew 0''' | '''carp: MASTER vhid X advbase 1 advskew 0''' | ||
'''peer 224.0.0.18 peer6 ff02::12''' | '''peer 224.0.0.18 peer6 ff02::12''' | ||
| Zeile 212: | Zeile 366: | ||
status: active | status: active | ||
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> | nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> | ||
| − | + | ||
| − | em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 | + | === Backup === |
| + | em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 | ||
description: LAN (lan) | description: LAN (lan) | ||
options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> | options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> | ||
ether 08:00:27:1c:44:8b | ether 08:00:27:1c:44:8b | ||
inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255 | inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255 | ||
| − | '''inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid | + | '''inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid 100''' |
| − | '''carp: BACKUP vhid | + | '''carp: BACKUP vhid 100 advbase 1 advskew 100''' |
'''peer 224.0.0.18 peer6 ff02::12''' | '''peer 224.0.0.18 peer6 ff02::12''' | ||
media: Ethernet autoselect (1000baseT <full-duplex>) | media: Ethernet autoselect (1000baseT <full-duplex>) | ||
| Zeile 230: | Zeile 385: | ||
ether 08:00:27:95:9b:4b | ether 08:00:27:95:9b:4b | ||
inet 192.168.HS.X+60 netmask 0xffffff00 broadcast 192.168.HS.255 | inet 192.168.HS.X+60 netmask 0xffffff00 broadcast 192.168.HS.255 | ||
| − | '''inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X | + | '''inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X''' |
'''carp: BACKUP vhid X advbase 1 advskew 100''' | '''carp: BACKUP vhid X advbase 1 advskew 100''' | ||
'''peer 224.0.0.18 peer6 ff02::12''' | '''peer 224.0.0.18 peer6 ff02::12''' | ||
| Zeile 236: | Zeile 391: | ||
status: active | status: active | ||
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> | nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> | ||
| + | |||
| + | * Der Master hat '''advskew 0''', das Backup '''advskew 100'''. Diesen Wert setzt OPNsense beim Sync automatisch – er wird nicht von Hand vergeben. | ||
==Wird Synchronisiert?== | ==Wird Synchronisiert?== | ||
;Master | ;Master | ||
| − | *System | + | * System |
| − | **High Availability | + | ** High Availability |
| − | ***Status | + | *** Status |
| − | ****Synchronize and reconfigure all (Push) | + | **** Synchronize and reconfigure all (Push) |
;Backup | ;Backup | ||
| − | + | tail -f /var/log/configd/latest.log | |
| − | Hier | + | * Hier sollte man die Übertragung sehen. |
Aktuelle Version vom 20. August 2026, 19:12 Uhr
Plan
Platzhalter in diesem Artikel
| Platzhalter | Bedeutung | Beispiel |
|---|---|---|
| HS | Drittes Oktett des Schulungsnetzes (WAN), wird vom Trainer vorgegeben | 4 |
| X | Deine Teilnehmernummer, wird vom Trainer vorgegeben | 13 |
- Beispiel für X=13 und HS=4: WAN Master 192.168.4.53, WAN Backup 192.168.4.73, WAN-VIP 192.168.4.33, VHID 13
- Alle Passwörter in diesem Artikel sind Laborwerte und dürfen so niemals in eine produktive Umgebung übernommen werden.
Wichtig
- Die Netzwerkkarten für LAN und WAN müssen im Hypervisor in den Promiscuous-Modus geschaltet werden – nicht in OPNsense.
- VirtualBox: Maschine => Ändern => Netzwerk => Adapter => Erweitert => Promiscuous-Modus: Alle erlauben
- Proxmox: Bridge ohne MAC-Filter bzw. entsprechende Bridge-Einstellung
- Das gilt sowohl für den Master als auch für das Backup.
- Begründung
- CARP verwendet virtuelle MAC-Adressen für die gemeinsame VIP. In virtualisierten Umgebungen werden Frames mit diesen MAC-Adressen vom Hypervisor standardmäßig verworfen, da sie nicht der echten VM-NIC zugeordnet sind. Ohne aktivierten Promiscuous-Modus erreichen CARP-Advertisements den Partner nicht, was zu Fehldetektion, unerwünschtem Failover und HA-Inkonsistenzen führt.
Vorbereitung
- Zwei OPNsense-Installationen mit jeweils mind. 3 Netzwerkkarten
- Auf beiden Maschinen muss die gleiche OPNsense-Version laufen
- Die Anzahl der Netzwerkkarten muss auf beiden Maschinen gleich sein
- Die Reihenfolge und Anzahl der Netzwerkschnittstellen muss auf beiden Maschinen identisch sein!
- Empfehlung für beide Maschinen:
- em0: LAN
- em1: WAN
- em2: SYN
- Am Anfang sollten so wenige Dienste wie möglich laufen
IP-Adressen der Master Firewall
- em0 (LAN): 192.168.1.1/24
- em1 (WAN): 192.168.HS.X+40/24
- em2 (SYN): 100.64.64.1/30
IP-Adressen der Backup Firewall
- em0 (LAN): 192.168.1.2/24
- em1 (WAN): 192.168.HS.X+60/24
- em2 (SYN): 100.64.64.2/30
Übersicht
| Master (opns-ha1) | Backup (opns-ha2) | VIP | VHID | |
|---|---|---|---|---|
| LAN (em0) | 192.168.1.1 | 192.168.1.2 | 192.168.1.3 | 100 |
| WAN (em1) | 192.168.HS.X+40 | 192.168.HS.X+60 | 192.168.HS.X+20 | X |
| SYN (em2) | 100.64.64.1 | 100.64.64.2 | – | – |
- Die VHID muss nur innerhalb einer Broadcast-Domäne eindeutig sein, der Wertebereich ist 1 bis 255.
- Da sich alle Teilnehmer das WAN-Segment teilen, wird dort die Teilnehmernummer X verwendet (1 bis 13).
- Das LAN ist pro Teilnehmer ein eigenes, isoliertes Segment. Dort steht deshalb bei allen Teilnehmern fest die 100. Der Abstand zum WAN-Bereich ist Absicht: dreistellig = LAN, zweistellig = WAN.
Firewall Regeln (beide Firewalls)
- Auf allen Schnittstellen außer dem SYN-Interface muss das Protokoll CARP akzeptiert werden
- Dazu muss im Menü Firewall => Rules => {WAN, LAN} je eine Allow-Regel erstellt werden, die auf das CARP-Protokoll matcht
- Für das SYN-Interface kann man eine Standard-Allow-Regel erstellen, die alles erlaubt
Virtuelle IPs (Master Firewall)
- Die virtuellen IPs werden von den Knoten des HA-Clusters geteilt, sobald ein Ausfall erkannt wird
- Somit wird dafür gesorgt, dass die virtuelle IP immer erreichbar ist
- Die virtuelle IP wird nur auf der Master Firewall eingestellt und an die Backups mitgeteilt
- Dazu muss man im Menü Interfaces => Virtual IPs => Settings an allen Schnittstellen bis auf das SYN-Interface die gewünschten IPs vergeben
- Über das [+] auf der rechten Seite muss man folgende Einträge machen:
virtuelle WAN IP
| Parameter | Wert |
|---|---|
| Mode | CARP |
| Interface | WAN |
| Address | 192.168.HS.X+20/24 |
| Virtual Password | radler |
| VHID Group | X |
| Advertising Frequency | 1 |
| Description | Virtual WAN IP |
virtuelle LAN IP
| Parameter | Wert |
|---|---|
| Mode | CARP |
| Interface | LAN |
| Address | 192.168.1.3/24 |
| Virtual Password | radler |
| VHID Group | 100 |
| Advertising Frequency | 1 |
| Description | Virtual LAN IP |
Source NAT (Master Firewall)
- Da die virtuelle IP für ausgehende Verbindungen benutzt werden soll, muss die automatische Regelgenerierung ausgeschaltet werden
- Im Menü Firewall => NAT => Outbound muss die Option "Manual outbound NAT rule generation" ausgewählt werden
- Dann die folgende Regel erstellen:
- Interface: WAN
- Source address: LAN net
- Translation / target: Virtual WAN IP (192.168.HS.X+20) aus der Auswahlliste
- Achtung
- Als Ziel muss der VIP-Eintrag aus der Auswahlliste gewählt werden, nicht das Netz 192.168.HS.0/24. Trägt man ein ganzes Netz ein, baut OPNsense daraus einen NAT-Pool.
High Availability Konfiguration (Master Firewall)
- Die eigentliche HA-Einstellung erfolgt über das Menü System => High Availability => Settings:
| Parameter | Wert |
|---|---|
| Synchronize all states via | SYN |
| Sync compatibility | OPNsense 24.7 or above |
| Synchronize Peer IP | 100.64.64.2 |
| Synchronize Config | 100.64.64.2 |
| Verify peer | deaktiviert |
| Remote System Username | root |
| Remote System Password | 123Start$ |
| Services | Aliases, Firewall Rules, NAT, Virtual IPs |
- "Verify peer" bleibt deaktiviert, weil die Web-GUI der Gegenstelle ein selbstsigniertes Zertifikat verwendet.
High Availability Konfiguration (Backup Firewall)
- Hier darf im Menü System => High Availability => Settings nur folgendes eingestellt werden:
| Parameter | Wert |
|---|---|
| Synchronize all states via | SYN |
| Sync compatibility | OPNsense 24.7 or above |
| Synchronize Peer IP | 100.64.64.1 |
| Synchronize Config | leer |
| Verify peer | deaktiviert |
| Remote System Username | leer |
| Remote System Password | leer |
| Services | Nothing selected |
- Synchronize Config muss auf dem Backup leer bleiben. Trägt man hier den Master ein, schieben sich beide Knoten gegenseitig ihre Konfiguration zu.
Client im LAN
- Der Windows-Client (192.168.1.50) muss als Gateway und als DNS-Server die LAN-VIP 192.168.1.3 erhalten – nicht die 192.168.1.1
- Wird die echte IP des Masters eingetragen, ist der Client beim Ausfall des Masters trotz funktionierendem Cluster offline
- Bei Verwendung eines DHCP-Servers muss dieser die VIP als Gateway und DNS verteilen
Endergebnis
Master
- System
- High Availability
- Status
- High Availability
- Hier müssen beide Spalten gefüllt sein und auf beiden Knoten die gleichen Dienste erscheinen:
| Service | Description |
|---|---|
| configd | System Configuration Daemon |
| cron | Cron |
| hostwatch | Host discovery service |
| login | Users and Groups |
| ntpd | Network Time Daemon |
| openssh | Secure Shell Daemon |
| pf | Packet Filter |
| routing | System routing |
| sysctl | System tunables |
| syslog-ng | Syslog-ng Daemon |
| unbound | Unbound DNS |
| webgui | Web GUI |
Slave
- System
- High Availability
- Status
- High Availability
- Auf der Backup-Firewall erscheint hier die Warnung, dass die XMLRPC-Konfiguration unvollständig sei.
- Diese Meldung kann ignoriert werden: Das Backup empfängt nur passiv, deshalb sind die XMLRPC-Felder dort absichtlich leer und werden fälschlicherweise als "unvollständig" markiert. Solange die Master-Firewall auf Version 24.7 eingestellt ist und die Daten erfolgreich überträgt, arbeitet der Cluster technisch einwandfrei.
Failover testen
- Auf dem Client einen Dauerping nach draußen starten:
ping -t 192.168.HS.254
- Auf dem Master: System => High Availability => Status => Enter persistent CARP maintenance mode
- Erwartetes Verhalten:
- Das Backup wechselt für beide VHIDs von BACKUP auf MASTER
- Der Ping läuft weiter oder verliert maximal ein bis zwei Pakete
- Kontrolle auf beiden Knoten:
ifconfig em0 ; ifconfig em1
- Zurückschalten über Leave persistent CARP maintenance mode auf dem Master
- Zweiter Test: Master hart ausschalten (VM stoppen) und das gleiche Verhalten prüfen
Debugging
Vorgehen
- Von unten nach oben prüfen: erst CARP (Layer 2/3), dann pfsync (States), dann XMLRPC (Konfiguration)
- Ein Cluster kann sauber synchronisieren und trotzdem kein Failover können – und umgekehrt
Schritt 1: CARP-Status
- Auf beiden Knoten:
ifconfig em0 ; ifconfig em1
- Erwartetes Bild:
| Knoten | LAN (vhid 100) | WAN (vhid X) |
|---|---|---|
| Master | MASTER, advskew 0 | MASTER, advskew 0 |
| Backup | BACKUP, advskew 100 | BACKUP, advskew 100 |
- In der GUI: Interfaces => Virtual IPs => Status
- CARP global ein-/ausgeschaltet:
sysctl net.inet.carp.allow
- Ausführlichere CARP-Meldungen im Log einschalten:
sysctl net.inet.carp.log=2
Schritt 2: Beide Knoten sind MASTER (Split Brain)
- Das häufigste Fehlerbild im Labor. Beide Knoten sehen den Partner nicht und übernehmen die VIP.
- Prüfen, ob die Advertisements des Partners überhaupt ankommen:
tcpdump -n -i em1 proto 112 tcpdump -n -i em0 proto 112
- Man muss die Pakete beider Knoten sehen (Quelle = jeweils die echte Interface-IP)
| Beobachtung | Ursache |
|---|---|
| Nur eigene Pakete sichtbar | Promiscuous-Modus im Hypervisor fehlt |
| Gar keine Pakete sichtbar | VIP nicht angelegt oder Interface down |
| Pakete kommen an, trotzdem beide MASTER | CARP-Allow-Regel auf dem Interface fehlt |
| Pakete mit fremder VHID | Anderer Teilnehmer nutzt die gleiche VHID |
- Weitere Ursachen bei Split Brain:
- Unterschiedliches Virtual Password auf den beiden Knoten
- Unterschiedliche VHID auf den beiden Knoten
- Unterschiedliche Advertising Frequency
Schritt 3: Kein Failover trotz korrektem Status
- Demotion-Zähler prüfen – ist er größer als 0, bleibt der Knoten absichtlich BACKUP:
sysctl net.inet.carp.demotion
- Ursachen für einen erhöhten Zähler: ein Interface ist down, ein Dienst startet nicht sauber, der Knoten befindet sich noch im Maintenance Mode
- Maintenance Mode verlassen: System => High Availability => Status => Leave persistent CARP maintenance mode
Schritt 4: Sicht des Clients
- Auf dem Windows-Client prüfen, welche MAC hinter dem Gateway steckt:
arp -a
- Die LAN-VIP muss auf eine virtuelle MAC zeigen, nicht auf die echte NIC des Masters:
192.168.1.3 00-00-5e-00-01-64
- Das letzte Byte ist die VHID in hex – 0x64 = 100
- Steht dort eine 08:00:27:... Adresse, arbeitet der Client an CARP vorbei direkt mit einer echten Firewall-IP
- Nach einem Failover darf sich der ARP-Eintrag nicht ändern – genau das ist der Sinn der virtuellen MAC
Schritt 5: Zustandssynchronisation (pfsync)
- Läuft der pfsync-Verkehr über das SYN-Netz?
tcpdump -n -i em2 proto 240
- Anzahl der States auf beiden Knoten vergleichen – die Werte müssen ähnlich sein:
pfctl -s state | wc -l
- Ist die Zahl auf dem Backup dauerhaft 0, überträgt pfsync nicht:
- Synchronize Peer IP zeigt auf die falsche Adresse
- Die Allow-Regel auf dem SYN-Interface fehlt
- SYN-Interface auf einem der Knoten nicht aktiviert
Schritt 6: Konfigurationssynchronisation (XMLRPC)
- Auf der Master-Firewall: System => Log Files => General, im Filter-Feld xmlrpc eingeben
- Gesucht wird ein Eintrag wie: [OK] Configuration synchronized to https://100.64.64.2:443
- Manuell anstoßen: System => High Availability => Status => Synchronize and reconfigure all (Push)
- Gleichzeitig auf dem Backup mitlesen:
tail -f /var/log/configd/latest.log
| Meldung | Ursache |
|---|---|
| Connection refused | Web-GUI des Backups nicht erreichbar oder falscher Port |
| Authentication failed | Falsches Passwort unter "Remote System Password" |
| Certificate verify failed | "Verify peer" ist aktiviert, Zertifikat ist selbstsigniert |
| Endlose Sync-Schleife | Auf dem Backup ist "Synchronize Config" gefüllt – muss leer sein |
Schritt 7: Ausgehende Verbindungen
- Prüfen, mit welcher Quelladresse der Client nach draußen geht:
tcpdump -n -i em1 host 192.168.HS.254
- Es muss die Virtual WAN IP (192.168.HS.X+20) erscheinen, nicht die echte IP des Masters
- Erscheint die echte IP: Outbound-NAT steht noch auf automatisch, oder in der manuellen Regel wurde als Target nicht die VIP gewählt
Nützliche Befehle im Überblick
| Befehl | Zweck |
|---|---|
| ifconfig em0 ; ifconfig em1 | CARP-Rolle und VIPs anzeigen |
| tcpdump -n -i em1 proto 112 | CARP-Advertisements mitlesen |
| tcpdump -n -i em2 proto 240 | pfsync-Verkehr mitlesen |
| wc -l | Anzahl der Firewall-States |
| sysctl net.inet.carp.demotion | Demotion-Zähler |
| sysctl net.inet.carp.log=2 | Ausführliches CARP-Logging |
| tail -f /var/log/configd/latest.log | Konfigurationssync mitlesen |
| configctl filter reload | Regelwerk neu laden |
Netzwerkschnittstellen
Master
em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 description: LAN (lan) options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> ether 08:00:27:c4:a2:6f inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255 inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid 100 carp: MASTER vhid 100 advbase 1 advskew 0 peer 224.0.0.18 peer6 ff02::12 media: Ethernet autoselect (1000baseT <full-duplex>) status: active nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
em1: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 description: WAN (wan) options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> ether 08:00:27:61:6f:6d inet 192.168.HS.X+40 netmask 0xffffff00 broadcast 192.168.HS.255 inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X carp: MASTER vhid X advbase 1 advskew 0 peer 224.0.0.18 peer6 ff02::12 media: Ethernet autoselect (1000baseT <full-duplex>) status: active nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Backup
em0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 description: LAN (lan) options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> ether 08:00:27:1c:44:8b inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255 inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 vhid 100 carp: BACKUP vhid 100 advbase 1 advskew 100 peer 224.0.0.18 peer6 ff02::12 media: Ethernet autoselect (1000baseT <full-duplex>) status: active nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
em1: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500 description: WAN (wan) options=48500b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,VLAN_HWTSO,HWSTATS,MEXTPG> ether 08:00:27:95:9b:4b inet 192.168.HS.X+60 netmask 0xffffff00 broadcast 192.168.HS.255 inet 192.168.HS.X+20 netmask 0xffffff00 broadcast 192.168.HS.255 vhid X carp: BACKUP vhid X advbase 1 advskew 100 peer 224.0.0.18 peer6 ff02::12 media: Ethernet autoselect (1000baseT <full-duplex>) status: active nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
- Der Master hat advskew 0, das Backup advskew 100. Diesen Wert setzt OPNsense beim Sync automatisch – er wird nicht von Hand vergeben.
Wird Synchronisiert?
- Master
- System
- High Availability
- Status
- Synchronize and reconfigure all (Push)
- Status
- High Availability
- Backup
tail -f /var/log/configd/latest.log
- Hier sollte man die Übertragung sehen.
