linux firewalld 查看防火墙规则

CentOS7使用firewall-cmd打开关闭防火墙与端口 以开放8080端口为例

CENTOS7中FIREWALL防火墙


IpTables

基于Centos6 及以下版本

允许特定IP访问SSH端口

-I:表示在头部(大写的i),
-A:表示追加到底部

/sbin/iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100/32 -j ACCEPT

拒绝其他IP访问SSH端口

危险:将导致拒绝所有其他ip地址访问22端口(已中招!!呆逼…自述)

/sbin/iptables -A INPUT -p tcp –dport 22 -j DROP

查看验证

service iptables save && service iptables restart 

删除防火墙规则

iptables -L -n --line-number
iptables -D INPUT 3 #删除INPUT的第三条已添加规则,这里3代表第几行规则

查看防火墙规则配置文件

cat /etc/sysconfig/iptables

统计防火墙已配置规则

ACCEPT: 表示以ACCEPT开头的记录行

iptables -L | grep -E '^ACCEPT' | wc -l

防火墙是否开启

service iptables status;

没有开启则输出:iptables: Firewall is not running. 【注意:并不代表所以情况均如此!!!】-> 见下文


Firewalld

基于Centos7及以上版本

Firewalld

允许特定IP访问SSH端口

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100/32" port protocol="tcp" port="22" accept'

拒绝其他IP访问SSH端口

危险:将导致拒绝所有其他ip地址访问22端口(已中招!!呆逼…自述)

sudo firewall-cmd –permanent –add-rich-rule=’rule family=”ipv4” source address=”0.0.0.0/0” port protocol=”tcp” port=”22” reject’

重载规则

firewall-cmd --reload

查看规则

firewall-cmd --list-all

删除规则

firewall-cmd --permanent --remove-rich-rule '要删除的防火墙规则'

示例:firewall-cmd --permanent --remove-rich-rule 'rule family="ipv4" source address="xx.xxx.5.1/32" port port="22" protocol="tcp" accept'

查看防火墙规则配置文件

cat /etc/firewalld/zones/public.xml

掩码:知识补充

CIDR(Classless Inter-Domain Routing)表示法中的掩码格式用于指定IP地址范围。下面是常见的CIDR表示法:

/0:表示全范围,即0.0.0.0/0,它匹配所有可能的IP地址,相当于没有过滤,因为子网掩码为0时,IP地址的每一位都是可变的。

/32:表示单个IP地址,例如192.168.1.1/32,它匹配一个特定的IP地址,因为子网掩码为32时,IP地址的每一位都是固定的。

/24:表示一个子网,例如192.168.1.0/24,它匹配192.168.1.0到192.168.1.255之间的所有IP地址,因为子网掩码为24时,IP地址的前24位是网络部分,后8位是主机部分,可以有256个不同的地址。

【旧】判断当前防火墙类型

Firewalld防火墙检测在前,然后Iptables防火墙检测在后。

麒麟服务器中发现,同时具有IptablesFirewalld,且默认开启的为Firewalld,在执行脚本sh时由service iptables status导致重定向命令systemctl status iptables.service开启了防火墙iptables关闭了Firewalld

#!/bin/bash

# 检查是否正在使用 firewalld
if [ -f /etc/firewalld/firewalld.conf ]; then
echo "当前正在使用 firewalld。"
exit 0
fi

# 检查是否正在使用 iptables
if [ -f /etc/sysconfig/iptables ]; then
echo "当前正在使用 iptables。"
exit 0
fi

echo "无法确定当前使用的防火墙。"
exit 1

补充信息

由于centos6下部分服务器存在差异情况:
执行命令service iptables status;会出现两种情况返回输出:

1.

iptables: Firewall is not running.

2.

iptables
Loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled)
Active: inactive (dead) since Wed 2024-05-08 10:19:53 CST; 13min ago
Process: 358493 ExecStart=/usr/libexec/iptables/iptables.init start (code=exited, status=0/SUCCESS)
Process: 358645 ExecStop=/usr/libexec/iptables/iptables.init stop (code=exited, status=0/SUCCESS)
Main PID: 358493 (code=exited, status=0/SUCCESS)

5月 08 10:03:25 qilinmbgui systemd[1]: Starting IPv4 firewall with iptables...
5月 08 10:03:25 qilinmbgui iptables.init[358493]: iptables: Applying firewall rules: [ OK ]
5月 08 10:03:25 qilinmbgui systemd[1]: Started IPv4 firewall with iptables.
5月 08 10:19:53 qilinmbgui systemd[1]: Stopping IPv4 firewall with iptables...
5月 08 10:19:53 qilinmbgui iptables.init[358645]: iptables: Setting chains to policy ACCEPT: nat mangle raw security filter [FAILED]
5月 08 10:19:53 qilinmbgui iptables.init[358645]: iptables: Flushing firewall rules: [ OK ]
5月 08 10:19:53 qilinmbgui systemd[1]: iptables.service: Succeeded.
5月 08 10:19:53 qilinmbgui systemd[1]: Stopped IPv4 firewall with iptables.

【新】判断当前防火墙类型(已优化)

添加防火墙命令脚本(测试版本)

#!/bin/bash

# 检查是否正在使用 firewalld
if [ -f /etc/firewalld/firewalld.conf ]; then
echo "当前正在使用 firewalld "


# 运行 firewall-cmd --state 命令并将结果保存到变量中
firewall_state=$(firewall-cmd --state)

# 判断防火墙状态是否为running
if [ "$firewall_state" = "running" ]; then
echo "防火墙正在运行."

#############################
########## 操作命令 ##########
#############################

else
echo "防火墙未运行."
fi

exit 0
fi

# 检查是否正在使用 iptables
if [ -f /etc/sysconfig/iptables ]; then
echo "当前正在使用 iptables。"

# 运行 service iptables status 命令并检查输出
status_output=$(service iptables status)

# 检查输出是否包含 "not running"
if [[ "$status_output" != *"not running"* || "$status_output" == *"Active: active"* ]]; then

# 获取当前已配置防火墙规则数量
if iptables -L | grep -c -E '^ACCEPT' > 0; then
echo "iptables 防火墙正在运行."

#############################
########## 操作命令 ##########
#############################

else
echo "iptables 服务处于停止状态"
fi
else
echo "iptables 服务处于停止状态"
fi

exit 0
fi


echo "无法确定当前使用的防火墙。"
exit 1

添加防火墙命令脚本(完整版本)

firewalld防火墙规则

#添加防火墙规则(允许放行指定ip来源访问22端口)
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="xx.xxx.5.1/32" port protocol="tcp" port="22" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="xx.xxx.5.11/32" port protocol="tcp" port="22" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="xx.xxx.x.25/32" port protocol="tcp" port="22" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="xx.xxx.x.29/32" port protocol="tcp" port="22" accept'
#应用防火墙规则
firewall-cmd --reload
#输出防火墙规则
firewall-cmd --list-all

iptables防火墙规则

#添加防火墙规则(允许放行指定ip来源访问22端口)
/sbin/iptables -I INPUT -p tcp --dport 22 -s xx.xxx.5.1/32 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22 -s xx.xxx.5.11/32 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22 -s xx.xxx.x.25/32 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22 -s xx.xxx.x.29/32 -j ACCEPT
#应用防火墙规则
service iptables save
service iptables restart
#输出防火墙规则
cat /etc/sysconfig/iptables

防火墙端口转发配置

已确认!通过自定义端口转发访问,不会绕过已配置的防火墙规则。

在一般情况下,firewalld的端口转发规则是应用在防火墙流量经过转发之前的阶段,而不是在目标端口接收流量后的阶段。因此,如果你在22端口上设置了指定IP访问规则,端口转发不会绕过这些规则。


为避免后续在犯错,我决定留一个备用端口。
通过Firewalld端口转发,将其他自定义端口流量转发至于22端口,这样即使ssh的默认端口由于防火墙规则配置出错导致无法连接,我也有备用解决方案!

SSH 连接自定义端口命令

格式:ssh -p 端口号 用户名@主机地址

ssh -p root@192.168.226.131

Firewalld端口转发规则

开启Firewalld端口转发

默认是关闭端口转发

firewall-cmd --zone=public --add-masquerade --permanent
firewall-cmd --reload

添加端口转发规则

将8080端口转发至22端口

firewall-cmd --zone=public --add-forward-port=port=8080:proto=tcp:toport=22 --permanent
firewall-cmd --reload

查询端口转发规则

firewall-cmd --zone=public --list-all

观察是否输出:forward-ports:port=8080:proto=tcp:toport=22:toaddr=

删除端口转发规则

同上防火墙删除规则

调整SSH端口

Linux系统配置ssh监听多个端口方法

注意:如果系统升级过ssh,即使修改配置文件/etc/ssh/sshd_config也不会生效,升级openssh后,配置文件被修改到/usr/local/etc/sshd_config

脚本命令

#!/bin/bash

# 添加新的listenAddress配置到sshd_config文件
echo "listenAddress 0.0.0.0:22" | sudo tee -a /etc/ssh/sshd_config
echo "listenAddress 0.0.0.0:2201" | sudo tee -a /etc/ssh/sshd_config

# 修改SELinux配置文件(重启生效)
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

# 检查SELinux状态并打印日志
selinux_status=$(getenforce)
echo "SELinux status: $selinux_status"
if [ "$selinux_status" == "Permissive" ]; then
echo "SELinux is in Permissive mode."
else
echo "SELinux is not in Permissive mode."

# 设置SELinux为宽容模式(立即生效)
setenforce 0
fi

# 重启sshd服务
service sshd restart


修改默认端口

例如:修改默认22端口为2201

Port 2201
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

监听多个端口

selinux需设置为disabled,否则不生效!

#Port 22
#AddressFamily any
listenAddress 0.0.0.0:22
listenAddress 0.0.0.0:2201
listenAddress 0.0.0.0:2202
#ListenAddress ::

重启SSH服务

service sshd restart

查看sshd的端口情况

netstat -anp|grep sshd

补充:修改selinux

立即生效方案

设置宽容模式,permissive (不执行但产生警告)

setenforce 0

检查设置结果

getenforce

需要重启方案

vim /etc/selinux/config

修改内容

SELINUX=disabled

重启应用修改

reboot

验证修改

如果SELinux已被禁用,命令的输出应该显示SELinux status: disabled。

sestatus

脚本命令

添加防火墙规则

添加指定IP的SSH防火墙规则,并同时开启备用SSH端口

  • centos6 (待确认)
  • centos7 ok
  • 麒麟 ok

解决复制代码格式打乱:使用 :set paste 命令开启 Paste 模式,这样在插入模式下粘贴内容时会关闭自动缩进,可以保持原始格式。插入模式下,使用 :set nopaste 命令可以关闭 Paste 模式。

#!/bin/bash

# 定义配置放开的ssh端口数组
configs=("ListenAddress 0.0.0.0:22" "ListenAddress 0.0.0.0:2201")
# 定义备用SSH端口访问IP地址【备用SSH】
bak_ip_addresses=("xx.xxx.x.25/32" "xx.xxx.x.29/32")

# 定义要添加的IP地址和端口【主要SSH】
ip_addresses=("xx.xxx.5.1/32" "xx.xxx.5.11/32" "xx.xxx.x.25/32" "xx.xxx.x.29/32")
port="22"

# 定义ssh配置文件路径
file="/etc/ssh/sshd_config"

# 定义selinux配置文件
selinux_config="/etc/selinux/config"

# 遍历配置数组
for config in "${configs[@]}"; do
# 使用grep命令检查配置是否存在于文件中
if grep -q "^$config" "$file"; then
echo "$config 配置已存在"
else
# 如果配置不存在,则追加到文件中
echo "$config" | tee -a "$file" > /dev/null
echo "$config 配置已添加到 $file"
fi
done


# 检查SELinux状态并打印日志
selinux_status=$(getenforce)
echo "SELinux status: $selinux_status"
if [ "$selinux_status" == "Permissive" ] || [ "$selinux_status" == "Disabled" ] ; then
echo "SELinux 当前属于宽容模式"
else
echo "SELinux 已修改为宽容模式"

# 修改SELinux配置文件(重启生效)
sed -i 's/^SELINUX=.*/SELINUX=disabled/' "$selinux_config"

# 设置SELinux为宽容模式(立即生效)
setenforce 0
fi

# 重启sshd服务
service sshd restart

# 检查是否正在使用 firewalld
if [ -f /etc/firewalld/firewalld.conf ]; then
echo "当前正在使用 firewalld "

# 运行 firewall-cmd --state 命令并将结果保存到变量中
firewall_state=$(firewall-cmd --state)

# 判断防火墙状态是否为running
if [ "$firewall_state" = "running" ]; then
echo "防火墙正在运行."

#############################
########## 操作命令 ##########

# 指定规则文件路径
rules_file="/etc/firewalld/zones/public.xml"
# 指定备份文件路径
backup_file="/etc/firewalld/zones/firewalld_backup_$(date +%Y%m%d_%H%M%S).rules"
# 备份当前规则文件
cp "$rules_file" "$backup_file"
# 输出备份文件路径
echo "Firewalld规则文件已备份到: $backup_file"

# 循环遍历IP地址数组(firewalld没有相关方法实现对重复规则的检查,但重复的规则不会被frewalld添加到防火墙规则中。)
for ip in "${ip_addresses[@]}"; do
# 构建规则
rule="rule family=\"ipv4\" source address=\"$ip\" port protocol=\"tcp\" port=\"$port\" accept"

firewall-cmd --permanent --add-rich-rule="$rule"
done

# 循环遍历端口数组->添加备用SSH端口访问IP地址的防火墙规则
for config in "${configs[@]}"; do
# 提取端口号
port=$(echo "$config" | awk -F ':' '{print $2}')

# 循环遍历IP地址数组
for ip in "${bak_ip_addresses[@]}"; do
# 构建规则
rule="rule family=\"ipv4\" source address=\"$ip\" port protocol=\"tcp\" port=\"$port\" accept"

# 添加规则
firewall-cmd --permanent --add-rich-rule="$rule"
echo "备用SSH_已添加规则:$rule"
done
done

#应用防火墙规则
firewall-cmd --reload
#输出防火墙规则
#firewall-cmd --list-all

#############################

else
echo "防火墙未运行."
fi

exit 0
fi

# 检查是否正在使用 iptables
if [ -f /etc/sysconfig/iptables ]; then
echo "当前正在使用 iptables。"

# 运行 service iptables status 命令并检查输出
status_output=$(service iptables status)

# 检查输出是否包含 "not running"
if [[ "$status_output" != *"not running"* || "$status_output" == *"Active: active"* ]]; then

# 获取当前已配置防火墙规则数量
if iptables -L | grep -c -E '^ACCEPT' > 0; then
echo "iptables 防火墙正在运行."

#############################
########## 操作命令 ##########


# 指定备份文件路径
backup_file="/etc/sysconfig/iptables_backup_$(date +%Y%m%d_%H%M%S).rules"
# 保存当前iptables规则到备份文件中
iptables-save > "$backup_file"
# 输出备份文件路径
echo "iptables规则已备份到: $backup_file"

# 检查规则是否存在
if iptables -C INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT &>/dev/null; then
# 规则存在,删除它
iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
echo "默认允许新连接22端口:规则已删除"
else
echo "默认允许新连接22端口:规则不存在"
fi


# 检查规则是否已经存在的函数
rule_exists() {
local rule="$1"
local table="$2"
/sbin/iptables -C "$table" $rule &>/dev/null
}

# 循环遍历IP地址数组
for ip in "${ip_addresses[@]}"; do
# 构建规则
rule="-p tcp --dport $port -s $ip -j ACCEPT"

# 检查规则是否已经存在
if ! rule_exists "$rule" "INPUT"; then
# 如果规则不存在,则添加规则
/sbin/iptables -I INPUT $rule
echo "已添加规则:$rule"
else
echo "规则已存在:$rule"
fi
done


# 循环遍历端口数组->添加备用SSH端口访问IP地址的防火墙规则
for config in "${configs[@]}"; do
# 提取端口号
port=$(echo "$config" | awk -F ':' '{print $2}')

# 循环遍历IP地址数组
for ip in "${bak_ip_addresses[@]}"; do
# 构建规则
rule="-p tcp --dport $port -s $ip -j ACCEPT"

# 检查规则是否已经存在
if ! rule_exists "$rule" "INPUT"; then
# 如果规则不存在,则添加规则
/sbin/iptables -I INPUT $rule
echo "备用SSH_已添加规则:$rule"
else
echo "规则已存在:$rule"
fi
done
done

#应用防火墙规则
service iptables save && service iptables restart

#输出防火墙规则
#cat /etc/sysconfig/iptables

#############################

else
echo "iptables 服务处于停止状态"
fi
else
echo "iptables 服务处于停止状态"
fi

exit 0
fi


echo "无法确定当前使用的防火墙。"
exit 1

OpenSSH修复CVE-2023-38408漏洞

  • centos6 fail
  • centos7 ok
  • 麒麟 ok
#!/bin/bash
#https://blog.51cto.com/qiuyue/6904175


# 指定下载目录
download_dir="/tmp/"

# 指定要下载的文件
file="openssh-9.3p2.tar.gz"

# 指定要下载的URL
url="https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/"

# 检查wget是否存在
if which wget &>/dev/null; then
echo "wget已安装"
# 使用wget下载文件到指定目录
wget -P "$download_dir" "$url$file"
else
echo "wget未安装"
exit 1
fi

# 备份配置文件
cd /etc/ssh && cp sshd_config{,.bak}
cd /etc/pam.d && cp sshd{,.bak}

# 按照依赖包
yum -y install gcc gcc-c++ zlib-devel openssl-devel pam-devel

#编译新版本
tar -xf "$download_dir$file" -C /usr/src

cd /usr/src/openssh-9.3p2 && ./configure --prefix=/usr --sysconfdir=/etc/ssh --with-zlib --with-pam

rpm -qa | grep openssh

rpm -e --nodeps `rpm -qa | grep openssh`

make && make install

echo $?

# 修复权限
chmod 600 /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key

# 复制配置文件并授权
cp -a contrib/redhat/sshd.init /etc/init.d/sshd && chmod u+x /etc/init.d/sshd

# 还原之前备份的配置文件
cd /etc/ssh && mv -f sshd_config.bak sshd_config
cd /etc/pam.d && mv -f sshd.bak sshd

# 允许root用户远程登录(生产服务器一般属于`普通用户`登录后切`su`用户)
# sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/g' /etc/ssh/sshd_config

# 设置开机自启
chkconfig --add sshd
chkconfig sshd on
chkconfig --list

# 重启SSH
systemctl restart sshd

# 查看SSH版本
ssh -V

Centos6 升级 (OpenSSH修复CVE-2023-38408漏洞)

补充下 : centos6 更新源

wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-6.10.repo
yum clean all && yum makecache

Linux - centos6.6升级openssh9.7p1

openSSH升级常见报错汇总

【已解决】openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No

Centos7安装、配置SSH服务远程登录

当SSH升级失败,无法登录情况下,登录VM虚机,然后在终端下重新安装openSSH服务即可。

完美解决 unbuntu中vim编辑完成后 按ESC毫无反映

按ESC退出编辑模式:

再同时按 shift键和:键 就可以出现:

如果你按shift键+:没有反映,需要将输入法切换成英文输入法


安装环境依赖

yum -y install gcc zlib-devel openssh-devel

安装perl

tar -zxvf perl-5.38.2.tar.gz
./Configure -des -Dprefix=/usr/local/perl
make && make install 

配置环境变量

/etc/profile

echo 'export PATH=/usr/local/perl/bin/:$PATH' >> /etc/profile
source /etc/profile
perl -v

安装 zlib

tar -zxvf zlib.tar.gz
./configure  --prefix=/usr/local/zlib
make && make install

配置环境变量

echo 'export LD_LIBRARY_PATH=/usr/local/zlib/lib:$LD_LIBRARY_PATH' >> /etc/profile
source /etc/profile

检查是否具有目录includelibshare

ls /usr/local/zlib/

安装 openssl

tar -zxvf openssl-3.2.1.tar.gz
./config --prefix=/usr/local/openssl
make && make install

配置环境变量

echo 'export PATH=/usr/local/openssl/bin:$PATH' >> /etc/profile
echo 'export LD_LIBRARY_PATH=/usr/local/openssl/lib64:$LD_LIBRARY_PATH' >> /etc/profile
source /etc/profile

刷新缓存

ldconfig

查看版本

openssl version

安装openssh

解压Openssh9.7p1文件

tar -zxvf openssh-9.7p1.tar.gz
./configure --prefix=/usr/local/openssh --sysconfdir=/etc/ssh --with-ssl-dir=/usr/local/openssl --with-zlib=/usr/local/zlib
make && make install

针对不支持配置进行注释

/etc/ssh/sshd_config line 81: Unsupported option GSSAPIAuthentication
/etc/ssh/sshd_config line 83: Unsupported option GSSAPICleanupCredentials
/etc/ssh/sshd_config line 97: Unsupported option UsePAM

sed -i 's/^GSSAPIAuthentication/#&/' /etc/ssh/sshd_config
sed -i 's/^GSSAPICleanupCredentials/#&/' /etc/ssh/sshd_config
sed -i 's/^UsePAM/#&/' /etc/ssh/sshd_config

配置环境变量

echo 'export PATH=/usr/local/openssh/bin:$PATH' >> /etc/profile
source /etc/profile

查看版本信息

ssh -V

创建软连接

ln -snf /usr/local/openssh/bin/ssh-keygen /usr/bin/ssh-keygen
# ssh-keygen需要依赖openssl的libcrypto
ln -snf /usr/local/openssl/lib64/libcrypto.so.3 /usr/lib64/libcrypto.so.3
ln -snf /usr/local/openssh/sbin/sshd /usr/sbin/sshd

重启SSH服务

service sshd restart;

root用户无法登录,则修改/etc/ssh/sshd_config文件,修改PermitRootLogin yes 即可


错误命令
./configure –prefix=/usr –sysconfdir=/etc/ssh

编译报错: configure: error: *** working libcrypto not found, check config.log

升级openssh编译报错“configure: error: *** working libcrypto not found, check config.log”的解决办法

yum install -y openssl-devel

