11#! /bin/bash
22#
3- # Hardens sshd by modifying '/etc/ssh/sshd_config'.
3+ # Hardens sshd by modifying the configurations of '/etc/ssh/sshd_config'.
44#
55# Note: This configures sshd_config to the recommendations of the security auditing tool
66# knonw as Lynis (https://github.com/CISOfy/lynis).
77#
8- # Version: v1.0.3
8+ # Version: v1.1.0
99# License: MIT License
10- # Copyright (c) 2020-2021 Hunter T.
10+ # Copyright (c) 2020-2022 Hunter T. (StrangeRanger)
1111#
1212# #######################################################################################
1313# ### [ Variables ]
1414
1515
1616config_file_bak=" /etc/ssh/sshd_config.bak"
1717config_file=" /etc/ssh/sshd_config"
18+ green=$' \033 [0;32m'
1819cyan=$' \033 [0;36m'
1920red=$' \033 [1;31m'
2021nc=$' \033 [0m'
@@ -29,15 +30,15 @@ nc=$'\033[0m'
2930if [[ $EUID != 0 ]]; then
3031 echo " ${red} Please run this script as or with root privilege$nc " >&2
3132 echo -e " \nExiting..."
32- exit 1
33+ exit 2
3334fi
3435
3536# # Confirm that 'sshd_config' exists.
3637if [[ ! -f $config_file ]]; then
3738 echo " ${red} 'sshd_config' doesn't exist" >&2
38- echo " ${cyan} sshd -server may not be installed$nc "
39+ echo " ${cyan} openssh -server may not be installed$nc "
3940 echo -e " \nExiting..."
40- exit 1
41+ exit 3
4142fi
4243
4344
4849
4950read -rp " We will now harden sshd. Press [Enter] to continue."
5051
51- # # Backup 'sshd_config' if 'sshd_config.bak' doesn't already exist.
52- if [[ ! -f $config_file_bak ]]; then
53- echo " Backing up original 'sshd_config'..."
52+ if [[ -f $config_file_bak ]]; then
53+ printf " A backup of 'sshd_config' already exists. "
54+ read -rp " Do you want to overwrite it? [y/N] " choice
55+
56+ choice=$( echo " $choice " | tr ' [:upper:]' ' [:lower:]' )
57+ case " $choice " in
58+ y|yes)
59+ echo " Overwriting backup of 'sshd_config'..."
60+ rm $config_file_bak && cp $config_file $config_file_bak || {
61+ echo " ${red} Failed to back up sshd_config" >&2
62+ echo " ${cyan} Please create a backup of the original 'sshd_config'" \
63+ " before continuing$nc "
64+ exit 1
65+ }
66+ ;;
67+ esac
68+ else
69+ echo " Backing up 'sshd_config'..."
5470 cp $config_file $config_file_bak || {
5571 echo " ${red} Failed to back up sshd_config" >&2
56- echo " ${cyan} Please create a backup of the original 'sshd_config'" \
57- " before continuing$nc "
72+ echo " ${cyan} Please create a backup of the original 'sshd_config' before " \
73+ " continuing$nc "
5874 exit 1
5975 }
6076fi
6177
62- echo " Setting LogLevel VERBOSE..."
63- sed -i ' s/\(#\)\?LogLevel\(.*\)\?/LogLevel VERBOSE/g' " $config_file " \
64- || echo " ${red} Failed to set LogLevel VERBOSE$nc "
78+ if grep -Eq ' ^LogLevel VERBOSE$' " $config_file " ; then
79+ echo " LogLevel already set to 'VERBOSE'"
80+ elif grep -Eq ' ^#?LogLevel(.*)?$' " $config_file " ; then
81+ echo " Setting 'LogLevel VERBOSE'..."
82+ sed -Ei ' s/^#?LogLevel(.*)?$/LogLevel VERBOSE/gm' " $config_file " \
83+ || echo " ${red} Failed to set 'LogLevel VERBOSE'$nc "
84+ fi
6585
66- echo " Setting LoginGraceTime 30..."
67- sed -i ' s/\(#\)\?LoginGraceTime\(.*\)\?/LoginGraceTime 30/g' " $config_file " \
68- || echo " ${red} Failed to set LoginGraceTime 30$nc "
86+ if grep -Eq ' ^LoginGraceTime 30$' " $config_file " ; then
87+ echo " LoginGraceTime already set to '30'"
88+ elif grep -Eq ' ^#?LoginGraceTime(.*)?$' " $config_file " ; then
89+ echo " Setting 'LoginGraceTime 30'..."
90+ sed -Ei ' s/^#?LoginGraceTime(.*)?$/LoginGraceTime 30/gm' " $config_file " \
91+ || echo " ${red} Failed to set 'LoginGraceTime 30'$nc "
92+ fi
6993
70- echo " Setting PermitRootLogin no..."
71- sed -i ' s/\(#\)\?PermitRootLogin\(.*\)\?/PermitRootLogin no/g' " $config_file " \
72- || echo " ${red} Failed to set PermitRootLogin no$nc "
94+ if grep -Eq ' ^PermitRootLogin no$' " $config_file " ; then
95+ echo " PermitRootLogin already set to 'no'"
96+ elif grep -Eq ' ^#?PermitRootLogin(.*)?$' " $config_file " ; then
97+ echo " Setting 'PermitRootLogin no'..."
98+ sed -Ei ' s/^#?PermitRootLogin(.*)?$/PermitRootLogin no/gm' " $config_file " \
99+ || echo " ${red} Failed to set 'PermitRootLogin no'$nc "
100+ fi
73101
74- echo " Setting MaxAuthTries 3..."
75- sed -i ' s/\(#\)\?MaxAuthTries\(.*\)\?/MaxAuthTries 3/g' " $config_file " \
76- || echo " ${red} Failed to set MaxAuthTries 3$nc "
102+ if grep -Eq ' ^MaxAuthTries 3$' " $config_file " ; then
103+ echo " MaxAuthTries already set to '3'"
104+ elif grep -Eq ' ^#?MaxAuthTries(.*)?$' " $config_file " ; then
105+ echo " Setting 'MaxAuthTries 3'..."
106+ sed -Ei ' s/^#?MaxAuthTries(.*)?$/MaxAuthTries 3/gm' " $config_file " \
107+ || echo " ${red} Failed to set 'MaxAuthTries 3'$nc "
108+ fi
77109
78- echo " Setting MaxSessions 2..."
79- sed -i ' s/\(#\)\?MaxSessions\(.*\)\?/MaxSessions 2/g' " $config_file " \
80- || echo " ${red} Failed to set MaxSessions 2$nc "
110+ if grep -Eq ' ^MaxSessions 2$' " $config_file " ; then
111+ echo " MaxSessions already set to '2'"
112+ elif grep -Eq ' ^#?MaxSessions(.*)?$' " $config_file " ; then
113+ echo " Setting 'MaxSessions 2'..."
114+ sed -Ei ' s/^#?MaxSessions(.*)?$/MaxSessions 2/gm' " $config_file " \
115+ || echo " ${red} Failed to set 'MaxSessions 2'$nc "
116+ fi
81117
82- echo " Setting PubkeyAuthentication yes..."
83- sed -i ' s/\(#\)\?PubkeyAuthentication\(.*\)\?/PubkeyAuthentication yes/g' " $config_file " \
84- || echo " ${red} Failed to set PubkeyAuthentication yes$nc "
118+ if grep -Eq ' ^PubkeyAuthentication yes$' " $config_file " ; then
119+ echo " PubkeyAuthentication already set to 'yes'"
120+ elif grep -Eq ' ^#?PubkeyAuthentication(.*)?$' " $config_file " ; then
121+ echo " Setting 'PubkeyAuthentication yes'..."
122+ sed -Ei ' s/^#?PubkeyAuthentication(.*)?$/PubkeyAuthentication yes/gm' " $config_file " \
123+ || echo " ${red} Failed to set 'PubkeyAuthentication yes'$nc "
124+ fi
85125
86- # Uncomment only if an ssh key has been set
87- # echo "Setting PasswordAuthentication no..."
88- # sed -i 's/\(#\)\?PasswordAuthentication\(.*\)\?/PasswordAuthentication no/g' "$config_file" \
89- # || echo "${red}Failed to set PasswordAuthentication no$nc"
126+ if grep -Eq ' ^PermitEmptyPasswords no$' " $config_file " ; then
127+ echo " PermitEmptyPasswords already set to 'no'"
128+ elif grep -Eq ' ^#?PermitEmptyPasswords(.*)?$' " $config_file " ; then
129+ echo " Setting 'PermitEmptyPasswords no'..."
130+ sed -Ei ' s/^#?PermitEmptyPasswords(.*)?$/PermitEmptyPasswords no/gm' " $config_file " \
131+ || echo " ${red} Failed to set 'PermitEmptyPasswords no'$nc "
132+ fi
90133
91- echo " Setting PermitEmptyPasswords no..."
92- sed -i ' s/\(#\)\?PermitEmptyPasswords\(.*\)\?/PermitEmptyPasswords no/g' " $config_file " \
93- || echo " ${red} Failed to set PermitEmptyPasswords no$nc "
134+ if grep -Eq ' ^ChallengeResponseAuthentication no$' " $config_file " ; then
135+ echo " ChallengeResponseAuthentication already set to 'no'"
136+ elif grep -Eq ' ^#?ChallengeResponseAuthentication(.*)?$' " $config_file " ; then
137+ echo " Setting 'ChallengeResponseAuthentication no'..."
138+ sed -Ei ' s/^#?ChallengeResponseAuthentication(.*)?$/ChallengeResponseAuthentication no/gm' " $config_file " \
139+ || echo " ${red} Failed to set 'ChallengeResponseAuthentication no'$nc "
140+ fi
94141
95- echo " Setting ChallengeResponseAuthentication no..."
96- sed -i ' s/\(#\)\?ChallengeResponseAuthentication\(.*\)\?/ChallengeResponseAuthentication no/g' \
97- " $config_file " \ || echo " ${red} Failed to set ChallengeResponseAuthentication no$nc "
142+ if grep -Eq ' ^KbdInteractiveAuthentication no$' " $config_file " ; then
143+ echo " KbdInteractiveAuthentication already set to 'no'"
144+ elif grep -Eq ' ^#?KbdInteractiveAuthentication(.*)?$' " $config_file " ; then
145+ echo " Setting 'KbdInteractiveAuthentication no'..."
146+ sed -Ei ' s/^#?KbdInteractiveAuthentication(.*)?$/KbdInteractiveAuthentication no/gm' " $config_file " \
147+ || echo " ${red} Failed to set 'KbdInteractiveAuthentication no'$nc "
148+ fi
98149
99- echo " Setting UsePAM yes..."
100- sed -i ' s/\(#\)\?UsePAM\(.*\)\?/UsePAM yes/g' " $config_file " \
101- || echo " ${red} Failed to set UsePAM yes$nc "
150+ if grep -Eq ' ^UsePAM yes$' " $config_file " ; then
151+ echo " UsePAM already set to 'yes'"
152+ elif grep -Eq ' ^#?UsePAM(.*)?$' " $config_file " ; then
153+ echo " Setting 'UsePAM yes'..."
154+ sed -Ei ' s/^#?UsePAM(.*)?$/UsePAM yes/gm' " $config_file " \
155+ || echo " ${red} Failed to set 'UsePAM yes'$nc "
156+ fi
102157
103- echo " Setting AllowAgentForwarding no..."
104- sed -i ' s/\(#\)\?AllowAgentForwarding\(.*\)\?/AllowAgentForwarding no/g' " $config_file " \
105- || echo " ${red} Failed to set AllowAgentForwarding no$nc "
158+ if grep -Eq ' ^AllowAgentForwarding no$' " $config_file " ; then
159+ echo " AllowAgentForwarding already set to 'no'"
160+ elif grep -Eq ' ^#?AllowAgentForwarding(.*)?$' " $config_file " ; then
161+ echo " Setting 'AllowAgentForwarding no'..."
162+ sed -Ei ' s/^#?AllowAgentForwarding(.*)?$/AllowAgentForwarding no/gm' " $config_file " \
163+ || echo " ${red} Failed to set 'AllowAgentForwarding no'$nc "
164+ fi
106165
107- echo " Setting AllowTcpForwarding no..."
108- sed -i ' s/\(#\)\?AllowTcpForwarding\(.*\)\?/AllowTcpForwarding no/g' " $config_file " \
109- || echo " ${red} Failed to set AllowTcpForwarding no$nc "
166+ if grep -Eq ' ^AllowTcpForwarding no$' " $config_file " ; then
167+ echo " AllowTcpForwarding already set to 'no'"
168+ elif grep -Eq ' ^#?AllowTcpForwarding(.*)?$' " $config_file " ; then
169+ echo " Setting 'AllowTcpForwarding no'..."
170+ sed -Ei ' s/^#?AllowTcpForwarding(.*)?$/AllowTcpForwarding no/gm' " $config_file " \
171+ || echo " ${red} Failed to set 'AllowTcpForwarding no'$nc "
172+ fi
110173
111- echo " Setting X11Forwarding no..."
112- sed -i ' s/\(#\)\?X11Forwarding\(.*\)\?/X11Forwarding no/g' " $config_file " \
113- || echo " ${red} Failed to set X11Forwarding no$nc "
174+ if grep -Eq ' ^X11Forwarding no$' " $config_file " ; then
175+ echo " X11Forwarding already set to 'no'"
176+ elif grep -Eq ' ^#?X11Forwarding(.*)?$' " $config_file " ; then
177+ echo " Setting 'X11Forwarding no'..."
178+ sed -Ei ' s/^#?X11Forwarding(.*)?$/X11Forwarding no/gm' " $config_file " \
179+ || echo " ${red} Failed to set 'X11Forwarding no'$nc "
180+ fi
114181
115- echo " Setting PrintMotd no..."
116- sed -i ' s/\(#\)\?PrintMotd\(.*\)\?/PrintMotd no/g' " $config_file " \
117- || echo " ${red} Failed to set PrintMotd no$nc "
182+ if grep -Eq ' ^PrintMotd no$' " $config_file " ; then
183+ echo " PrintMotd already set to 'no'"
184+ elif grep -Eq ' ^#?PrintMotd(.*)?$' " $config_file " ; then
185+ echo " Setting 'PrintMotd no'..."
186+ sed -Ei ' s/^#?PrintMotd(.*)?$/PrintMotd no/gm' " $config_file " \
187+ || echo " ${red} Failed to set 'PrintMotd no'$nc "
188+ fi
118189
119- echo " Setting TCPKeepAlive no..."
120- sed -i ' s/\(#\)\?TCPKeepAlive\(.*\)\?/TCPKeepAlive no/g' " $config_file " \
121- || echo " ${red} Failed to set TCPKeepAlive no$nc "
190+ if grep -Eq ' ^TCPKeepAlive no$' " $config_file " ; then
191+ echo " TCPKeepAlive already set to 'no'"
192+ elif grep -Eq ' ^#?TCPKeepAlive(.*)?$' " $config_file " ; then
193+ echo " Setting 'TCPKeepAlive no'..."
194+ sed -Ei ' s/^#?TCPKeepAlive(.*)?$/TCPKeepAlive no/gm' " $config_file " \
195+ || echo " ${red} Failed to set 'TCPKeepAlive no'$nc "
196+ fi
122197
123- echo " Setting Compression no..."
124- sed -i ' s/\(#\)\?Compression\(.*\)\?/Compression no/g' " $config_file " \
125- || echo " ${red} Failed to set Compression no$nc "
198+ if grep -Eq ' ^Compression no$' " $config_file " ; then
199+ echo " Compression already set to 'no'"
200+ elif grep -Eq ' ^#?Compression(.*)?$' " $config_file " ; then
201+ echo " Setting 'Compression no'..."
202+ sed -Ei ' s/^#?Compression(.*)?$/Compression no/gm' " $config_file " \
203+ || echo " ${red} Failed to set 'Compression no'$nc "
204+ fi
126205
127- echo " Setting ClientAliveInterval 300..."
128- sed -i ' s/\(#\)\?ClientAliveInterval\(.*\)\?/ClientAliveInterval 300/g' " $config_file " \
129- || echo " ${red} Failed to set ClientAliveInterval 30$nc "
206+ if grep -Eq ' ^ClientAliveInterval 300$' " $config_file " ; then
207+ echo " ClientAliveInterval already set to '300'"
208+ elif grep -Eq ' ^#?ClientAliveInterval(.*)?$' " $config_file " ; then
209+ echo " Setting 'ClientAliveInterval 300'..."
210+ sed -Ei ' s/^#?ClientAliveInterval(.*)?$/ClientAliveInterval 300/gm' " $config_file " \
211+ || echo " ${red} Failed to set 'ClientAliveInterval 300'$nc "
212+ fi
130213
131- echo " Setting ClientAliveCountMax 2..."
132- sed -i ' s/\(#\)\?ClientAliveCountMax\(.*\)\?/ClientAliveCountMax 2/g' " $config_file " \
133- || echo " ${red} Failed to set ClientAliveCountMax 2$nc "
214+ if grep -Eq ' ^ClientAliveCountMax 2$' " $config_file " ; then
215+ echo " UseClientAliveCountMaxPAM already set to '2'"
216+ elif grep -Eq ' ^#?ClientAliveCountMax(.*)?$' " $config_file " ; then
217+ echo " Setting 'ClientAliveCountMax 2'..."
218+ sed -Ei ' s/^#?ClientAliveCountMax(.*)?$/ClientAliveCountMax 2/gm' " $config_file " \
219+ || echo " ${red} Failed to set 'ClientAliveCountMax 2'$nc "
220+ fi
134221
135222echo -e " \nRestarting sshd..."
136223systemctl restart sshd
137224
138- echo -e " \nDone"
139- echo -e " ${cyan} NOTE: It is highly recommended to manually:\n1) Change sshd default" \
140- " port (22) to something else\n2) Add 'AllowUsers [your username]' to the bottom" \
141- " of 'sshd_config'$nc "
225+ echo -e " \n${green} Finished hardening sshd"
226+ echo -e " ${cyan} It is highly recommended to manually:
227+ 1) Change the default sshd port (22)
228+ 2) Disable PasswordAuthentication in favor of PubkeyAuthentication
229+ 3) Add 'AllowUsers [your username]' to the bottom of 'sshd_config'$nc "
142230
143231
144232# ### End of [ Main ]
0 commit comments