Skip to content

Instantly share code, notes, and snippets.

@simontraill
Last active July 18, 2018 16:50
Show Gist options
  • Save simontraill/bf34665372515cd4699fac7f4ec7e2ba to your computer and use it in GitHub Desktop.
Save simontraill/bf34665372515cd4699fac7f4ec7e2ba to your computer and use it in GitHub Desktop.
SwiftStack Firewall rules addition - example
#!/usr/bin/env bash
# Allow extra connections to a SwiftStack controller or node through the firewall.
# We require firewall-cmd be installed for this, or else we warn the user.
# On startup this script adds a new input chain called localrules-in...
#
# - To the INPUT chain if on a node;
# - To the IN_public_allow chain if on a controller.
#
# For Enterprise Linux 7 only; for IPv4 only.
#
# straill@swiftstack.com 2018/07/18
#
# To use:
#
# 1. Copy this script to /opt/swiftstack-extra-firewall-rules/firewall_up.sh
# on the controller or every node for which you need extra rules;
# 2. Edit the PORTS variable just below the top and set it to the ports you need, in
# format <port_number>:<protocol>, whitespace seperated (the example below
# allows inbound TCP connections to ports 3000 and 3001, for instance).
# 3. Run this script as root with the "add-service" option to add a systemd service
# that adds firewall chains on startup:
#
# # sh /opt/swiftstack-extra-firewall-rules/firewall_up.sh add-service
#
# 4. As root, set permissions and start the service as shown below.
#
# # chown -R root:root /opt/swiftstack-extra-firewall-rules
# # systemctl start swiftstack-extra-firewall-rules.service
# # systemctl status swiftstack-extra-firewall-rules.service
# Configure the ports you'd like here. Protocol should be lowercase and one of "tcp", "udp".
PORTS="3000:tcp 3001:tcp"
fatal() {
echo $1 1>&2
exit 1
}
# Install a systemd service if requested
if [ "$1" = "add-service" ]; then
cat <<'EOF' > /lib/systemd/system/swiftstack-extra-firewall-rules.service
[Unit]
Description=Local firewall rules for SwiftStack nodes
Requires=firewalld.service
Before=network.target
Before=libvirtd.service
Before=NetworkManager.service
After=firewalld.service
After=ssnode-firewall.service
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c '/opt/swiftstack-extra-firewall-rules/firewall_up.sh'
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
echo " >> Added systemd service (swiftstack-extra-firewall-rules.service)"
systemctl daemon-reload || fatal "Coudn't run 'systemctl daemon-reload'"
systemctl enable swiftstack-extra-firewall-rules.service || fatal "Coudn't run 'systemctl enable swiftstack-extra-firewall-rules.service'"
echo " >> Enabled systemd service (swiftstack-extra-firewall-rules.service)"
echo
echo "Run 'systemctl start swiftstack-extra-firewall-rules.service' to add your firewall rules when ready."
exit 0
fi
# Otherwise modify the firewall.
# We add a new chain named "localrules-in" for the PORTS specified above.
# On nodes, we just add this chain to the first free slot in the INPUT chain.
# On controllers, we add this chain to the slot in the IN_public_allow chain.
CHAIN=INPUT
IS_CONTROLLER=false
if [ -f /opt/ss/etc/ssman.crt ]; then
IS_CONTROLLER=true
CHAIN=IN_public_allow
fi
if [ -f /bin/firewall-cmd -a "$(/bin/firewall-cmd --state)" = "running" ]; then
LOCALRULES_SLOT=$( iptables --list ${CHAIN} -n --line-numbers | awk '$2=="localrules-in" {print $1}' | head -1 )
if [ "X${LOCALRULES_SLOT}" != "X" ]; then
/bin/firewall-cmd --direct --remove-rule ipv4 filter ${CHAIN} ${LOCALRULES_SLOT} -j localrules-in >/dev/null 2>&1
fi
# Remove rules from localrules chain
/bin/firewall-cmd --direct --remove-rules ipv4 filter localrules-in >/dev/null 2>&1
# Remove localrules chain
/bin/firewall-cmd --direct --remove-chain ipv4 filter localrules-in >/dev/null 2>&1
# Locate the first free slot in the input chain
LOCALRULES_SLOT=$( iptables --list ${CHAIN} -n --line-numbers | awk '$2=="localrules-in" {print $1}' | head -1 )
if [ ${IS_CONTROLLER} == 'true' ]; then
SLOT=$( iptables --list ${CHAIN} -n --line-numbers | grep ACCEPT | awk '$2=="ACCEPT" {print $1}' | tail -1 )
SLOT=$(( ${SLOT} + 1 ))
else
SLOT=$( iptables --list ${CHAIN} -n --line-numbers | grep ACCEPT | awk '$2=="ACCEPT" {print $1}' | head -1 )
fi
if [ "X${SLOT}" != "X" ]; then
if [ "X${LOCALRULES_SLOT}" = "X" ]; then
# Add chain
/bin/firewall-cmd --direct --add-passthrough ipv4 -N localrules-in >/dev/null 2>&1
# Add chain to input chain
/bin/firewall-cmd --direct --add-passthrough ipv4 -I ${CHAIN} ${SLOT} -j localrules-in >/dev/null 2>&1
# Add our ports to the localrules chain.
for PORT in $PORTS; do
PORTNUM=$( echo ${PORT} | awk -F: '{print $1}' )
PROTO=$( echo ${PORT} | awk -F: '{print $2}' )
/bin/firewall-cmd --direct --add-passthrough ipv4 -A localrules-in -p ${PROTO} --dport ${PORTNUM} -j ACCEPT >/dev/null 2>&1
done
else
echo "Could not find a free slot in iptables for localrules-in chain - you'll need to allow firewall access to port 3000 manually"
fi
fi
elif [ -f /bin/firewall-cmd ]; then
echo "Firewalld is installed but not running. Will not add firewall rules for LOCALRULES".
else
echo "Firewalld is not installed. If you use iptables, you should add firewall rules for LOCALRULES manually (ie, allow TCP 3000 inbound)."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment