终于遇到我最怕面对、最怕麻烦的加固工作。怕的是因为要Linux编译安装,而那些环境变量、软件依赖、乃至编译链接安装,都很少涉猎,特别是生产环境的系统,特别是这个物理机的CentOS,就没有镜像备份的概念。
犹记得上次只是重启sshd来刷新版本,弹出个no hostkey alg都吓了一跳。犹记得上次,polkit升级,找了半天有签名的RPM包,然后rpm -Uvh,就为了避免源码编译。这次,OpenSSL升级,是硬货。
Telnet保障
序言:菜鸟Telnet不开,机房为你开。
为10台机子,开telnet时,惊觉,8台都没有telnet-server服务,不禁默默赞上一位加固OpenSSH的工程师一句,艺高人胆大。
#查看telnet-server版本
rpm -qa telnet-server
#没有就去阿里云下载对应xinetd、telnet-server的RPM包,看版本号,cat /etc/issue,http://mirrors.aliyun.com/centos-vault/6.5/os/x86_64/Packages/
rpm -ivh xinetd
rpm -ivh telnet-server
#编辑disable=no,并启动telnet服务做备用
vi /etc/xinetd.d/telnet
#sed可以快速修改,无奈匹配符学得不好
#关
sed -i 's/disable\t\t= no/disable\t\t= yes/g' /etc/xinetd.d/telnet
cat /etc/xinetd.d/telnet
service xinetd restart
#开
sed -i 's/disable\t\t= yes/disable\t\t= no/g' /etc/xinetd.d/telnet
#确认
cat /etc/xinetd.d/telnet
service xinetd restart
#开放23端口防火墙,Centos6.5 防火墙开放端口
vi /etc/sysconfig/iptables
#开放23,发现管理员已经对特定IP放通所有端口,好,少折腾一个。
##centos7的话
firewall-cmd --zone=public --add-port=23/tcp
firewall-cmd --reload
默认Telnet禁止不信任的终端tty登陆Root用户,而普通账号又密码全过期了,懒得帮管理员改,所以选择无脑加白名单。how-enable-telnet-root-user
#可查登陆记录,发现pts/0的告警日志
tail /var/log/secure
#Mar 31 11:42:13 server3 login: pam_securetty(remote:auth): access denied: tty 'pts/0' is not secure !
#添加tty白名单
vi /etc/securetty
#添加以下对应的终端
pts/0
pts/1
pts/2
pts/3
pts/4
pts/5
pts/6
pts/7
pts/8
pts/9
#从同网段的机器登录,telnet一遍,测试成功
telnet 19.XXX.XXX.150
For OpenSSL1.1.1x
SFTP把所有的测试过可能依赖环境的RPM包、OpenSSL源码包放到自己喜欢的路径。看见了历代加固工程师,喜欢放根目录,感觉就是一个字,为所欲为。
#先看看版本
openssl version
#一个技巧,cd到前辈们的openssl目录,看他们的config配置:
#perl configdata.pm --dump
历史红利,一般编译环境都会有的。make gcc不需要怎么关注。
sudo yum install zlib zlib-devel pam-devel
我的思路保守,希望生成一个独立的OpenSSL,不要覆盖以前的。https://www.openssl.org/source/
cd openssl-2022-3-30
tar -zxvf openssl-1.1.1n.tar.gz
cd openssl-1.1.1n
#可以看到prefix、openssldir,指定了特定的文件夹,前辈笔记有shared参数,感觉不是必要的,删走。zlib本地测试没加上都能用,还是参考着写一写吧。
./config zlib --prefix=/usr/local/openssl1.1.1n --openssldir=/usr/local/openssl1.1.1n
#make clean
#默认一切顺利
make
make install
#去看看有无正确响应
/usr/local/openssl1.1.1n/bin/openssl version
#一般会报错找不到glibc.so
所以将OpenSSL加载起来。
#门面功夫(感觉非必要:将openssl的二进制链接起来,注意看当前系统openssl的路径
which openssl
mv /usr/bin/openssl /usr/bin/openssl.1.1.1k.bak
mv /usr/include/openssl /usr/include/openssl.1.1.1k.bak
ll /usr/bin/openssl.1.1.1k.bak
ln -s /usr/local/openssl1.1.1n/bin/openssl /usr/bin/openssl
ln -s /usr/local/openssl1.1.1n/include/openssl /usr/include/openssl
#真正的登堂入室,加载配置
#先备份
cp /etc/ld.so.conf /etc/ld.so.conf.bak.3.31
#追加写入/etc/ld.so.conf配置
echo "/usr/local/openssl1.1.1n/lib/" >> /etc/ld.so.conf
#再vi进去删除老的openssl库的行
vi /etc/ld.so.conf
#刷新加载
/sbin/ldconfig
openssl version
#好的,偷懒的可以收工了。
#上一位真·高工,升级的OpenSSH是动态加载OpenSSL的,所以,无缝升级了OpenSSH版本。
sshd -VVVVVVVVVVVVV
For OpenSSL1.1.1o
tar -zxvf openssl-1.1.1o.tar.gz
cd openssl-1.1.1o
#可以看到prefix、openssldir,指定了特定的文件夹,前辈笔记有shared参数,感觉不是必要的,删走。zlib本地测试没加上都能用,还是参考着写一写吧。
./config zlib --prefix=/usr/local/openssl1.1.1o --openssldir=/usr/local/openssl1.1.1o
#make clean
#默认一切顺利
make
make install
#去看看有无正确响应
/usr/local/openssl1.1.1o/bin/openssl version
#一般会报错找不到glibc.so
所以将OpenSSL加载起来。
which openssl
#如果是/usr/bin/openssl
mv /usr/bin/openssl /usr/bin/openssl.1.1.1n.bak
mv /usr/include/openssl /usr/include/openssl.1.1.1n.bak
ll /usr/bin/openssl.1.1.1n.bak
ln -s /usr/local/openssl1.1.1o/bin/openssl /usr/bin/openssl
ln -s /usr/local/openssl1.1.1o/include/openssl /usr/include/openssl
#如果是/usr/local/openssl/bin/openssl
mv /usr/local/openssl/bin/openssl /usr/local/openssl/bin/openssll.1.1.1n.bak
mv /usr/local/include/openssl /usr/local/include/openssll.1.1.1n.bak
ll /usr/local/openssl/bin/openssll.1.1.1n.bak
ln -s /usr/local/openssl1.1.1o/bin/openssl /usr/local/openssl/bin/openssl
ln -s /usr/local/openssl1.1.1o/include/openssl /usr/local/include/openssl
#真正的登堂入室,加载配置
#先备份
cp /etc/ld.so.conf /etc/ld.so.conf.bak.2022.5.25
#追加写入/etc/ld.so.conf配置
echo "/usr/local/openssl1.1.1o/lib/" >> /etc/ld.so.conf
#再vi进去删除老的openssl库的行
vi /etc/ld.so.conf
#刷新加载
/sbin/ldconfig
openssl version
sshd -VVVVVVVVVVVVV
ip a
For OpenSSH8.9
tar -zxvf openssh-8.9p1.tar.gz
cd openssh-8.9p1
#要留意pam.d有没有这个sshd文件,可能导致重启后因为开了selinux而sshd起不来。没有就,复制一份cp contrib/sshd.pam.generic /etc/pam.d/sshd
cp /etc/pam.d/sshd /etc/pam.d/sshd.3.23.bak
#比较怂,整个文件夹备份
cp -r /etc/ssh /etc/ssh.3.23.bak
#指定ssl路径,这应该是静态SSL的写法。
./configure --prefix=/opt/openssh8.9p1 --sysconfdir=/etc/ssh --with-pam --with-ssl-dir=/usr/local/openssl1.1.1o
make
make install
#测试
/opt/openssh8.9p1/sbin/sshd -t -f /etc/ssh/sshd_config
vim /etc/ssh/sshd_config
which sshd
#根据真实路径备份
mv /usr/sbin/sshd /usr/sbin/sshd.bak0325
mv /usr/local/sbin/sshd /usr/local/sbin/sshd.bak0325
ln -s /opt/openssh8.9p1/sbin/sshd /usr/local/sbin/sshd
ll /usr/sbin/sshd.bak0325
#链接,替代旧主。
ln -s /opt/openssh8.9p1/sbin/sshd /usr/sbin/sshd
sshd -V
/etc/init.d/sshd restart
service sshd restart
For OpenSSL1.0.2x
1.0.2有漏洞,但是官方也要收费支持,才能获得源码?
所以我们全都升1.1.1,不要给自己设限,是可以的。
实际上,跟上面章节几乎一样。
除了perl的版本要编译升级一下。思路一样,独立安装,不想影响原来的perl,即添加Dversiononly参数
下载地址:https://www.perl.org/get.html#unix_like
cd perl-5.34.1
./Configure -des -Dprefix=/usr/local/perl-5.34.1 -Dusethreads -Dversiononly
make
make install
mv /usr/bin/perl /usr/bin/perl.old.bak
ln -s /usr/local/perl-5.34.1/bin/perl5.34.1 /usr/bin/perl
perl -v
可能zlib也太老,可以编译,可以找RPM,最新的软件对zlib版本要求都不高。
tar -zxvf zlib-1.2.12.tar.gz
cd zlib-1.2.12
./configure
make
make install
编译安装,愿你平安。
#ERROR:crypto/threads_pthread.c:48: error: `PTHREAD_MUTEX_RECURSIVE'
#https://github.com/openssl/openssl/issues/10966
./config --prefix=/usr/local/openssl1.1.1n/ --openssldir=/usr/local/openssl1.1.1n -D_XOPEN_SOURCE=500
mv /usr/bin/openssl /usr/bin/openssl.1.0.1.bak
ll /usr/bin/openssl.1.0.1.bak
ln -s /usr/local/openssl1.1.1n/bin/openssl /usr/bin/openssl
openssl version
echo "/usr/local/openssl1.1.1n/lib" >> /etc/ld.so.conf
/sbin/ldconfig
已经觉得大功告成了。所以我下班了。
想着第二天收个尾,早早溜。
第二天,傻了,ssh_exchange_identification: Connection closed by remote host,堡垒机登不上了,而Telnet没开!昨晚加班的恶果,兴冲冲的装了,却忘记上保险。
原本1.0.2的OpenSSL换成1.1.1n后,猜被OpenSSH加载了,但不兼容,毕竟大版本升级了OpenSSL。
隐藏OpenSSH版本号
法1、临时修改
注意备份sshd,启动telnet。容易版本号改高了导致sshd启动失败。
strings /usr/sbin/sshd | grep OpenSSH
sed -i 's/OpenSSH_8.9p1/OpenSSH_9.2p1/g' /usr/sbin/sshd
sed -i 's/OpenSSH_8.9/OpenSSH_9.1/g' /usr/sbin/sshd
法2、修改openssh的version.h,再次编译。
抢修方案
#ssh_exchange_identification: Connection closed by remote host
冷静下来,思路是,ln是影响不了OpenSSH的,so库才是,还好做了备份。
疫情,空降的工程师不能进机房,只好委托机房管理员操办,不知道他的水平,只好,谨慎的写出简短精确的恢复命令。
方案1、
cp -f /etc/ld.so.conf.bak.3.31 /etc/ld.so.conf
ldconfig
openssl version
service sshd start
方案2、开启telnet
由于不确定telnet-server是否安装(我忘了装,不推荐。
rpm -qa telnet-server
#如果有显示行,代表存在telnet服务
service xinetd start
非常幸运,就在用户领导站起来,抬头望到我时,我确认恢复了,对他一个肯定的呲牙笑点头,他得以放松地去吃午餐。
no hostkey alg.(On OpenSSH 8.8+,SSH-RSA)
我前一晚说收尾的工作就是,OpenSSH升级太高了,堡垒机又报经典的no hostkey alg。
上次笔记是,清空/etc/ssh的key文件,重启sshd,即会重新生成密钥对。
cd /etc/ssh
mkdir host_key_bak
mv ssh_host*key host_key_bak/
mv ssh_host*pub host_key_bak/
service sshd restart
这里没key重启。失败了。本地测试好好的,这里就只报错,不自动生成key。
#手动生成
ssh-keygen -A
service sshd restart
还是只有堡垒机不行。这时我就猜到这个堡垒机年月太久了,肯定仅支持被老淘汰的密钥算法。但无奈,只能打给管理员,想轻轻的敲击一下他们,你们的堡垒机太老了。然后问问有没类似问题的解决手册,下班了,明天请早。
那我也别偷懒了,求人不如求己,线索有,找找方法更靠谱。对比以前生成的key和现在的key,发现少了一个名叫ssh_host_key的文件。cat查看,第一行:”SSH PRIVATE KEY FILE FORMAT 1.1“,原来这是ssh-rsa第一代算法,有缺陷,8.8起默认禁用了。
所以,ssh-keygen也不能生成:
ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key
官方release,指出了潜在不兼容的问题。Potentially-incompatible changes
可是,没有写服务器端的解决方法,还好stackexchange有。How to enable ssh-rsa in sshd of OpenSSH 8.8?
#因为升级后的ssh-keygen不支持生成rsa1的key了,所以沿用以前的key
#保留原来的ssh-rsa1的密钥对,/etc/ssh/ssh_host_key,文件特征是第一行:SSH PRIVATE KEY FILE FORMAT 1.1
#There are also legacy RSA1 keys that should be gone today with SSHv1 protocol, but can be identified by the header:
SSH PRIVATE KEY FILE FORMAT 1.1
vim /etc/ssh/sshd_config
#添加以下行,恢复ssh-rsa算法支持:
HostKeyAlgorithms=+ssh-rsa
PubkeyAcceptedAlgorithms=+ssh-rsa
#重启服务
service sshd restart
完满解决。
Host old-host
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
Errors&Answers
ERROR:enc.c:(.text+0x1223): undefined reference to `BIO_f_zlib'
清空上一次make的残留再make。
make clean
make
OpenSSL编译报错:crypto/threads_pthread.c:48: error: `PTHREAD_MUTEX_RECURSIVE'
https://github.com/openssl/openssl/issues/10966
多线程编译openssl的问题?添加-D_XOPEN_SOURCE=500参数
./config --prefix=/usr/local/openssl1.1.1n/ --openssldir=/usr/local/openssl1.1.1n -D_XOPEN_SOURCE=500
sshd_config line 72: Unsupported option GSSAPIAuthentication
关了GSSAPIAuthentication的支持,看起来也没用到
sed -i 's/GSSAPI/#GSSAPI/g' /etc/ssh/sshd_config
vi /etc/ssh/sshd_config
#注释掉GSSAPI相关的行,有两行。
#/etc/ssh/sshd_config line 81: Unsupported option GSSAPIAuthentication
#/etc/ssh/sshd_config line 83: Unsupported option GSSAPICleanupCredentials
#测试
/opt/openssh8.9p1/sbin/sshd -t -f /etc/ssh/sshd_config
configure: error: *** zlib.h missing - please install first or check config.log **
#下载RPM包,zlib的源码包。
rpm -ivh zlib-1.2.1.2-1.2.x86_64.rpm
rpm -ivh zlib-devel-1.2.1.2-1.2.i386.rpm
#手动编译
tar -zxvf zlib-1.2.12.tar.gz
cd zlib-1.2.12
./configure
make
make install
编译OpenSSH的依赖软件包,https://blog.csdn.net/liumiaocn/article/details/103444258
#yum install make gcc perl pcre-devel zlib-devel -y
#离线安装
rpm -ivh pam-0.77-66.26.x86_64.rpm
rpm -ivh pam-devel-0.77-66.26.x86_64.rpm
rpm -ivh make-3.80-7.EL4.x86_64.rpm
rpm -ivh zlib-1.2.1.2-1.2.x86_64.rpm
rpm -ivh zlib-devel-1.2.1.2-1.2.i386.rpm
rpm -ivh pcre-devel-4.5-4.el4_6.6.x86_64.rpm
rpm -ivh glibc-kernheaders-2.4-9.1.103.EL.x86_64.rpm
rpm -ivh glibc-devel-2.3.4-2.43.x86_64.rpm
Error(15) 解决 sshd: no hostkeys available
ssh-keygen -A
service sshd restart
Your OpenSSL headers do not match your library.
1、提高headers版本的加载顺序。
cat /etc/ld.so.conf
ld.so.conf.d/*.conf
/opt/openssl/openssl1.1.1k_20210609/lib
/usr/local/lib64
2、headers建立新link
mv /usr/include/openssl /usr/include/openssl.1.1.1k.bak
ln -s /usr/local/openssl1.1.1n/include/openssl /usr/include/openssl
插曲-乱装RPM的余波
某台机器,RPM安装时报错:#libc.so.6: version ‘GLIBC_2.14’ not found(require by /lib64/libgcc_s.so.1)
我差点,以为GLIBC太老要升级,找了资料,发现升级glibc非同小可,搞错可以导致系统宕机。
而博客们,可信度还是不高,不想节外生枝冒险。
查一下谁引入了什么导致要求GLIBC_2.14吧。
ll lib64/libgcc_s.so.1
#指向/lib64/libgc_s-4.8.5-20150702.so.1
谷歌了libgc_s-4.8.5-20150702.so.1,发现是CentOS7的包!
libgcc-4.8.5-44.el7.x86_64.rpm
再find全硬盘查找,果然找到这个RPM包,同目录还有其他编译环境用的RPM包。
破案。
有人以为这系统是CentOS 7,一通安装闯祸了,又不修好!
思路,卸载gcc、gcc++,由于某些软件版本太高,版本依赖又互相纠缠
只能边尝试rpm -e gcc卸载,边试rpm -Uvh –oldpackage gcc.rpm低版本退回,边安装rpm -i gcc.rpm 。
几番递归,才解决。
rpm -Uvh --oldpackage gcc.rpm
无关的技巧:查看当前so的进程占用情况。
lsof lib64/libgcc_s.so.1
ldd sshd
加固就是这么多意外。
哪怕本地流畅调试成功。
定位利刃,可加固就是钝石,偶尔砍一下可以,长久还是不要挥出来。
这一章,我写了太多“猜”的字眼,因为不愿意纠细节了,能用先用着吧,一扩散可以有无限多的分岔条件,不需要不需要精通。
升级openssl后sftp-server服务异常
发现回退/etc/ld.so.conf可以恢复sftp服务。
处置一:
修改sshd_config的密钥白名单配置项
Host *
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
处置二:
尝试1:
指定最新的openssl库,重新编译openssh
失败,问题依然重现。
尝试2:
删除/etc/ld.so.conf内过时的库路径。
ok!
/etc/ld.so.conf
/usr/local/openssl/lib
/usr/local/openssl_102l/lib
/usr/local/openssl1.1.1n/lib/
==》
include ld.so.conf.d/*.conf
/usr/local/openssl/lib
/usr/local/openssl1.1.1o/lib/