Centos6 升级 (OpenSSH修复CVE-2023-38408漏洞)【SH脚本版】

linux多核处理下提高编译速度 make -j

解决Linux关闭ssh连接导致执行的程序停掉的问题

# 示例代码
nohup sh start.sh > run.log 2>&1 &
#!/bin/bash

# ------------------------------------------------

# 定义一个生成备份文件名的方法
generate_backup_name() {
echo ".backup_$(date +%Y%m%d_%H%M%S)"
}

generate_backup_date() {
echo "$(date +%Y%m%d)"
}

# 定义一个备份路径的方法
backup_path() {
local path=$1
local backup_name=$2

if [ -d "$path" ]; then
# 处理目录备份
local parent_dir=$(dirname "$path")
local dir_name=$(basename "$path")
cp -r "$path" "$parent_dir/$dir_name$backup_name" || { echo "Failed to backup directory $path"; return 1; }
echo "Backup created: $parent_dir/$dir_name$backup_name"
elif [ -f "$path" ]; then
# 处理文件备份
local dir=$(dirname "$path")
local file=$(basename "$path")
cp "$path" "$dir/$file$backup_name" || { echo "Failed to backup file $path"; return 1; }
echo "Backup created: $dir/$file$backup_name"
else
echo "$path does not exist"
return 1
fi
}

# 定义一个解压方法
extract_tar_gz() {
local tar_file=$1
local dest_dir=$2

# 检查 tar.gz 文件是否存在
if [ ! -f "$tar_file" ]; then
echo "File $tar_file does not exist"
return 1
fi

# 检查目标目录是否存在,如果不存在则创建
if [ ! -d "$dest_dir" ]; then
mkdir -p "$dest_dir" || { echo "Failed to create directory $dest_dir"; return 1; }
fi

# 解压 tar.gz 文件到指定目录
tar -xzf "$tar_file" -C "$dest_dir" || { echo "Failed to extract $tar_file to $dest_dir"; return 1; }

echo "Extracted $tar_file to $dest_dir"
}

# 定义一个提取文件名的方法(去掉`.tar.gz`)
extract_filename_exp() {
local url=$1
local basename

# 提取文件名(不包括扩展名)
basename=$(basename "$url" .tar.gz)

echo "$basename"
}


# 定义一个提取文件名的方法
extract_filename() {
local url=$1
local filename

# 提取 ? 前的部分
filename=$(echo "$url" | cut -d '?' -f 1)

echo "$filename"
}

# ------------------------------------------------

# 指定下载目录
download_dir="/root/"

# 指定要下载的URL
URL_PRIFIX="https://XXX.aliyuncs.com/ssh_upgrade/"

# 指定要下载的文件
perl_URL="perl-5.38.2.tar.gz?OSSAccessKeyId=LTAI4FnhQ9DsrVxZW9uwDd1q&Expires=1716373493&Signature=IaiQ9Z6XPONkqS2nZxu6v2OSVI8%3D"

zlib_URL="zlib-1.3.1.tar.gz?OSSAccessKeyId=LTAI4FnhQ9DsrVxZW9uwDd1q&Expires=1716373463&Signature=T3p9uD%2BgwE51hAbHv5er2zYqFG8%3D"

openSSL_URL="openssl-3.2.1.tar.gz?OSSAccessKeyId=LTAI4FnhQ9DsrVxZW9uwDd1q&Expires=1716373445&Signature=XO1njdaYbF1DDJ5ybrkAYf7BWNI%3D"

openSSH_URL="openssh-9.7p1.tar.gz?OSSAccessKeyId=LTAI4FnhQ9DsrVxZW9uwDd1q&Expires=1716373429&Signature=%2BKlQOrhJsUPOvlPKiCH6Ancufu8%3D"

# 检查wget是否存在
if which wget &>/dev/null; then
echo "wget已安装"
else
echo "wget未安装,通过yum命令安装中...安装完成后继续执行下载任务!"
yum install -y wget
fi

# 生成日期
option_date=$(generate_backup_date)
# 生成备份文件名
backup_name=$(generate_backup_name)
# 开始备份文件或目录
backup_path "/etc/ssh/sshd_config" "$backup_name"
backup_path "/etc/pam.d/sshd" "$backup_name"
#backup_path "/usr/bin/openssl" "$backup_name"
#backup_path "/usr/lib/systemd/system" "$backup_name"

# 按照依赖包
yum -y install gcc gcc-c++ zlib-devel openssl-devel pam-devel

