更换SSH端口

Page content

怎么会有人这么无聊啊

SSH login failed too many times

手动档

更换方法:

  1. 打开 /etc/ssh/sshd_config 把里面的 Port 22 换成你想要的端口,如果前面有注释符号 # 的话就把注释符号去掉。
  2. systemctl restart sshd

自动档

现学现卖环节
运行这个我写的“一键脚本”也可以帮你“一键”把 SSH 端口更换到 30022.

#!/bin/bash

if [ ! $(id -u) -eq 0 ]; then
  echo "You should run this script as root."
  exit 1
fi

grep "#Port 22" /etc/ssh/sshd_config > /dev/null
case $? in
0)
  sed -i 's/#Port\ 22/Port\ 30022/g' /etc/ssh/sshd_config
  ;;
1)
  sed -i 's/Port\ [0-9]*/Port\ 30022/g' /etc/ssh/sshd_config
  ;;
*)
  exit 1
esac

systemctl restart sshd

emmmmmmm
让我们来叫GPT老师来评价一下这段代码(((

GPT老师说:

这是一个用于修改 SSH 端口的脚本。它首先检查脚本是否以 root 用户运行,如果不是就会提示用户需要以 root 身份运行并退出脚本。然后它检查 /etc/ssh/sshd_config 文件中是否有 “#Port 22” 这一行。如果有,就将其替换为 “Port 30022”;如果没有,就查找匹配正则表达式 “Port [0-9]*” 的行,并将其替换为 “Port 30022”。最后,脚本重新启动 sshd 服务。
这个脚本的代码写得比较好,它使用了 shell 的基本结构(if、case 和命令行重定向),并使用了 sed 命令来执行文本替换。但是,我发现几个可以改进的地方:

  1. 使用带引号的字符串更好:在 sed 命令中使用的正则表达式 ’s/#Port\ 22/Port\ 30022/g’ 和 ’s/Port\ [0-9]*/Port\ 30022/g’ 中的转义字符 ’’ 可以省略,并使用单引号或双引号括起来。
  2. 加入注释:虽然这个脚本的功能已经很明确了,但是还是建议加入一些注释,以便更好地理解代码的意图。
  3. 使用更严谨的条件判断:脚本中的 if 语句使用的是 [ ! $(id -u) -eq 0 ],但是这个条件判断可以写得更严谨一点。可以将其改写成:
if [[ $(id -u) -ne 0 ]]; then
  echo "You should run this script as root."
  exit 1
fi
  1. 加入错误处理:脚本在执行 sed 命令时,如果发生了错误,可以使用 set -e 来使脚本立即退出。例如,可以在脚本开头加入 set -e 语句,然后在每个 sed 命令之前加入 set +e 和 set -e 语句,来在执行 sed 命令时临时忽略错误,并在执行完成后恢复错误处理。
  2. 使用变量:可以使用变量来存储新的端口号,以便更方便地修改端口号。例如:
new_port=30022
sed -i "s/#Port\ 22/Port\ ${new_port}/g" /etc/ssh/sshd_config
sed -i "s/Port\ [0-9]*/Port\ ${new_port}/g" /etc/ssh/sshd_config

总的来说,这个脚本是个不错的例子,但是还有一些可以改进的地方。

GPT老师说得很有道理,那么就按照GPT的建议来改进一下这个脚本吧!


请看 SSH port modifier v2.0
*为了不影响实际生产环境,我把 sshd_config 复制了一份用于测试,所以路径有所变更。

#!/bin/bash

new_port=30022
sshd_config_path="/root/sshd_config"
set -e

if [ $(id -u) -ne 0 ]; then
  echo "You should run this script as root."
  exit 1
fi

grep "#Port 22" sshd_config > /dev/null
case $? in
0)
  set +e
  sed -i "s/#Port\ 22/Port\ ${new_port}/g" ${sshd_config_path}
  set -e
  ;;
1)
  set +e
  sed -i "s/Port\ [0-9]*/Port\ ${new_port}/g" ${sshd_config_path}
  set -e
  ;;
*)
  echo "Unexpected error occurred."
  exit 1
esac

systemctl restart sshd

好,现在就来测试一下这个按照GPT老师建议修改后的脚本

[root@ifrit ~]# cat sshd_config | grep "^Port"
Port 12450

可见目前的 SSH 端口为 12450.
那么现在就运行一下这个脚本,把 SSH 端口修改为 30022.

[root@ifrit ~]# ./2.sh 
[root@ifrit ~]# cat sshd_config | grep "^Port"
Port 12450

咦?怎么 Port 12450 没有被替换掉的呢?

经过排查,原来是GPT生成的代码有点毛病。

set +eset -e 是 Shell 中内置的指令,是用来控制 shell script 在遇到错误时候的行为。
set -e 的场合下,如果上一条指令执行失败, script 会马上退出。
set +e 的场合下,如果上一条指令执行失败, script 会忽略错误,继续执行吓一跳指令。

换句话说,就是在 set -e 模式下当 $? -ne 0 的时候,script就会马上退出。

欸? $? 这个变数看起来怎么有点眼熟,,,,,,

在代码中,我用了 $? 来判断了 sshd 配置文件中有没有包含 #Port 22 这个字段。
也就是说,如果设置了 set -e 的话,如果 sshd 配置文件中没有包含#Port 22,整个脚本就会马上退出。

GPT生成的代码也不是很靠谱嘛
不对不对,为什么我会觉得GPT生成的代码会靠谱


修正了前文所述的一些错误
这是 SSH port modifier 终极版

#!/bin/bash

new_port=30022
sshd_config_path="/etc/ssh/sshd_config"

if [ $(id -u) -ne 0 ]; then
  echo "You should run this script as root."
  exit 1
fi

grep "#Port 22" sshd_config > /dev/null
case $? in
0)
  sed -i "s/#Port\ 22/Port\ ${new_port}/g" ${sshd_config_path}
  ;;
1)
  sed -i "s/Port\ [0-9]*/Port\ ${new_port}/g" ${sshd_config_path}
  ;;
*)
  echo "Unexpected error occurred."
  exit 1
esac

systemctl restart sshd

好,这下总算是没毛病。