-
-
Save willjasen/6ae0f47bca36ced2bd52b2fefc2bc21e to your computer and use it in GitHub Desktop.
Disable WAN interfaces when CARP is down
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/php | |
<?php | |
/* | |
This script can be used with OPNsense when using CARP in certain circumstances where CARP is desired on the LAN side | |
but where CARP cannot run on the WAN side. This script runs each time an event by CARP is generated. In the event that | |
there are multiple LAN interfaces where CARP is enabled, this script will check that all interfaces where CARP is | |
enabled are in a particular state (MASTER/BACKUP) before enabling or disabling its WAN interfaces. | |
*/ | |
// this file should be saved to /usr/local/etc/rc.syshook.d/carp/10-wancarp | |
// some ideas taken from https://gist.github.com/taxilian/eecdc1fb17cf70e8080118cf6d8af412 | |
/* --- EDIT AS NEEDED --- */ | |
// my primary WAN is on the opt2 interface and secondary WAN is on the wan interface | |
$interfaces = array('opt2', 'wan'); | |
require_once("config.inc"); | |
require_once("interfaces.inc"); | |
require_once("util.inc"); | |
$subsystem = !empty($argv[1]) ? $argv[1] : ''; | |
$type = !empty($argv[2]) ? $argv[2] : ''; | |
if ($type != 'MASTER' && $type != 'BACKUP' && $type != 'INIT' && $type != 'DISABLED') { | |
log_error("CARP '$type' event unknown from source '{$subsystem}'"); | |
exit(1); | |
} | |
if (!strstr($subsystem, '@')) { | |
log_error("CARP '$type' event triggered from wrong source '{$subsystem}'"); | |
exit(1); | |
} | |
// Get a list of CARP statuses across interfaces that have it | |
$cmd = "/sbin/ifconfig -m -v | grep 'carp:' | awk '{print $2}'"; | |
$cmd2 = "/sbin/ifconfig -m -v | grep 'carp:' | awk '{print $2}' | wc -l | tr -d ' '"; | |
exec($cmd, $ifconfig_data, $ret); | |
exec($cmd2, $ifconfig_num, $ret); | |
$activeCARPInterfaces = $ifconfig_num[0]; | |
// Log what the CARP subsystem is doing | |
// After INIT, the subsystem will become BACKUP, then MASTER if needed | |
if($type == 'INIT' && $activeCARPInterfaces > 0) { | |
log_error("CARP on '{$subsystem}' is now INIT, but other subsystems are still active"); | |
} else if($type == 'INIT' && $activeCARPInterfaces == 0) { | |
log_error("CARP on '{$subsystem}' is now INIT, and appears to be the last active"); | |
} | |
else if($type == 'MASTER' && $activeCARPInterfaces > 0) { | |
log_error("CARP on '{$subsystem}' is now MASTER, but other subsystems are still active"); | |
} else if($type == 'MASTER' && $activeCARPInterfaces == 0) { | |
log_error("CARP on '{$subsystem}' is now MASTER, and appears to be the last active"); | |
} | |
else if($type == 'BACKUP' && $activeCARPInterfaces > 0) { | |
log_error("CARP on '{$subsystem}' is now BACKUP, other subsystems are still active"); | |
} else if($type == 'BACKUP' && $activeCARPInterfaces == 0) { | |
log_error("CARP on '{$subsystem}' is now BACKUP, and appears to be the last active"); | |
} | |
// If no CARP subsystems/interfaces are active, then disable WAN interfaces | |
// This will generally apply when CARP is disabled and reports no statuses | |
if($activeCARPInterfaces == 0) { | |
log_error("No CARP subsystems are active, deactivating WAN interfaces"); | |
foreach ($interfaces as $ifkey) { | |
unset($config['interfaces'][$ifkey]['enable']); | |
interface_configure(false, $ifkey, false, false); | |
write_config("disable interface '$ifkey' due CARP event '$type'", false); | |
} | |
exit(0); | |
} | |
// Keep track of active MASTER and BACKUP instances | |
$masterCount = 0; | |
$backupCount = 0; | |
// Loop over $ifconfig_data and count how many are "MASTER" and how many are "BACKUP" | |
foreach ($ifconfig_data as $line) { | |
if (strpos($line, 'MASTER') !== false) { | |
$masterCount++; | |
} else if (strpos($line, 'BACKUP') !== false) { | |
$backupCount++; | |
} | |
} | |
// Toggle WAN interfaces depending if all interfaces are MASTER or BACKUP | |
if ($masterCount == $activeCARPInterfaces && $masterCount > 0) { | |
// The current node is all MASTER | |
log_error("All CARP subsystems are MASTER, activating WAN interfaces"); | |
foreach ($interfaces as $ifkey) { | |
$config['interfaces'][$ifkey]['enable'] = '1'; | |
interface_configure(false, $ifkey, false, false); | |
write_config("enable interface '$ifkey' due CARP event '$type'", false); | |
} | |
} else if ($backupCount == $activeCARPInterfaces && $backupCount > 0) { | |
// The current node is all BACKUP | |
log_error("Not all CARP subsystems are MASTER, deactivating WAN interfaces"); | |
foreach ($interfaces as $ifkey) { | |
unset($config['interfaces'][$ifkey]['enable']); | |
interface_configure(false, $ifkey, false, false); | |
write_config("disable interface '$ifkey' due CARP event '$type'", false); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey there everyone looking at this thread - I hope this script has helped out in some way!
I am softly abandoning my further development however. My setup where this was used was running two OPNsense instances virtually acting as my primary home firewall/router, but I have since replaced it with a Ubiquiti firewall - the two main reasons for myself being that it would be less time developing and troubleshooting this script as well as I could foreshadow an edge case where my Proxmox cluster might not gain quorum and be able to boot up virtual machines (including the OPNsenses) and thus would be a catch 22 and very bad. I still could have a use case for this within my dedicated cloud server, but one OPNsense there is enough and two aren't necessary.
Thank you, namaste, and good luck!