From 8294e508bbf8c662a71e61a7a8ff15059e246e25 Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Thu, 15 Aug 2024 18:12:16 -0700 Subject: [PATCH 1/7] In beta testing --- hardening/UFW Cloudflare/ufw-cloudflare.bash | 211 +++++++++++++++++++ 1 file changed, 211 insertions(+) diff --git a/hardening/UFW Cloudflare/ufw-cloudflare.bash b/hardening/UFW Cloudflare/ufw-cloudflare.bash index e69de29..a775e4d 100644 --- a/hardening/UFW Cloudflare/ufw-cloudflare.bash +++ b/hardening/UFW Cloudflare/ufw-cloudflare.bash @@ -0,0 +1,211 @@ +#!/bin/bash +# +# +# +######################################################################################## +####[ Global Variables ]################################################################ + + +## URL for retrieving the current Cloudflare IP ranges. +readonly C_CLOUDFLARE_IPV4_RANGES_URL="https://www.cloudflare.com/ips-v4/" +readonly C_CLOUDFLARE_IPV6_RANGES_URL="https://www.cloudflare.com/ips-v6/" + +current_cloudflare_rule_numbers=() +current_cloudflare_ip_ranges=() +new_cloudflare_ip_ranges=() +stage=0 + + +####[ Function ]######################################################################## + + +#### +# Description: +# Check if a UFW rule exists for a specific IP address and port. +# +# Arguments: +# - $1: ip (Required) +# - The IP address to check. +# - $2: port (Required) +# - The port to check. +# +# Return: +# - 0: The rule exists. +# - ?: The rule does not exist. +ufw_rule_exists() { + local ip="$1" + local port="$2" + + ufw status | grep -qE "^${port}.*ALLOW.*${ip}.*$" +} + +#### +# Description: +# Retrieves the rule number of all Cloudflare IP rules currently set in UFW, then +# stores them in an array. +# +# Arguments: +# - $1: string_to_grep (Required) +# - The string to grep for in the UFW status output. +# - Acceptable values: +# - 0: "Cloudflare IP" +# - 1: "Temporary rule" +get_set_cloudflare_rule_numbers() { + if (( $1 == 0 )); then + local string_to_grep="Cloudflare IP" + elif (( $1 == 1 )); then + local string_to_grep="Temporary rule" + else + echo "Invalid argument: $1" + exit 1 + fi + + mapfile -t current_cloudflare_rule_numbers < <( + ufw status numbered \ + | grep "$string_to_grep" \ + | awk -F'[][]' '{print $2}' \ + | sort -rn + ) +} + +#### +# Description: +# Retrieves the IP addresses of all Cloudflare IP rules currently set in UFW, then +# stores them in an array. +get_set_cloudflare_ip_ranges() { + while IFS= read -r line; do + ip=$(echo "$line" | awk '{print $3}') # Extract the IP address. + current_cloudflare_ip_ranges+=("$ip") + done < <(sudo ufw status | grep "Cloudflare IP") +} + +#### +# Description: +# Set the new Cloudflare IP ranges in UFW, retrieved from the Cloudflare website. +set_new_cloudflare_ip_ranges() { + for ip in "${new_cloudflare_ip_ranges[@]}"; do + ufw_rule_exists "$ip" "80,443" \ + || ufw allow from "$ip" to any port 80,443 proto tcp comment "Cloudflare IP" + done +} + +#### +# Description: +# Restores the previous (non-new) Cloudflare IP ranges in UFW. +restore_current_cloudflare_ip_ranges() { + for ip in "${current_cloudflare_ip_ranges[@]}"; do + ufw_rule_exists "$ip" "80,443" \ + || ufw allow from "$ip" to any port 80,443 proto tcp comment "Cloudflare IP" + done +} + +#### +# Description: +# Deletes all Cloudflare IP rules currently set in UFW. +delete_set_cloudflare_rules() { + get_set_cloudflare_rule_numbers "0" + + for rule_num in "${current_cloudflare_rule_numbers[@]}"; do + # TODO: Add configuration option to confirm deletion. + yes | ufw delete "$rule_num" + done +} + +#### +# Description: +# Cleanup function to close ports 80 and 443 from any IP address. +cleanup() { + case $stage in + 2) + delete_set_cloudflare_rules "1" + ;; + 3) + echo "Potential error or interruption detected." + echo "Restoring the previous Cloudflare IP ranges..." + restore_current_cloudflare_ip_ranges + delete_set_cloudflare_rules "1" + ;; + 4) + echo "Potential error or interruption detected." + echo "Restoring the previous Cloudflare IP ranges..." + delete_new_cloudflare_ip_ranges + restore_current_cloudflare_ip_ranges + delete_set_cloudflare_rules "1" + ;; + 5) + # Continue, as we are too far along to realistically undo anything + ;; + *) + echo "Invalid stage: $stage" + ;; + esac +} + + +####[ Trap Logic ]###################################################################### + + +trap cleanup EXIT + + +####[ Main ]############################################################################ + + +### +### [ Initial Setup ] +### + +stage=1 + +get_set_cloudflare_ip_ranges +mapfile -t new_cloudflare_ip_ranges < <(curl -s "$C_CLOUDFLARE_IPV4_RANGES_URL") +mapfile -t new_cloudflare_ipv6_ranges < <(curl -s "$C_CLOUDFLARE_IPV6_RANGES_URL") + +new_cloudflare_ip_ranges+=("${new_cloudflare_ipv6_ranges[@]}") +unset new_cloudflare_ipv6_ranges + +### +### [ Opening ports 80 and 443 from any IP address ] +### + +stage=2 + +echo "Temporarily opening ports 80 and 443 from any IP address..." +ufw allow from any to any port 80,443 proto tcp comment "Temporary rule" +sleep 1 # Wait for the rule to take effect. + +### +### [ Removing the existing Cloudflare IP ranges ] +### + +stage=3 + +if (( ${#current_cloudflare_ip_ranges[@]} != 0 )); then + echo "Removing the existing Cloudflare IP ranges..." + delete_set_cloudflare_rules +fi + +sleep 1 # Wait for the rule to take effect. + +### +### [ Adding the new Cloudflare IP ranges ] +### + +stage=4 + +echo "Adding the new Cloudflare IPv4 and IPv6 ranges..." +set_new_cloudflare_ip_ranges +sleep 1 # Wait for the rule to take effect. + +### +### [ Finalizing ] +### + +stage=5 + +echo "Removing temporary rules..." +ufw delete allow from any to any port 80,443 proto tcp +sleep 1 # Wait for the rule to take effect. + +echo "Done." + From 97e21c5703d41217e09067f653c9ad5c29c2666b Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Thu, 15 Aug 2024 18:13:01 -0700 Subject: [PATCH 2/7] Made script executable --- hardening/UFW Cloudflare/ufw-cloudflare.bash | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hardening/UFW Cloudflare/ufw-cloudflare.bash diff --git a/hardening/UFW Cloudflare/ufw-cloudflare.bash b/hardening/UFW Cloudflare/ufw-cloudflare.bash old mode 100644 new mode 100755 From a09d6dee82e9ebc0304052ad8191e86ad50815a9 Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Thu, 15 Aug 2024 18:13:26 -0700 Subject: [PATCH 3/7] Remove Deepsource configuration file --- .deepsource.toml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 01a11e0..0000000 --- a/.deepsource.toml +++ /dev/null @@ -1,9 +0,0 @@ -version = 1 - -[[analyzers]] -name = "secrets" -enabled = true - -[[analyzers]] -name = "shell" -enabled = true \ No newline at end of file From 8326d72847a6f96b504e2f1090052db8d0657c4c Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Thu, 15 Aug 2024 18:16:57 -0700 Subject: [PATCH 4/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 445967e..7439812 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repository is a collection of scripts designed to secure/harden Linux based Distributions. -For information on each of the scripts, visit the [repo wiki](https://github.com/StrangeRanger/linux-security-scripts/wiki). Each page will provide information on the script in question, example output, and a changelog. + ## Getting Started From 40f03a35ddea33565b4b02bf874ca67b09a24b4a Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Thu, 17 Oct 2024 13:57:46 -0700 Subject: [PATCH 5/7] Update comments and readonly properties --- auditing/Lynis Installer/lynis-installer.bash | 11 +++----- hardening/Root Locker/root-locker.bash | 5 +--- hardening/SSHD Hardening/harden-sshd.bash | 25 ++++++++----------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/auditing/Lynis Installer/lynis-installer.bash b/auditing/Lynis Installer/lynis-installer.bash index 83b7dc7..d0faf96 100755 --- a/auditing/Lynis Installer/lynis-installer.bash +++ b/auditing/Lynis Installer/lynis-installer.bash @@ -1,12 +1,9 @@ #!/bin/bash # -# Name: lynis-installer.bash -# -# Description: -# This script downloads a security auditing tool called Lynis, designed to scan a -# system and identify security issues, and provides recommendations on how to better -# secure it. Lynis, unless an error is encountered, will always be downloaded to the -# user's root directory (/home/USERNAME/). +# This script downloads a security auditing tool called Lynis. It is designed to scan a +# system, identify security issues, and provide recommendations on how to better secure +# it. Unless an error is encountered, Lynis will always be downloaded to the current +# user's root directory (`/home/USERNAME/`). # # Version: v1.0.7 # License: MIT License diff --git a/hardening/Root Locker/root-locker.bash b/hardening/Root Locker/root-locker.bash index bb68914..fe077b1 100755 --- a/hardening/Root Locker/root-locker.bash +++ b/hardening/Root Locker/root-locker.bash @@ -1,9 +1,6 @@ #!/bin/bash # -# Name: root-locker.bash -# -# Description: -# This script locks the root account, preventing users from direct logins as root. +# This script locks the root account, preventing users from directly logging in as root. # # Note: # Locking the root account doesn't prevent users from using something like `sudo su` diff --git a/hardening/SSHD Hardening/harden-sshd.bash b/hardening/SSHD Hardening/harden-sshd.bash index 6d557e9..b14d3ff 100755 --- a/hardening/SSHD Hardening/harden-sshd.bash +++ b/hardening/SSHD Hardening/harden-sshd.bash @@ -1,14 +1,10 @@ #!/bin/bash # -# Name: harden-sshd.bash -# -# Description: -# This script hardens the sshd-server, by modifying it's configuration file -# (sshd_config). +# This script hardens the ssh server by modifying its configuration file, 'sshd_config'. # # Note: -# This configures sshd_config to the recommendations of the security auditing tool -# knonw as Lynis (https://github.com/CISOfy/lynis). +# These configurations align with the recommendations of the security auditing tool +# known as Lynis (https://github.com/CISOfy/lynis). # # Version: v2.0.0 # License: MIT License @@ -31,11 +27,11 @@ C_NC="$(printf '\033[0m')" readonly C_GREEN C_CYAN C_RED C_NC ## Short-hand colorized messages. -C_SUCCESS="${C_GREEN}==>${C_NC} " -C_WARNING="${C_YELLOW}==>${C_NC} " -C_ERROR="${C_RED}ERROR:${C_NC} " -C_INFO="${C_BLUE}==>${C_NC} " -C_NOTE="${C_CYAN}==>${C_NC} " +readonly C_SUCCESS="${C_GREEN}==>${C_NC} " +readonly C_WARNING="${C_YELLOW}==>${C_NC} " +readonly C_ERROR="${C_RED}ERROR:${C_NC} " +readonly C_INFO="${C_BLUE}==>${C_NC} " +readonly C_NOTE="${C_CYAN}==>${C_NC} " # Associative array containing the configuration settings for sshd_config. declare -A C_SSHD_CONFIG=( @@ -83,10 +79,9 @@ readonly C_SSHD_CONFIG #### -# Description: -# Cleanly exit the script. +# Cleanly exit the script. # -# Arguments: +# PARAMETERS: # - $1: exit_code (Required) # - The exit code to exit the script with. clean_exit() { From 1ce8327e6cd523333f9555a5cc6339848f000178 Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Sat, 19 Oct 2024 11:47:54 -0700 Subject: [PATCH 6/7] Specify script is in beta --- hardening/UFW Cloudflare/ufw-cloudflare.bash | 35 +++++++++----------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/hardening/UFW Cloudflare/ufw-cloudflare.bash b/hardening/UFW Cloudflare/ufw-cloudflare.bash index a775e4d..cd70ca4 100755 --- a/hardening/UFW Cloudflare/ufw-cloudflare.bash +++ b/hardening/UFW Cloudflare/ufw-cloudflare.bash @@ -1,6 +1,10 @@ #!/bin/bash # +# Sets up UFW to only allow HTTP and HTTPS traffic from Cloudflare's IP ranges. # +# Version: v1.0.0-beta.1 +# License: MIT License +# Copyright (c) 2024 Hunter T. (StrangeRanger) # ######################################################################################## ####[ Global Variables ]################################################################ @@ -20,16 +24,15 @@ stage=0 #### -# Description: -# Check if a UFW rule exists for a specific IP address and port. +# Check if a UFW rule exists for a specific IP address and port. # -# Arguments: +# PARAMETERS: # - $1: ip (Required) # - The IP address to check. # - $2: port (Required) # - The port to check. # -# Return: +# RETURN: # - 0: The rule exists. # - ?: The rule does not exist. ufw_rule_exists() { @@ -40,11 +43,10 @@ ufw_rule_exists() { } #### -# Description: -# Retrieves the rule number of all Cloudflare IP rules currently set in UFW, then -# stores them in an array. +# Retrieves the rule number of all Cloudflare IP rules currently set in UFW, then +# stores them in an array. # -# Arguments: +# PARAMETERS: # - $1: string_to_grep (Required) # - The string to grep for in the UFW status output. # - Acceptable values: @@ -69,9 +71,8 @@ get_set_cloudflare_rule_numbers() { } #### -# Description: -# Retrieves the IP addresses of all Cloudflare IP rules currently set in UFW, then -# stores them in an array. +# Retrieves the IP addresses of all Cloudflare IP rules currently set in UFW, then +# stores them in an array. get_set_cloudflare_ip_ranges() { while IFS= read -r line; do ip=$(echo "$line" | awk '{print $3}') # Extract the IP address. @@ -80,8 +81,7 @@ get_set_cloudflare_ip_ranges() { } #### -# Description: -# Set the new Cloudflare IP ranges in UFW, retrieved from the Cloudflare website. +# Set the new Cloudflare IP ranges in UFW, retrieved from the Cloudflare website. set_new_cloudflare_ip_ranges() { for ip in "${new_cloudflare_ip_ranges[@]}"; do ufw_rule_exists "$ip" "80,443" \ @@ -90,8 +90,7 @@ set_new_cloudflare_ip_ranges() { } #### -# Description: -# Restores the previous (non-new) Cloudflare IP ranges in UFW. +# Restores the previous (non-new) Cloudflare IP ranges in UFW. restore_current_cloudflare_ip_ranges() { for ip in "${current_cloudflare_ip_ranges[@]}"; do ufw_rule_exists "$ip" "80,443" \ @@ -100,8 +99,7 @@ restore_current_cloudflare_ip_ranges() { } #### -# Description: -# Deletes all Cloudflare IP rules currently set in UFW. +# Deletes all Cloudflare IP rules currently set in UFW. delete_set_cloudflare_rules() { get_set_cloudflare_rule_numbers "0" @@ -112,8 +110,7 @@ delete_set_cloudflare_rules() { } #### -# Description: -# Cleanup function to close ports 80 and 443 from any IP address. +# Cleanup function to close ports 80 and 443 from any IP address. cleanup() { case $stage in 2) From 55405d58fa6e6c19bb28599572c318574e7899bd Mon Sep 17 00:00:00 2001 From: "Hunter T." Date: Sat, 19 Oct 2024 11:52:49 -0700 Subject: [PATCH 7/7] Update tested Linux Distributions --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7439812..67b3464 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ A majority of the scripts will require root privilege to be executed: All of the scripts should work on most, if not all Linux Distributions. With that said, below is a list of Linux Distributions that the scripts have been officially tested and are confirmed to work on. -| Distributions | Distro Versions | -| ------------- | --------------- | -| Ubuntu | 22.04, 20.04 | -| Debian | 10, 9 | +| Distributions | Distro Versions | +| ------------- | ---------------------- | +| Ubuntu | 24.04, 22.04, 20.04 | +| Debian | 11, 10, 9 | ## Other Resources