Disable ssh root login by modifying /etc/ssh/sshd_conf from within a script? Disable ssh root login by modifying /etc/ssh/sshd_conf from within a script? shell shell

Disable ssh root login by modifying /etc/ssh/sshd_conf from within a script?


Script:

$ sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config

Then:

$ service ssh reload


You can do something like that

#!/bin/bashif [[ "${UID}" -ne 0 ]]; then    echo " You need to run this script as root"    exit 1fi#To directly modify sshd_config.sed -i 's/#\?\(Port\s*\).*$/\1 2231/' /etc/ssh/sshd_configsed -i 's/#\?\(PerminRootLogin\s*\).*$/\1 no/' /etc/ssh/sshd_configsed -i 's/#\?\(PubkeyAuthentication\s*\).*$/\1 yes/' /etc/ssh/sshd_configsed -i 's/#\?\(PermitEmptyPasswords\s*\).*$/\1 no/' /etc/ssh/sshd_configsed -i 's/#\?\(PasswordAuthentication\s*\).*$/\1 no/' /etc/ssh/sshd_config#Check the exit status of the last commandif [[ "${?}" -ne 0 ]]; then   echo "The sshd_config file was not modified successfully"   exit 1fi/etc/init.d/ssh restartexit 0


Configuring SSH programmatically

I did some investigation on this and I think JNevevill's answer is the most solid. I have some example script that illustrated the two ways, SED and AWK.

Preparation

Showing the test data only once for better readability in the examples. It has been initialized for each approach the same way. It will define some rules in a test file and a dictionary of new rules that should replace the rules in the file or be written to the file.

echo 'LoginGraceTime 120' > ./data.txtecho '#PermitRootLogin yes' >> ./data.txtecho 'PermitRootLogin no' >> ./data.txtecho 'PasswordAuthentication yes' >> ./data.txtdeclare -A rules=(     ["LoginGraceTime"]="1m"    ["PermitRootLogin"]="no"    ["PasswordAuthentication"]="no"    ["AllowUsers"]="blue")

SED

SED will replace the rules it finds. If a line is commented, it will remove the #and replace the value. This approach is less solid as it can lead to duplicate rules. I.E. A rule exists commented and uncommented. Also, if the rule wasn't there, it will not be written at all.

for rule in "${!rules[@]}"; do  regex="s/#\?\(${rule}\s*\).*$/\1 ${rules[${rule}]}/"  sed "${regex}" ./data.txt > temp.txt;  mv -f temp.txt ./data.txtdone

Result:

LoginGraceTime  1mPermitRootLogin  noPermitRootLogin  noPasswordAuthentication  no

AWK

AWK is more solid in this situation. It yields better control.It will read line by line and replace the value if it exists without changing commented rules. If a rule wasn't found at the end of the file, it will append this rule to the file. This is much more solid than the SED approach. We can be sure there will be not duplicate rule and all rules are defined.

for rule in "${!rules[@]}"; doawk -v key="${rule}" -v val="${rules[${rule}]}" \  '$1==key {foundLine=1; print key " " val} $1!=key{print $0} END{if(foundLine!=1) print key " " val}' \  ./data.txt > sshd_config.tmp && mv sshd_config.tmp ./data.txtdone

Result:

LoginGraceTime 1m#PermitRootLogin yesPermitRootLogin noPasswordAuthentication noAllowUsers blue

Conclusion

AWK is clearly the better choice. It is more safe and can handle rules that are not in the file.