Skip to content

Commit 3e218dc

Browse files
Merge pull request #18 from StrangeRanger/dev
Small changes + new script (in beta/incomplete)
2 parents fdc8641 + 55405d5 commit 3e218dc

File tree

6 files changed

+228
-40
lines changed

6 files changed

+228
-40
lines changed

.deepsource.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
This repository is a collection of scripts designed to secure/harden Linux based Distributions.
88

9-
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.
9+
<!-- TODO: Add a list of all avaliable scripts and what they do. -->
1010

1111
## Getting Started
1212

@@ -26,10 +26,10 @@ A majority of the scripts will require root privilege to be executed:
2626

2727
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.
2828

29-
| Distributions | Distro Versions |
30-
| ------------- | --------------- |
31-
| Ubuntu | 22.04, 20.04 |
32-
| Debian | 10, 9 |
29+
| Distributions | Distro Versions |
30+
| ------------- | ---------------------- |
31+
| Ubuntu | 24.04, 22.04, 20.04 |
32+
| Debian | 11, 10, 9 |
3333

3434
## Other Resources
3535

auditing/Lynis Installer/lynis-installer.bash

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
#!/bin/bash
22
#
3-
# Name: lynis-installer.bash
4-
#
5-
# Description:
6-
# This script downloads a security auditing tool called Lynis, designed to scan a
7-
# system and identify security issues, and provides recommendations on how to better
8-
# secure it. Lynis, unless an error is encountered, will always be downloaded to the
9-
# user's root directory (/home/USERNAME/).
3+
# This script downloads a security auditing tool called Lynis. It is designed to scan a
4+
# system, identify security issues, and provide recommendations on how to better secure
5+
# it. Unless an error is encountered, Lynis will always be downloaded to the current
6+
# user's root directory (`/home/USERNAME/`).
107
#
118
# Version: v1.0.7
129
# License: MIT License

hardening/Root Locker/root-locker.bash

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#!/bin/bash
22
#
3-
# Name: root-locker.bash
4-
#
5-
# Description:
6-
# This script locks the root account, preventing users from direct logins as root.
3+
# This script locks the root account, preventing users from directly logging in as root.
74
#
85
# Note:
96
# Locking the root account doesn't prevent users from using something like `sudo su`

hardening/SSHD Hardening/harden-sshd.bash

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
#!/bin/bash
22
#
3-
# Name: harden-sshd.bash
4-
#
5-
# Description:
6-
# This script hardens the sshd-server, by modifying it's configuration file
7-
# (sshd_config).
3+
# This script hardens the ssh server by modifying its configuration file, 'sshd_config'.
84
#
95
# Note:
10-
# This configures sshd_config to the recommendations of the security auditing tool
11-
# knonw as Lynis (https://github.com/CISOfy/lynis).
6+
# These configurations align with the recommendations of the security auditing tool
7+
# known as Lynis (https://github.com/CISOfy/lynis).
128
#
139
# Version: v2.0.0
1410
# License: MIT License
@@ -31,11 +27,11 @@ C_NC="$(printf '\033[0m')"
3127
readonly C_GREEN C_CYAN C_RED C_NC
3228

3329
## Short-hand colorized messages.
34-
C_SUCCESS="${C_GREEN}==>${C_NC} "
35-
C_WARNING="${C_YELLOW}==>${C_NC} "
36-
C_ERROR="${C_RED}ERROR:${C_NC} "
37-
C_INFO="${C_BLUE}==>${C_NC} "
38-
C_NOTE="${C_CYAN}==>${C_NC} "
30+
readonly C_SUCCESS="${C_GREEN}==>${C_NC} "
31+
readonly C_WARNING="${C_YELLOW}==>${C_NC} "
32+
readonly C_ERROR="${C_RED}ERROR:${C_NC} "
33+
readonly C_INFO="${C_BLUE}==>${C_NC} "
34+
readonly C_NOTE="${C_CYAN}==>${C_NC} "
3935

4036
# Associative array containing the configuration settings for sshd_config.
4137
declare -A C_SSHD_CONFIG=(
@@ -83,10 +79,9 @@ readonly C_SSHD_CONFIG
8379

8480

8581
####
86-
# Description:
87-
# Cleanly exit the script.
82+
# Cleanly exit the script.
8883
#
89-
# Arguments:
84+
# PARAMETERS:
9085
# - $1: exit_code (Required)
9186
# - The exit code to exit the script with.
9287
clean_exit() {

hardening/UFW Cloudflare/ufw-cloudflare.bash

100644100755
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#!/bin/bash
2+
#
3+
# Sets up UFW to only allow HTTP and HTTPS traffic from Cloudflare's IP ranges.
4+
#
5+
# Version: v1.0.0-beta.1
6+
# License: MIT License
7+
# Copyright (c) 2024 Hunter T. (StrangeRanger)
8+
#
9+
########################################################################################
10+
####[ Global Variables ]################################################################
11+
12+
13+
## URL for retrieving the current Cloudflare IP ranges.
14+
readonly C_CLOUDFLARE_IPV4_RANGES_URL="https://www.cloudflare.com/ips-v4/"
15+
readonly C_CLOUDFLARE_IPV6_RANGES_URL="https://www.cloudflare.com/ips-v6/"
16+
17+
current_cloudflare_rule_numbers=()
18+
current_cloudflare_ip_ranges=()
19+
new_cloudflare_ip_ranges=()
20+
stage=0
21+
22+
23+
####[ Function ]########################################################################
24+
25+
26+
####
27+
# Check if a UFW rule exists for a specific IP address and port.
28+
#
29+
# PARAMETERS:
30+
# - $1: ip (Required)
31+
# - The IP address to check.
32+
# - $2: port (Required)
33+
# - The port to check.
34+
#
35+
# RETURN:
36+
# - 0: The rule exists.
37+
# - ?: The rule does not exist.
38+
ufw_rule_exists() {
39+
local ip="$1"
40+
local port="$2"
41+
42+
ufw status | grep -qE "^${port}.*ALLOW.*${ip}.*$"
43+
}
44+
45+
####
46+
# Retrieves the rule number of all Cloudflare IP rules currently set in UFW, then
47+
# stores them in an array.
48+
#
49+
# PARAMETERS:
50+
# - $1: string_to_grep (Required)
51+
# - The string to grep for in the UFW status output.
52+
# - Acceptable values:
53+
# - 0: "Cloudflare IP"
54+
# - 1: "Temporary rule"
55+
get_set_cloudflare_rule_numbers() {
56+
if (( $1 == 0 )); then
57+
local string_to_grep="Cloudflare IP"
58+
elif (( $1 == 1 )); then
59+
local string_to_grep="Temporary rule"
60+
else
61+
echo "Invalid argument: $1"
62+
exit 1
63+
fi
64+
65+
mapfile -t current_cloudflare_rule_numbers < <(
66+
ufw status numbered \
67+
| grep "$string_to_grep" \
68+
| awk -F'[][]' '{print $2}' \
69+
| sort -rn
70+
)
71+
}
72+
73+
####
74+
# Retrieves the IP addresses of all Cloudflare IP rules currently set in UFW, then
75+
# stores them in an array.
76+
get_set_cloudflare_ip_ranges() {
77+
while IFS= read -r line; do
78+
ip=$(echo "$line" | awk '{print $3}') # Extract the IP address.
79+
current_cloudflare_ip_ranges+=("$ip")
80+
done < <(sudo ufw status | grep "Cloudflare IP")
81+
}
82+
83+
####
84+
# Set the new Cloudflare IP ranges in UFW, retrieved from the Cloudflare website.
85+
set_new_cloudflare_ip_ranges() {
86+
for ip in "${new_cloudflare_ip_ranges[@]}"; do
87+
ufw_rule_exists "$ip" "80,443" \
88+
|| ufw allow from "$ip" to any port 80,443 proto tcp comment "Cloudflare IP"
89+
done
90+
}
91+
92+
####
93+
# Restores the previous (non-new) Cloudflare IP ranges in UFW.
94+
restore_current_cloudflare_ip_ranges() {
95+
for ip in "${current_cloudflare_ip_ranges[@]}"; do
96+
ufw_rule_exists "$ip" "80,443" \
97+
|| ufw allow from "$ip" to any port 80,443 proto tcp comment "Cloudflare IP"
98+
done
99+
}
100+
101+
####
102+
# Deletes all Cloudflare IP rules currently set in UFW.
103+
delete_set_cloudflare_rules() {
104+
get_set_cloudflare_rule_numbers "0"
105+
106+
for rule_num in "${current_cloudflare_rule_numbers[@]}"; do
107+
# TODO: Add configuration option to confirm deletion.
108+
yes | ufw delete "$rule_num"
109+
done
110+
}
111+
112+
####
113+
# Cleanup function to close ports 80 and 443 from any IP address.
114+
cleanup() {
115+
case $stage in
116+
2)
117+
delete_set_cloudflare_rules "1"
118+
;;
119+
3)
120+
echo "Potential error or interruption detected."
121+
echo "Restoring the previous Cloudflare IP ranges..."
122+
restore_current_cloudflare_ip_ranges
123+
delete_set_cloudflare_rules "1"
124+
;;
125+
4)
126+
echo "Potential error or interruption detected."
127+
echo "Restoring the previous Cloudflare IP ranges..."
128+
delete_new_cloudflare_ip_ranges
129+
restore_current_cloudflare_ip_ranges
130+
delete_set_cloudflare_rules "1"
131+
;;
132+
5)
133+
# Continue, as we are too far along to realistically undo anything
134+
;;
135+
*)
136+
echo "Invalid stage: $stage"
137+
;;
138+
esac
139+
}
140+
141+
142+
####[ Trap Logic ]######################################################################
143+
144+
145+
trap cleanup EXIT
146+
147+
148+
####[ Main ]############################################################################
149+
150+
151+
###
152+
### [ Initial Setup ]
153+
###
154+
155+
stage=1
156+
157+
get_set_cloudflare_ip_ranges
158+
mapfile -t new_cloudflare_ip_ranges < <(curl -s "$C_CLOUDFLARE_IPV4_RANGES_URL")
159+
mapfile -t new_cloudflare_ipv6_ranges < <(curl -s "$C_CLOUDFLARE_IPV6_RANGES_URL")
160+
161+
new_cloudflare_ip_ranges+=("${new_cloudflare_ipv6_ranges[@]}")
162+
unset new_cloudflare_ipv6_ranges
163+
164+
###
165+
### [ Opening ports 80 and 443 from any IP address ]
166+
###
167+
168+
stage=2
169+
170+
echo "Temporarily opening ports 80 and 443 from any IP address..."
171+
ufw allow from any to any port 80,443 proto tcp comment "Temporary rule"
172+
sleep 1 # Wait for the rule to take effect.
173+
174+
###
175+
### [ Removing the existing Cloudflare IP ranges ]
176+
###
177+
178+
stage=3
179+
180+
if (( ${#current_cloudflare_ip_ranges[@]} != 0 )); then
181+
echo "Removing the existing Cloudflare IP ranges..."
182+
delete_set_cloudflare_rules
183+
fi
184+
185+
sleep 1 # Wait for the rule to take effect.
186+
187+
###
188+
### [ Adding the new Cloudflare IP ranges ]
189+
###
190+
191+
stage=4
192+
193+
echo "Adding the new Cloudflare IPv4 and IPv6 ranges..."
194+
set_new_cloudflare_ip_ranges
195+
sleep 1 # Wait for the rule to take effect.
196+
197+
###
198+
### [ Finalizing ]
199+
###
200+
201+
stage=5
202+
203+
echo "Removing temporary rules..."
204+
ufw delete allow from any to any port 80,443 proto tcp
205+
sleep 1 # Wait for the rule to take effect.
206+
207+
echo "Done."
208+

0 commit comments

Comments
 (0)