##开始安装perl##
wget -O "$download_dir$(extract_filename $perl_URL)" "$URL_PRIFIX$perl_URL" #下载安装文件
perl=$(extract_filename "$perl_URL") #从url中获取perl.tar.gz文件名
perl_dir=$(extract_filename_exp "$perl") #获取`perl`中获取解压后目录名
extract_tar_gz "$download_dir$perl" "/opt/${option_date}/" #解压文件到指定目录下
cd /opt/${option_date}/$perl_dir
./Configure -des -Dprefix=/usr/local/perl
make -j
make install -j
echo 'export PATH=/usr/local/perl/bin/:$PATH' >> /etc/profile && source /etc/profile
perl_version=$(perl -v 2>&1)
echo "perl已安装,版本:$perl_version"

##开始安装zlib##
wget -O "$download_dir$(extract_filename $zlib_URL)" "$URL_PRIFIX$zlib_URL"
zlib=$(extract_filename "$zlib_URL")
zlib_dir=$(extract_filename_exp "$zlib")
extract_tar_gz "$download_dir$zlib" "/opt/${option_date}/"
cd /opt/${option_date}/$zlib_dir
./configure --prefix=/usr/local/zlib
make -j
make install -j
echo 'export LD_LIBRARY_PATH=/usr/local/zlib/lib:$LD_LIBRARY_PATH' >> /etc/profile && source /etc/profile
zlib_check=$(ls -1 /usr/local/zlib/*)
if [ -n "$zlib_check" ]; then
echo "zlib已安装,/usr/local/zlib/目录下已存在文件:"
echo "$zlib_check"
else
echo "zlib未安装或者目录下没有文件"
exit 1
fi

##开始安装openssl##
wget -O "$download_dir$(extract_filename $openSSL_URL)" "$URL_PRIFIX$openSSL_URL"
openssl=$(extract_filename "$openSSL_URL")
openssl_dir=$(extract_filename_exp "$openssl")
extract_tar_gz "$download_dir$openssl" "/opt/${option_date}/"
cd /opt/${option_date}/$openssl_dir
./config --prefix=/usr/local/openssl
make -j
make install -j
echo 'export PATH=/usr/local/openssl/bin:$PATH' >> /etc/profile
echo 'export LD_LIBRARY_PATH=/usr/local/openssl/lib64:$LD_LIBRARY_PATH' >> /etc/profile
source /etc/profile
ldconfig
openssl_version=$(openssl version 2>&1)
echo "openssl已安装,版本:$openssl_version"

##开始安装openssh##
wget -O "$download_dir$(extract_filename $openSSH_URL)" "$URL_PRIFIX$openSSH_URL"
openssh=$(extract_filename "$openSSH_URL")
openssh_dir=$(extract_filename_exp "$openssh")
extract_tar_gz "$download_dir$openssh" "/opt/${option_date}/"
cd /opt/${option_date}/$openssh_dir
./configure --prefix=/usr/local/openssh --sysconfdir=/etc/ssh --with-ssl-dir=/usr/local/openssl --with-zlib=/usr/local/zlib
make -j
make install -j
echo 'export PATH=/usr/local/openssh/bin:$PATH' >> /etc/profile
source /etc/profile

##创建软连接##
ln -snf /usr/local/openssh/bin/ssh-keygen /usr/bin/ssh-keygen
# ssh-keygen需要依赖openssl的libcrypto
ln -snf /usr/local/openssl/lib64/libcrypto.so.3 /usr/lib64/libcrypto.so.3
ln -snf /usr/local/openssh/sbin/sshd /usr/sbin/sshd

##还原配置文件##
cd /etc/ssh && mv -f "/etc/ssh/sshd_config$backup_name" sshd_config
cd /etc/pam.d && mv -f "/etc/pam.d/sshd$backup_name" sshd

##注释不支持配置项##
sed -i 's/^GSSAPIAuthentication/#&/' /etc/ssh/sshd_config
sed -i 's/^GSSAPICleanupCredentials/#&/' /etc/ssh/sshd_config
sed -i 's/^UsePAM/#&/' /etc/ssh/sshd_config

##防止升级后ssh-v查询为旧版本号##
#ssh_path=$(which ssh)
#mv "${ssh_path}" "${ssh_path}${$backup_name}"
#sshd_path=${which sshd}
#mv "${sshd_path}" "${sshd_path}${$backup_name}"
#cp /usr/local/openssh/bin/ssh /usr/bin/ssh
#cp /usr/local/openssh/sbin/sshd /usr/sbin/sshd

##重启SSH服务##
service sshd restart

ssh_version=$(ssh -V 2>&1)
echo "ssh已安装,版本:$ssh_version"
注意事项

我这边升级之后遇到问题有,ssh -V输出日志 ssh 是9.3版本的,当我执行source /etc/profile在执行ssh -V就是9.7版本的。

参考博客:Openssh升级后版本不对应


获取ssh位置

which ssh 

/usr/bin/ssh

获取sshd位置

which sshd

/usr/sbin/sshd

备份ssh和sshd文件

mv /usr/bin/ssh /usr/bin/ssh.bak20240522
mv /usr/sbin/sshd /usr/sbin/sshd.bak20240522

通过环境变量配置文件可知,新升级ssh目录位置

export PATH=/usr/local/openssh/bin:$PATH

cp /usr/local/openssh/bin/ssh /usr/bin/ssh
cp /usr/local/openssh/sbin/sshd  /usr/sbin/sshd

再次验证ssh版本信息

ssh -V 

防止ssh升级失败导致无法连接服务器

防火墙Iptables

#!/bin/bash

# ================================
# Script Name: setup_telnet.sh
# Description: This script installs and configures Telnet as a backup method for connecting to the server.
# Author: Your Name
# Date: YYYY-MM-DD
# Version: 1.0
# ================================

# 检查是否以 root 用户运行
if [ "$(id -u)" -ne 0 ]; then
echo "请以 root 用户运行此脚本。"
exit 1
fi

# 安装 Telnet 服务和 xinetd
echo "正在安装 Telnet 服务和 xinetd..."
yum install -y telnet-server xinetd

# 配置 xinetd 启动 Telnet
echo "正在配置 xinetd 启动 Telnet..."
cat <<EOL > /etc/xinetd.d/telnet
service telnet
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
log_on_failure += USERID
disable = no
}
EOL

# 启动并启用 xinetd 服务
echo "正在启动并启用 xinetd 服务..."
service xinetd start
#systemctl enable xinetd #(如果当前命令不存在)
chkconfig xinetd on

# 使用 iptables 配置防火墙规则
echo "正在配置防火墙规则..."
# 允许 Telnet 连接
iptables -I INPUT -p tcp --dport 23 -j ACCEPT
# 提交规则更改
iptables-save > /etc/sysconfig/iptables

# 提示成功信息
echo "Telnet 服务已成功安装并配置。请尽快测试 Telnet 连接并在不再需要时禁用该服务。"

# 提示测试 Telnet 连接的方法
echo "使用以下命令从另一台机器测试 Telnet 连接:"
echo "telnet <your_server_ip>"

# 最后,重新加载 iptables 以应用新规则
echo "正在重新加载 iptables 配置..."
systemctl restart iptables

防火墙Firewalld

#!/bin/bash

# ================================
# Script Name: setup_telnet.sh
# Description: This script installs and configures Telnet as a backup method for connecting to the server.
# Author: Your Name
# Date: YYYY-MM-DD
# Version: 1.0
# ================================

# 检查是否以 root 用户运行
if [ "$(id -u)" -ne 0 ]; then
echo "请以 root 用户运行此脚本。"
exit 1
fi

# 安装 Telnet 服务和 xinetd
echo "正在安装 Telnet 服务和 xinetd..."
yum install -y telnet-server xinetd

# 配置 xinetd 启动 Telnet
echo "正在配置 xinetd 启动 Telnet..."
cat <<EOL > /etc/xinetd.d/telnet
service telnet
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
log_on_failure += USERID
disable = no
}
EOL

# 启动并启用 xinetd 服务
echo "正在启动并启用 xinetd 服务..."
systemctl start xinetd
systemctl enable xinetd

# 确认防火墙允许 Telnet 连接
echo "正在配置防火墙以允许 Telnet 连接..."
firewall-cmd --permanent --add-port=23/tcp
firewall-cmd --reload

# 提示成功信息
echo "Telnet 服务已成功安装并配置。请尽快测试 Telnet 连接并在不再需要时禁用该服务。"

# 提示测试 Telnet 连接的方法
echo "使用以下命令从另一台机器测试 Telnet 连接:"
echo "telnet <your_server_ip>"

禁用telnet服务

centos6

service xinetd stop
chkconfig xinetd off
yum remove -y telnet-server xinetd

centos7

systemctl stop xinetd
systemctl disable xinetd
yum remove -y telnet-server xinetd

SSH升级后,无法使用ftp服务

升级OpenSSH后SFTP无法连接问题修改

vim  /etc/ssh/sshd_config
#override default of no subsystems
#Subsystem sftp /usr/local/openssh/libexec/sftp-server改成下面这句
Subsystem sftp internal-sftp
systemctl restart sshd