Skip to content

Instantly share code, notes, and snippets.

@peelman
Created July 27, 2016 12:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save peelman/973f519ae32c526e894b3ee4186e7dc3 to your computer and use it in GitHub Desktop.
Save peelman/973f519ae32c526e894b3ee4186e7dc3 to your computer and use it in GitHub Desktop.
Backup pfSense firewalls remotely

Description

Based upon this script but updated to backup a highly available pair of firewalls from a remote backup server.

Also uses pigz in place of gz to parallelize (and rapidly speed up) compression (and if you're keeping more than a couple of days worth, you'll want to compress these).

Keeps 30 days of backups by default. Assumes that Cron runs daily. Adjust the KEEP_DAYS variable if necessary.

Requirements

  • pfSense, obviously
  • a dedicated Backup user, with WebCfg - Diagnostics: Backup & Restore permission
  • a remote server to run this script from
  • proper values for PFSENSE_HOST1, PFSENSE_HOST2, PFSENSE_USER, PFSENSE_PASS, BACKUP_DIR, etc.
#!/bin/sh
#
######################################################################################################
#
# Description:
# Backup pfSense 2.3 Firewalls to Local Disk
#
######################################################################################################
#
# Author: Nick Peelman
# Based upon: https://eternallybored.org/misc/pfsense/pfsensebackup.sh
#
######################################################################################################
#
# Usage:
# pfsense-backup.sh
#
######################################################################################################
#
# Requirements
# * user named "backup" on pfsense firewall
# * named user must have permissions to backup page
#
######################################################################################################
#
# TODO:
# * Post All Alerts to Slack.
#
######################################################################################################
#pfSense host (note: do not include the final /, otherwise backup will fail)
PFSENSE_HOST1=host1.domain.tld
PFSENSE_HOST2=host2.domain.tld
#login username
PFSENSE_USER=backup
#login password
PFSENSE_PASS=<password>
#path to binaries
WGET=/usr/bin/wget
GZIP=/usr/bin/pigz
#where to store backups
BACKUP_DIR=/path/to/pfSense/backup
#days to keep old backups for
KEEP_DAYS=30
#backup RRD data: 0 = no, anything else = yes
BACKUP_RRD=1
#backup package information: 0 = no, anything else = yes
BACKUP_PKGINFO=1
#encrypt backup with password (leave empty to not encrypt it)
BACKUP_PASSWORD=
# Build URLs
URL1="https://$PFSENSE_HOST1"
URL2="https://$PFSENSE_HOST2"
#backup path
HOST1_BACKUP_PATH="$BACKUP_DIR/$PFSENSE_HOST1"
HOST2_BACKUP_PATH="$BACKUP_DIR/$PFSENSE_HOST2"
#backup filename
HOST1_BACKUP_NAME="$HOST1_BACKUP_PATH/pfSense-backup-`date +%Y-%m-%d`.xml"
HOST2_BACKUP_NAME="$HOST2_BACKUP_PATH/pfSense-backup-`date +%Y-%m-%d`.xml"
COOKIE_FILE1="`mktemp /tmp/pfsbck1.XXXXXXXX`"
COOKIE_FILE2="`mktemp /tmp/pfsbck2.XXXXXXXX`"
unset RRD
unset PKG
unset PW
if [ "$BACKUP_RRD" = "0" ]
then
RRD="&donotbackuprrd=on"
fi
if [ "$BACKUP_PKGINFO" = "0" ]
then
PKG="&nopackages=on"
fi
if [ -n "$BACKUP_PASSWORD" ]
then
PW="&encrypt_password=$BACKUP_PASSWORD&encrypt_passconf=$BACKUP_PASSWORD&encrypt=on"
fi
mkdir -p "$BACKUP_DIR"
#fetch CSRF token
HOST1_CSRF1=$("$WGET" -qO- /dev/null --keep-session-cookies --save-cookies "$COOKIE_FILE1" "$URL1/diag_backup.php" | grep "name='__csrf_magic'" | sed 's/.*value="\(.*\)".*/\1/')
HOST2_CSRF1=$("$WGET" -qO- /dev/null --keep-session-cookies --save-cookies "$COOKIE_FILE2" "$URL2/diag_backup.php" | grep "name='__csrf_magic'" | sed 's/.*value="\(.*\)".*/\1/')
#log in
HOST1_CSRF2=$("$WGET" -qO- /dev/null --keep-session-cookies --save-cookies "$COOKIE_FILE1" --post-data "__csrf_magic=$HOST1_CSRF1&login=Login&usernamefld=$PFSENSE_USER&passwordfld=$PFSENSE_PASS" "$URL1/diag_backup.php" | grep "name='__csrf_magic'" | sed 's/.*value="\(.*\)".*/\1/')
HOST2_CSRF2=$("$WGET" -qO- /dev/null --keep-session-cookies --save-cookies "$COOKIE_FILE2" --post-data "__csrf_magic=$HOST2_CSRF1&login=Login&usernamefld=$PFSENSE_USER&passwordfld=$PFSENSE_PASS" "$URL2/diag_backup.php" | grep "name='__csrf_magic'" | sed 's/.*value="\(.*\)".*/\1/')
#download backup
"$WGET" -q --keep-session-cookies --load-cookies "$COOKIE_FILE1" --post-data "__csrf_magic=$HOST1_CSRF2&Submit=download$RRD$PKG$PW" "$URL1/diag_backup.php" -O "$HOST1_BACKUP_NAME" || mail -s "pfSense Backup Failed (fw121)" noc@thedatacave.com
"$WGET" -q --keep-session-cookies --load-cookies "$COOKIE_FILE2" --post-data "__csrf_magic=$HOST2_CSRF2&Submit=download$RRD$PKG$PW" "$URL2/diag_backup.php" -O "$HOST2_BACKUP_NAME" || mail -s "pfSense Backup Failed (fw130)" noc@thedatacave.com
"$GZIP" "$HOST1_BACKUP_NAME" "$HOST2_BACKUP_NAME"
#delete cookie jar
rm -f "$COOKIE_FILE1" "$COOKIE_FILE2"
#delete old backups
find "$BACKUP_DIR" -type f -and -mtime +"$KEEP_DAYS" -exec rm -f '{}' \;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment