Skip to content

Instantly share code, notes, and snippets.

@SoftCreatR
Last active January 1, 2024 12:36
Show Gist options
  • Save SoftCreatR/ad836edd0214a822263ea2089ebb49e2 to your computer and use it in GitHub Desktop.
Save SoftCreatR/ad836edd0214a822263ea2089ebb49e2 to your computer and use it in GitHub Desktop.
Hetzner Cloud Firewall Cloudflare IP Updater using either curl, wget or httpie.
#!/usr/bin/env bash
##############################################################
# Title : Hetzner Firewall Cloudflare IP Updater #
# Description : Allows you to update your Hetzner Cloud #
# Firewall to allow all incoming requests #
# from Cloudflare. #
# #
# Author : Sascha Greuel <[email protected]> #
# Date : 2021-03-30 09:30 #
# License : MIT #
# Version : 1.2.0 #
# #
# Usage : bash update-hcfw.sh #
##############################################################
###
# You can either set the following option values manually,
# or append --client / --api-token / --firewall-id / --ports
# to the executed bash command.
###
CLIENT=""
API_TOKEN=""
FIREWALL_ID=""
PORTS="80,443"
###
# Helper functions
###
getClient()
{
if command -v curl &>/dev/null; then
CLIENT="curl"
elif command -v wget &>/dev/null; then
CLIENT="wget"
elif command -v http &>/dev/null; then
CLIENT="httpie"
else
echo "Error: This tool requires either curl, wget or httpie to be installed." >&2
return 1
fi
}
httpGet()
{
case "$CLIENT" in
curl) curl -A curl -s "$@" ;;
wget) wget -qO- "$@" ;;
httpie) http -b GET "$@" ;;
esac
}
updateFirewall()
{
API="https://api.hetzner.cloud/v1/firewalls/$FIREWALL_ID/actions/set_rules"
AUTHORIZATION="Authorization: Bearer $API_TOKEN"
CONTENT_TYPE="Content-Type: application/json"
POST_DATA='{"rules":['"$1"']}'
case "$CLIENT" in
curl) curl -X POST -H "$AUTHORIZATION" -H "$CONTENT_TYPE" -d "$POST_DATA" "$API" ;;
wget) wget -O- --header="$AUTHORIZATION" --header="$CONTENT_TYPE" --post-data="$POST_DATA" "$API" ;;
httpie) echo "$POST_DATA" | http POST "$API" "$AUTHORIZATION" ;;
esac
}
###
###
# Check prerequisites
###
while [ "$#" -gt 0 ]; do
case "$1" in
--client) CLIENT="$2" ;;
--api-token) API_TOKEN="$2" ;;
--firewall-id) FIREWALL_ID="$2" ;;
--ports) PORTS="$2" ;;
esac
shift
done
if [ -z "$CLIENT" ]; then
getClient || exit 1
fi
if ! httpGet github.com >/dev/null 2>&1; then
echo -e "No active internet connection. Please try again."
exit 1
fi
if [ -z "$API_TOKEN" ]; then
echo -e "API Token missing. Please run ./$0 --api-token API_TOKEN"
exit 1
fi
if [ -z "$FIREWALL_ID" ]; then
echo -e "Firewall ID missing. Please run ./$0 --firewall-id YOUR-FIREWALL-ID"
exit 1
fi
if [ -z "$PORTS" ]; then
echo -e "Port(s) missing. Please run ./$0 --ports COMMA-SEPARATED-LIST-OF-PORTS"
exit 1
fi
IPS=$(httpGet https://www.cloudflare.com/ips-v4)
IPS+=$(echo "" && httpGet https://www.cloudflare.com/ips-v6)
IPS=$(echo "$IPS" | sed "s/.*/\"&\"/;H;1h;"'$!d;x;s/\n/,/g')
RULES=()
# shellcheck disable=SC2116
for PORT in $(echo "${PORTS//,/ }"); do
RULES+=('{"direction":"in","source_ips":['"$IPS"'],"protocol":"tcp","port":"'"$PORT"'"}')
done
updateFirewall "$(IFS=, ; echo "${RULES[*]}")"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment