RHEL 8 使用总结/避坑指南(一) 安装及配置SSH和防火墙

最近把服务器从Ubuntu转移到了RHEL8,转移过程中遇到了不少问题,通过不断搜索逐个解决,整理记录在此,供参考。因为篇幅较长,分成几篇文章发表。

提纲:

0. 前言:为什么使用RHEL 8?
1. 下载、安装RHEL 8
2. 配置防火墙
3. 配置SSH
4. 安装最新稳定版nginx
5. 配置SSL 安全证书
6. 安装PHP-FPM支持PHP
7. 挂载额外硬盘
8. 配置Samba服务
9. 安装Plex media server

0. 前言:为什么使用RHEL 8?

以前我写过我试用过一次RHEL 8(参考此文),解决了wifi无法使用问题,文章里提到过虽然可以薅Red Hat的羊毛来免费使用一年,但我还是建议使用它的社区版本Centos,操作基本一样而且LTS版本版本可以支持10年。只是哪想到,随着最近红帽(Red Hat)公司把Centos 8的维护寿命出乎意料地缩短到了2021年12月31日,在没有新的类似Centos发行版发布之前,RHEL 8 就和Centos 8 没什么差别了,怀着对此变化的不满,该薅的羊毛还要继续薅 🙂 上面是开开玩笑了,其实一个原因是工作中时不时会用到Centos,所以还是要跟进它的技术发展。

1. 下载、安装RHEL 8

1.1 制作启动U盘

想想你上次用光驱是哪一年?我是记不得了,也就是说至少n年没有用到了,所以安装自然是用U盘方式了。

下载iso 9GB。 因为RHEL不是免费的,所以需要先去Red Hat官方注册一个账号,只需要提供邮箱(必须能接收确认邮件的), 个人信息如果不想被他们sales 打扰的话,不建议填真实信息。我的email里不断收到他们sales的联系邮件。
验证SHA256 和网站上的相同。保证下载后的文件无损伤或被人改动过。

根据这个红帽官方链接制作安装U盘: MAKING INSTALLATION USB MEDIA, 简单记录如下:

# 1. 查看磁盘分区,找出U盘, 我用了个32GB的,32e9/1024/1024/1024=29.8GB,还是丢了1.1G :)
sudo lsblk 
sdc                         8:32   1  28.7G  0 disk

# 确认U盘没有被加载,若被系统自动加载,需要先卸载它
ct@server:~$ sudo findmnt /dev/sdc 
#无返回就是没有被自动加载,否则需要umount

# 2. 使用dd命令写入文件,bs(blocksize)推荐512K,网友也测试说此值写入速度最快
ct@server:~$ sudo dd if=rhel-8.3-x86_64-dvd.iso of=/dev/sdc bs=512k

# 9GB的文件得写入一段时间,我的旧电脑上用了10分钟,如下所示:
18056+0 records in
18056+0 records out
9466544128 bytes (9.5 GB, 8.8 GiB) copied, 603.207 s, 15.7 MB/s

Ok, 制作完毕,就可以启动安装了。

1.2 安装设置和分区大小设置

安装时在初始安装界面里建议激活账号,输入你的红帽账号和密码,这样就自动注册到你账号下免费的Self Support Subscription了。如果不再这里激活,那么安装完毕后还要重复类似过程,否则系统的repo里是空的,无法安装任何软件。

避坑 1:另外虽然红帽友好地提供了一个自动分区,但是这里提醒读者,由于RHEL对每个user的home路径(/home/username)有严格的访问权限控制(drwx------), 这使得很多程序都无法访问用户自己home路径下的内容,因为它们运行时一般都有自己的进程用户名,比如nginx使用nginx,apache使用www-data或apache, plex的用户名是plex,此时因为上述权限设置都会导致访问文件失败。因此,如果你像我一样把RHEL主要部署为server使用, 那么安装时就要让/(根分区)的分区尽可能大,因为你的web和媒体内容都会尽量往/(根路径)下面的非/home路径存放来避开访问权限限制,比如网页放在/var/www。我当时就是没注意这个,几百G的硬盘只分了几十G给/(根分区), 其余都分配给了自己的home路径,导致后续使用中发现各种网页和媒体塞满了/var,而自己的/home分区很少用到,所以又进行了不少复杂操作才实现了磁盘调整(感兴趣这些具体操作的读者,请参见我另一篇博文“RHEL 8 无损调整/home和/分区大小”)。务必注意这一点。

避坑 2: 我曾经试着在Win 10下用balenaEtcher(v 1.5.109)尝试制作,中间失败了,就没再尝试了。此前我一直用此工具进行Ubuntu安装工具制作,没有问题,所以建议还是像官方链接里说的在Linux下制作吧,或者尝试别的windows下的制作工具。

2. 配置防火墙firewalld

安装完毕后它默认的防火墙firewalld就已经打开了,这点比Ubuntu强,Ubuntu自带的uwf安装后是默认关闭的。

sudo systemctl status firewalld 
# 查看firewalld 是否在运行, status可以替换成start,stop,restart,enable, disable来控制服务执行

sudo firewall-cmd --list-all  # 查看当前信息

我需要修改设置允许SSH,并限定只允许某个ip地址客户机进行SSH登陆,这点firewalld不如ufw,没法使用ufw里类似 allow from 192.168.1.0/24 语法简单实现,需要添加一个rich rule来实现:

# 添加一条rich rule: sudo firewall-cmd --add-rich-rule='[RichRule]', rule 用单引号''包围,内部引号用双引号""
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.123/32" service name="ssh" log prefix="SSH Access" level="notice" accept'

# 其他例子:允许某些IP访问某个端口, Plex使用 32400, port值也可以写"80-82" 开放3个端口
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="32400" protocol="tcp" accept'

# 允许某些IP访问某个服务,比如samba服务只能局域网内访问
rule family="ipv4" source address="192.168.1.0/24" service name="samba" accept

# 移除一条rich-rule,需要复制粘贴相同文本,不好用,应该加入ufw类似的id方式删除
sudo firewall-cmd --remove-rich-rule='[RichRule]'

# 重新加载设置使变更生效
sudo firewall-cmd --reload

另外还找到了添加自定义服务的方法,比如我安装了Plex Media Server,需要配置它需要的一些端口,当然可以一条条的添加rich rule, 但也可以采用可以自定义服务xml的方法来实现:

# 创建一个新文件,名字plex.xml
sudo nano /etc/firewalld/services/plex.xml  

# 添加如下端口内容并保存退出, 参考 https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>plex</short>  # 这个名字应该是用来区分服务的名字的。
<description>Ports required by Plex.</description>
<port protocol="tcp" port="32400"></port> #(for access to the Plex Media Server) [required]
<port protocol="tcp" port="32469"></port> # (for access to the Plex DLNA Server)
<port protocol="tcp" port="8324"></port> #  (for controlling Plex for Roku via Plex Companion)
<port protocol="tcp" port="3005"></port> #  (for controlling Plex Home Theater via Plex Companion)
<port protocol="udp" port="32414"></port> # (for current GDM network discovery)
<port protocol="udp" port="32413"></port> # (for current GDM network discovery)
<port protocol="udp" port="32412"></port> # (for current GDM network discovery)
<port protocol="udp" port="32410"></port> # (for current GDM network discovery)
<port protocol="udp" port="1900"></port> #  (for access to the Plex DLNA Server)
<port protocol="udp" port="5353"></port> #  (for older Bonjour/Avahi network discovery)
</service>

# 添加服务并重新加载, 可以采用如下简单方式:
sudo firewall-cmd --add-service=plex --permanent

# 但因为我想限定它只能被局域网内访问,因此采用rich rule方式
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="plex" accept'

sudo firewall-cmd --reload

# 最终发现我只需要使用32400端口,不需要使用其他,所以我把这个rich rule又删掉了,只开放最小需要的端口。

另外还发现了这个警告,也做了相应修改:

WARNING: AllowZoneDrifting is enabled. This is considered an insecure configuration option. It will be removed in a future release.

# You can disable it in 
sudo nano /etc/firewalld/firewalld.conf. 
#Search for AllowZoneDrifting in this conf and change yes to no.

避坑: 注意命令里的参数 --permanent, 少了它,--reload后会给你惊奇 🙂

firewall-cmd做的修改(add、remove)分为两种,runtime 修改和permanent修改。

runtime 修改在运行该命令后立即生效, 比如firewll-cmd --add-port=80/tcp, 执行完后80端口立即可以访问。但是当firewalld 服务被停止或reload后就失效了,即重启后80端口就无法访问。类比于ram内容关机丢失。此时当你执行 firewall-cmd --reload的时候就发现新添加的端口rule消失了 🙁

通过--permanent参数的修改是permanent修改,它也是立即生效,但不同于runtime修改, 它在firewalld 被停止或reload后仍然有效。类比与写入硬盘的数据不丢失。

3. 配置SSH

RHEL8 默认支持用户名/密码和key文件两种方式,这里修改设置为禁止用户名/密码登陆,即只能使用Key文件方式。

3.1 RHEL8 上生成密钥(公钥和私钥)

cd ~
ssh-keygen  #不需要sudo获取root权限, 一路enter选默认就可以了。默认路径为 ~/.ssh/id_rsa
# id_rsa是私钥,需要传输到其他客户端机器,mac/linux可以直接使用,Windows putty 需要先将此文件转存后才能用。
# id_ras.pub是公钥,里面含有公钥字符串。
# Your identification has been saved in ~/.ssh/id_rsa
# Your public key has been saved in ~/.ssh/id_rsa.pub

3.2 RHEL8上配置公钥

id_ras.pub里面含有公钥字符串。SSH默认从.ssh/authorized_keys 这个文件读取公钥字符串,因此执行命令:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
sudo chmod 600 ~/.ssh/authorized_keys  #禁止别的用户操作
# 如果此authorized_keys文件不存在,则会先创建它;如果此文件已经存在,则把id_rsa.pub文件里的内容添加到末尾。

3.3 修改ssh config文件

禁止密码登陆和允许免密码登陆都是通过修改/etc/ssh/sshd_config 文件实现,打开文件后确认、修改如下两个选项的值:

sudo nano /etc/ssh/sshd_config

# 只需要确认如下的两个选项为yes 和no即可:
#PubkeyAuthentication yes  # 支持Key文件访问,这个RHEL 8里默认就是yes,不需要修改
PasswordAuthentication no  # 禁止用户名/密码访问,这个RHEL 8里默认就是yes,需要修改为no

# 修改完毕后重启ssh 服务:
sudo systemd restart ssh

3.4 修改防火墙

默认SSH对所有ip有效,改为只允许某一个ip访问:

sudo firewall-cmd --permanent --remove-service=ssh  #移除当前ssh 规则因为它对所有ip开放

sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.122/32 service name=ssh log prefix="SSH Access" level="notice" accept' # 使用rich-rule来添加ssh只允许从某一个机器 
# 别的ip就会报错“ssh: connect to host port 22: No route to host”

sudo firewall-cmd --reload # 重载