Skip to content

Commit

Permalink
Merge pull request #18 from StrangeRanger/dev
Browse files Browse the repository at this point in the history
Small changes + new script (in beta/incomplete)
  • Loading branch information
StrangeRanger authored Oct 19, 2024
2 parents fdc8641 + 55405d5 commit 3e218dc
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 40 deletions.
9 changes: 0 additions & 9 deletions .deepsource.toml

This file was deleted.

10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
<!-- TODO: Add a list of all avaliable scripts and what they do. -->

## Getting Started

Expand All @@ -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

Expand Down
11 changes: 4 additions & 7 deletions auditing/Lynis Installer/lynis-installer.bash
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 1 addition & 4 deletions hardening/Root Locker/root-locker.bash
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
25 changes: 10 additions & 15 deletions hardening/SSHD Hardening/harden-sshd.bash
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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=(
Expand Down Expand Up @@ -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() {
Expand Down
208 changes: 208 additions & 0 deletions hardening/UFW Cloudflare/ufw-cloudflare.bash
100644 → 100755
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/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 ]################################################################


## 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 ]########################################################################


####
# Check if a UFW rule exists for a specific IP address and port.
#
# PARAMETERS:
# - $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}.*$"
}

####
# Retrieves the rule number of all Cloudflare IP rules currently set in UFW, then
# stores them in an array.
#
# PARAMETERS:
# - $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
)
}

####
# 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")
}

####
# 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
}

####
# 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
}

####
# 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
}

####
# 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."

0 comments on commit 3e218dc

Please sign in to comment.