Junior SA 实战管理手册

179 阅读13分钟

Linux 进程管理与端口探测

image.png

服务进程端口信息

ps 命令

使用 ps 显示系统上指定进程的详细信息,以下使用三种不同风格的命令行参数

# GNU 风格(双破折线 --)
root@localhost:~# ps --pid 1
    PID TTY          TIME CMD
      1 ?        00:00:02 systemd

# Unix/POSIX 风格(单破折线 -)
root@localhost:~# ps -ef | grep -i "sshd" | grep -v "grep"
root         563       1  0 Nov29 ?        00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root       14457     563  0 01:14 ?        00:00:00 sshd: root@pts/0

# 查看某个用户下的进程
root@localhost:~# ps -fu <username> 

# BSD 风格(不使用破折线)
root@localhost:~# ps aux | grep -i "sshd" | grep -v "grep"
root         563  0.0  0.1  15404  9384 ?        Ss   Nov29   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root       14457  0.0  0.1  17964 11172 ?        Ss   01:14   0:00 sshd: root@pts/0

列出内存使用 Top5 的进程:

# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root@localhost:~# ps aux --sort=-%mem --no-headers | head -n 5
root        5929  0.8  1.5 1860484 125004 ?      Ssl   2023 816:28 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9 --cgroup-driver=systemd
root     3621857  0.2  1.5 1166816 122960 ?      Ssl   2023  60:06 mongod --bind_ip_all --replSet rs0
root     2831333  0.1  1.2 148680 105580 ?       Sl    2023  42:19 /etc/sysop/mongoosev3-agent/plugin/scanner/scanner
root        2229  0.4  1.0 1718512 85384 ?       Ssl   2023 373:01 /usr/local/bin/containerd
root         293  0.0  0.9 110968 79772 ?        Ss    2023   4:10 /lib/systemd/systemd-journald

列出 CPU 使用 Top5 的进程:

# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root@localhost:~# ps aux --sort=-%cpu --no-headers | head -n 5
root        5929  0.8  1.5 1860484 125268 ?      Ssl   2023 816:31 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9 --cgroup-driver=systemd
root        6829  0.4  0.8 2346580 71960 ?       Sl    2023 440:21 calico-node -felix
root        2229  0.4  1.0 1718512 85384 ?       Ssl   2023 373:03 /usr/local/bin/containerd
root     3621857  0.2  1.5 1166816 123244 ?      Ssl   2023  60:07 mongod --bind_ip_all --replSet rs0
root     3385040  0.1  0.6 755784 55832 ?        Ssl   2023  56:37 /speaker --port=7472 --log-level=info

查看某个应用程序的内存占用:

# 查看内存占用率Top1的进程:
root@live-streaming:~# ps aux --sort=-%mem | head -n 2
USER       PID  %CPU %MEM     VSZ    RSS TTY     STAT START    TIME COMMAND
infra      2997  1.8  1.2 5480092 804548 ?       Ssl   2023 1118:26 /opt/infra/nodelet/app/bin/edgelive -conf /opt/infra/nodelet/app/conf/config.yml

# 报告一个运行中的进程的内存映射:
root@live-streaming:~# pmap -x 2997
2997:   /opt/infra/nodelet/app/bin/edgelive -conf /opt/infra/nodelet/app/conf/config.yml
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000   40484   33700       0 r-x-- edgelive
0000000000400000       0       0       0 r-x-- edgelive
0000000002d89000    1320     736     236 rw--- edgelive
0000000002d89000       0       0       0 rw--- edgelive
0000000002ed3000    2476     196     196 rw---   [ anon ]
0000000002ed3000       0       0       0 rw---   [ anon ]
0000000004d5e000     200      20      20 rw---   [ anon ]
0000000004d5e000       0       0       0 rw---   [ anon ]
---------------- ------- ------- ------- 
total kB         5480096  805676  766316

# 查看系统内存信息:
root@live-streaming:~# free -h
              total        used        free      shared  buff/cache   available
Mem:            62G        2.0G         56G        624M        4.3G         59G
Swap:          7.4G        3.5M        7.4G

# 内存使用率为 1.2%,表示程序占用的内存超过了系统总内存的 1.2%,有此可知:
#
# 1.2% * 62G = 0.012 * 62G = 0.744G ≈ 744MB
#
# 通过计算得到的进程占用内存是大约 744 MB,和 ps 命令的 RSS 字段数值是接近的,
# 考虑到可能存在的测量误差,以及进程内存使用量在运行过程中的自然波动,这是可以接受的。
#
# RSS,全称是 Resident Set Size,中文可以叫做常驻集大小。它是 Unix-like 系统(如 Linux)中的一个概念,表示进程在实际物理内存中占用的空间大小。
# RSS 包含了进程使用的所有物理内存,包括程序的指令、程序的堆和栈、以及共享库等等。值得注意的是,RSS 不包括交换出到硬盘的内存和分配但尚未使用的内存。

netstat 命令

使用 netstatnet-tools 工具包)显示所有正在监听的端口和相关的进程信息

# 过滤进程id
root@localhost:~# netstat -luntp | grep "$(pgrep -u root sshd | head -1)"
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      563/sshd: /usr/sbin
tcp6       0      0 :::22                   :::*                    LISTEN      563/sshd: /usr/sbin

# 过滤服务名
root@localhost:~# netstat -luntp | grep -i "sshd"
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      563/sshd: /usr/sbin
tcp6       0      0 :::22                   :::*                    LISTEN      563/sshd: /usr/sbin

格式化输出系统中所有 TCPUDP 监听端口及其对应的服务名称:

root@localhost:~# netstat -lnutp | awk '
BEGIN{print "Proto\tPort\tProgram-name"; print "============================"}
NR>2 {
  if($1 ~ /^(tcp|udp)/){
    split($1, proto, "6") 
    split($4, arr, ":") 
    if(proto[1] ~ /^tcp/){
      split($7, a, "/")        
    } else {
      split($6, a, "/")
    }
    gsub(/[:.]$/, "", a[length(a)])
    lines[sprintf("%-5s\t%-5s\t%s", $1, arr[length(arr)], a[length(a)])]
  }
}
END {
    PROCINFO["sorted_in"] = "@ind_str_asc"
    for(line in lines) {
        print line
    }
}'
Proto   Port    Program-name
============================
udp     323     chronyd
udp6    323     chronyd
udp6    514     rsyslogd
tcp     4505    python3
tcp6    10050   zabbix_agent2
udp     36027   rsyslogd
tcp     22      sshd
tcp     8888    python3
tcp     443     nginx
tcp6    22      sshd
tcp6    80      nginx
udp     514     rsyslogd
tcp     4506    python3
tcp     80      nginx

ss 命令

CentOS 7 及其他一些 Linux 发行版中,ss 命令被推荐用作替代netstat的工具。因为 ss(Socket Statistics) 命令提供了更快速和更详细的套接字统计信息。

root@localhost:~# ss -luntp | grep -i "sshd"
tcp   LISTEN 0      128          0.0.0.0:22         0.0.0.0:*    users:(("sshd",pid=563,fd=3))
tcp   LISTEN 0      128             [::]:22            [::]:*    users:(("sshd",pid=563,fd=4))

统计 TCP 连接状态

root@localhost:~# ss -antp --no-header | awk '{++count[$1]} END {for(i in count) printf "%-10s %s\n", i, count[i]}'
ESTAB      20
LISTEN     20
TIME-WAIT  53

本地/远程网络端口探测

lsof 命令

使用 lsof 查看本地主机上被进程打开的文件的相关信息

# 检查端口号
root@localhost:~# lsof -i tcp:22
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd      563 root    3u  IPv4  14057      0t0  TCP *:ssh (LISTEN)
sshd      563 root    4u  IPv6  14068      0t0  TCP *:ssh (LISTEN)
sshd    15412 root    4u  IPv4  89441      0t0  TCP 10.2.102.244:ssh->10.79.156.222:49766 (ESTABLISHED)

# 检查服务名
root@localhost:~# lsof -i -P | grep ssh
sshd        563 root    3u  IPv4  14057      0t0  TCP *:22 (LISTEN)
sshd        563 root    4u  IPv6  14068      0t0  TCP *:22 (LISTEN)
sshd      15412 root    4u  IPv4  89441      0t0  TCP 10.2.102.244:22->10.79.156.222:49766 (ESTABLISHED)

使用 lsof 显示所有处于监听状态(LISTEN)TCP 套接字

root@localhost:~# lsof -nP -i TCP -s TCP:LISTEN
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd        563 root    3u  IPv4  14057      0t0  TCP *:22 (LISTEN)
sshd        563 root    4u  IPv6  14068      0t0  TCP *:22 (LISTEN)
container  2186 root   10u  IPv4  19496      0t0  TCP 127.0.0.1:43655 (LISTEN)
docker-pr 15014 root    4u  IPv4  86858      0t0  TCP *:9000 (LISTEN)
docker-pr 15020 root    4u  IPv6  88024      0t0  TCP *:9000 (LISTEN)

fuser 命令

使用 fuser 查看本地主机上打开文件的进程 ID

root@localhost:~# fuser -v 22/tcp
                     USER        PID ACCESS COMMAND
22/tcp:              root        563 F.... sshd
                     root      15412 F.... sshd

nc 命令

使用 netcat 进行远程主机的网络探测

检查单个端口是否开放nc -zv <目标IP> <端口号>
扫描某个IP范围内的多个端口nc -zv <目标IP> <起始端口号>-<结束端口号>
使用UDP协议进行端口扫描nc -zvu <目标IP> <端口号>
➜ ~ nc -zv 10.2.102.244 22
Connection to 10.2.102.244 port 22 [tcp/ssh] succeeded!

➜ ~ nc -zv 10.2.102.244 1-65535
nc: connectx to 10.2.102.244 port 1 (tcp) failed: Connection refused
nc: connectx to 10.2.102.244 port 2 (tcp) failed: Connection refused
...

nmap 命令

使用 nmap 进行远程主机的网络探测,不进行主机发现(ping),即不检查主机是否在线,直接进行端口扫描

➜ ~ nmap -p 22 -Pn 10.2.102.244
Starting Nmap 7.92 ( https://nmap.org ) at 2023-11-30 18:33 CST
WARNING: Running Nmap setuid, as you are doing, is a major security risk.

Nmap scan report for 10.2.102.244
Host is up (0.0054s latency).

PORT   STATE SERVICE
22/tcp open  ssh

Nmap done: 1 IP address (1 host up) scanned in 0.27 seconds

telnet 命令

使用 telnet 测试远程主机的连通性

➜ ~ telnet 10.2.102.244 22
Trying 10.2.102.244...
Connected to 10.2.102.244.
Escape character is '^]'.
SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u1

Linux 用户群组管理

image.png

创建群组

创建 "foo" 群组并指定 1000 gid

root@localhost:~# groupadd -g 1000 foo

root@localhost:~# tail -n 1 /etc/group
foo:x:1000: 

创建用户

创建 "foo" 用户并指定 1000 uid 和 /home/foo 家目录位置

root@localhost:~# useradd -u 1000 -g 1000 -m -d /home/foo -c "Application account for foo" -s /bin/bash foo

root@localhost:~# tail -n 1 /etc/passwd
foo:x:1000:1000:Application account for foo:/home/foo:/bin/bash

root@localhost:~# ll -d /home/foo
drwxr-xr-x 2 foo foo 4096 Nov 29 20:42 /home/foo

激活用户

随机字符串

root@localhost:~# openssl rand -base64 18
DI9@C4YHckqXd8IjBW8Jtfok

设置 "foo" 用户口令

root@localhost:~# echo "foo:DI9@C4YHckqXd8IjBW8Jtfok" | chpasswd

root@localhost:~# tail -n 1 /etc/shadow foo:$y$j9T$8kIjRcQC5wDFWXT49SRqU0$wBkMGFDjcVXPRIT89Dx/fUX/C65qlUpjiYgP4VjcfQ5:19691:0:99999:7:::

添加辅组

将用户 "foo" 添加到 docker 组中,使其成为 docker 辅助组。这样,用户 "foo" 就具有了对 docker 守护程序的访问权限,可以运行 docker 命令而不需要具有 sudo 权限。

root@localhost:~# usermod -aG docker foo

root@localhost:~# groups foo
foo : foo docker

删除账号

userdel 命令尝试删除名为 "foo" 的用户。选项 -r 表示删除用户的家目录、群组以及相关的文件。需要注意,这个命令是强制性的,谨慎使用,确保你不会意外删除了重要的数据。

root@localhost:~# userdel -r foo
userdel: foo mail spool (/var/mail/foo) not found

LVM 逻辑卷管理

image.png

手动扩容变更方案

# 1. lvm软件安装:
root@localhost:~# apt-get install -y lvm2

# 2. 分盘:
root@localhost:~# parted -s /dev/sdb mklabel gpt mkpart primary 0% 100%

# 3. lvm与fs操作:
root@localhost:~# pvcreate /dev/sdb1
root@localhost:~# vgcreate vgdata /dev/sdb1
root@localhost:~# lvcreate -l 100%Free -n lv_home vgdata
root@localhost:~# mkfs.ext4 /dev/vgdata/lv_home
root@localhost:~# echo "/dev/mapper/vgdata-lv_home /home  ext4  defaults  0 0" >> /etc/fstab
root@localhost:~# mkdir /home.bak
root@localhost:~# mount /dev/mapper/vgdata-lv_home /home.bak

# 4. 备份数据:
root@localhost:~# cd /home
# 由于/下没有足够的空间,不然可以直接备份到/tmp下,会更方便。
root@localhost:~# nohup tar -zcvf /home.bak/home.tar.gz ./ &
root@localhost:~# tail -f nohup.out

# 5. 等待安全停掉/home下的服务,或者重启机器
root@localhost:~# reboot

# 6. 检查确保没有开机自启的服务,如果有,kill掉
root@localhost:~# lsof | grep -i /home
root@localhost:~# ps -ef | grep -i /home

# 7. 进入挂载点的/home,恢复数据
root@localhost:~# rmdir /home.bak
root@localhost:~# cd /home
root@localhost:~# nohup tar -xvf home.tar.gz &

# 8. 删掉原有数据,释放空间
root@localhost:~# umount /home
root@localhost:~# cd /home
root@localhost:~# rm -rf *

# 9. 重新挂载
root@localhost:~# mount -a

# 10. 业务验证
# 如果没问题,可以将tar包删除
root@localhost:~# rm -rf  /home/home.tar.gz
root@localhost:~# rm -rf /home/nohup.out

根满无法扩容

LVM + Couldn't create temporary archive name

root@localhost:~# parted -s /dev/sdb mklabel gpt mkpart primary 0% 100%

root@localhost:~# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created.

root@localhost:~# vgextend vgdata /dev/sdb1
  Volume group "vgdata" successfully extended

root@localhost:~# lvextend -An -l 100%FREE /dev/mapper/vgdata-lvbase
  Size of logical volume vgdata/lvbase changed from 10.00 GiB (2560 extents) to 29.99 GiB (7678 extents).
  WARNING: This metadata update is NOT backed up.
  Logical volume vgdata/lvbase successfully resized.

root@localhost:~# resize2fs /dev/mapper/vgdata-lvbase
resize2fs 1.44.1 (24-Mar-2018)
Filesystem at /dev/mapper/vgdata-lvbase is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 4
The filesystem on /dev/mapper/vgdata-lvbase is now 7862272 (4k) blocks long.

扫描新 LUN 和 SCSI 磁盘

# 扫描磁盘
root@localhost:~# SCSI_HOSTS=$(ls /sys/class/scsi_host | xargs) 
for HOST in $SCSI_HOSTS;do 
 echo '- - - ' > '/sys/class/scsi_host/'$HOST'/scan' 
done

root@localhost:~# lsblk
NAME        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda           8:0    0  80G  0 disk 
├─sda1        8:1    0   1G  0 part /boot
└─sda2        8:2    0  79G  0 part 
  ├─vg-root 253:0    0  50G  0 lvm  /
  ├─vg-swap 253:1    0   4G  0 lvm  [SWAP]
  └─vg-home 253:2    0  25G  0 lvm  /home
sdb           8:16   0  40G  0 disk 
├─sdb1        8:17   0  20G  0 part 
└─sdb2        8:18   0  20G  0 part 
sdc           8:32   0  20G  0 disk    #  可以看到新增的磁盘 sdc

root@localhost:~# fdisk /dev/sdc
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

Device does not contain a recognized partition table
使用磁盘标识符 0x2c726a61 创建新的 DOS 磁盘标签。

命令(输入 m 获取帮助):n    # 输入n 回车
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p    # 输入P 回车
分区号 (1-4,默认 1):      # 直接 回车
起始 扇区 (2048-41943039,默认为 2048):  # 直接 回车
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):  # 直接 回车
将使用默认值 41943039
分区 1 已设置为 Linux 类型,大小设为 20 GiB

命令(输入 m 获取帮助):w  # 输入w 回车
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。

root@localhost:~# lsblk    
NAME        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda           8:0    0  80G  0 disk 
├─sda1        8:1    0   1G  0 part /boot
└─sda2        8:2    0  79G  0 part 
  ├─vg-root 253:0    0  50G  0 lvm  /
  ├─vg-swap 253:1    0   4G  0 lvm  [SWAP]
  └─vg-home 253:2    0  25G  0 lvm  /home
sdb           8:16   0  40G  0 disk 
├─sdb1        8:17   0  20G  0 part 
└─sdb2        8:18   0  20G  0 part 
sdc           8:32   0  20G  0 disk 
└─sdc1        8:33   0  20G  0 part     # 可以看到创建了一个sdc1的分区

Linux 系统救援

image.png

系统救援方式

单用户模式救援系统

重新启动,进入单人维护模式,系统会主动的给予 root 权限的 bash 接口,此时再以 passwd 修改密码即可。

  1. 开机重启

  1. 悬停在选择 Kernel 的界面,选择默认的 Grab 引导装载程序条目,键入 e 来进入编辑模式

  1. Kernel 启动命令行参数末尾加上 init=/bin/bash

  1. 键入 F10 进行引导

  1. 获得单用户下的 Shell 界面
# 根分区的挂载模式默认是ro,需要将其改为rw
mount -no remount, rw /

# 更改root密码
passwd root

# 同步
sync

# 恢复ro模式
mount -no remount, ro /

# 可换成Ctrl+Alt+Del
reboot

挂载 Live CD 救援系统

Live CD 开机后,挂载根目录去修改 /etc/shadow 文件,将里面的 root 的密码字段替换成新的 SHA512 加密串,再重新启动后,输入指定的账号密码即可。

  1. 挂载虚拟 ISO(Live CD)

  1. 开机重启

  1. 选择进入 Live CD 系统

  1. 打开 Terminal 终端

  1. 切换到 root,查看设备文件

  1. 挂载原根文件系统

  1. 将挂载的 /mnt 根路径切换到 / 路径

  1. 设置一个新的 root 密码

  1. 重启操作系统

更改 root 密码

查看 SHA256 密码:

root@localhost:~# grep "^root" /etc/shadow
root:$y$j9T$3qcLdmX1la7E0QJ4cNuDr0$BFyUKqDEhnJpPOiB6KC9JY67QacHcsLL3EjYDp5gNL0:19191:7:90:7:30::

交互式/非交互式更新密码:

# 使用passwd命令
root@localhost:~# passwd
New password: 
Retype new password: 
passwd: password updated successfully

# 使用chpasswd命令
root@localhost:~# echo "root:newpassword" | chpasswd

生成基于 SHA256+salt 的密码哈希:

# python方式
root@localhost:~# python -c "import crypt, getpass, pwd; print(crypt.crypt('newpassword', '$6$salt$'))"
$6$salt$rZ6osOXEao6KnOmUvmzDT4mGRwTCykvBw9ZJMu3v/sjK9vKs4y2vT17P9.AthOPh7idSmKKMIGnCOH66ZFqpf1

# perl方式
root@localhost:~# perl -e 'print crypt("newpassword", "$6$salt$") . "\n"'
$6$salt$rZ6osOXEao6KnOmUvmzDT4mGRwTCykvBw9ZJMu3v/sjK9vKs4y2vT17P9.AthOPh7idSmKKMIGnCOH66ZFqpf1

# openssl方式
root@localhost:~# openssl passwd -6 -salt 'salt'
Password: 
$6$salt$rZ6osOXEao6KnOmUvmzDT4mGRwTCykvBw9ZJMu3v/sjK9vKs4y2vT17P9.AthOPh7idSmKKMIGnCOH66ZFqpf1

直接修改 /etc/shadow 文件(不建议):

# 备份影子文件
root@localhost:~# cp -a /etc/shadow /etc/shadow.bak

# 将newpassword改为需要的密码
root@localhost:~# newpassline=$(awk -F ':' -v NewPassword=`perl -e 'print crypt("newpassword", "\$6\$salt\$")'` 'BEGIN{OFS=":"} /^root/{sub(/^.*$/, NewPassword, $2); print $0}' /etc/shadow)

# 替换影子文件
root@localhost:~# sed -i "/^root/s/^.*$/$newpassline/" /etc/shadow

SSH 无法登陆的排障思路

当遇到 SSH 无法登录的问题,以下是较为完整的排查思路。

通用的排障思路

  1. 网络连接验证:首先验证你的网络是否可以正常访问目标服务器,可以通过 ping 命令来测试网络连接。
  2. SSH 服务检查:使用 ps -ef | grep sshd 命令确认 SSH 服务是否正在运行。如果 SSH 服务没有运行,你需要启动它。
  3. 端口验证:SSH 默认使用 22 端口,确认服务器端的 SSH 是否更改了端口,如果更改了,那么客户端在连接的时候也需要指定相应的端口。
  4. 主机防火墙:服务器或客户端的防火墙可能阻止了 SSH 连接,为了检查这个问题,你可以查看防火墙的规则是否可能影响到 SSH 连接,也可以尝试暂时关闭防火墙来测试连接。
    • 对于 Iptables,可以使用 iptables -nL 命令来列出当前所有生效的规则。
    • 对于 Nftables(替代iptables),需要使用 nft list ruleset 命令来查看所有的规则集。
    • 对于 Firewalldcentos系列),可以通过 firewall-cmd --list-all-zones 命令来显示所有区域的信息。
    • 对于 UFWdebian系列),可以通过 ufw status verbose 命令来获取详细的规则状态信息。
  5. 认证问题:如果你使用密钥对进行身份验证,确认你的私钥和服务器上保存的公钥是配对的。
  6. 权限问题:检查 .ssh 目录以及密钥文件的权限,用户的 .ssh 目录权限应设置为 700,密钥权限应为 600。可以使用 chmod 命令修正权限。
  7. 日志监查:为了了解连接失败的原因,应查看 SSH 的客户端和服务器端日志。在客户端,使用 SSH 命令加上 -vvv 选项可以获取详细的输出,例:ssh -vvv user@hostname; 在服务器端,查看 /var/log/auth.log/var/log/secure 文件来获取更多信息,可以通过命令 tail -f /var/log/auth.logtail -f /var/log/secure 查看最近的日志信息。
  8. PAM 模块问题:如果配置了 PAM 模块的认证,比如配置了两步验证 (2FA/MFA) 等,且客户端没有正确响应,也会导致登录失败。你需要查看服务器端的 PAM 模块配置(通常在 /etc/pam.d/sshd 下),并相应地调整你的登录方式。
  9. Selinux 的策略:在某些系统中,如 Red HatCentOSSelinux 安全模块可能会阻止 SSH 服务的正常运行。需要查看 Selinux 的状态,并确认其配置是否允许 SSH 服务的连接,或者禁用 Selinux 功能。

针对不同的用户

  • 对于 root 用户:需要确认 /etc/ssh/sshd_config 文件中的 PermitRootLogin 选项是否允许 root 登录。如果这个选项被设置成 no 或者 prohibit-passwordroot 用户将无法通过 SSH 登录。可以将此选项修改为 yes 并重启 SSH 服务以允许 root 登录。
  • 对于普通用户:确认用户账号是否存在,并且如果 /etc/ssh/sshd_config 文件中有 AllowUsers 列表的话,确认该用户被包含在列表中。

网络定位问题

以上基本能覆盖 90% 以上的问题了。当然,如果上述方法都无法确定问题的原因,那么抓包分析肯定是一个非常有效的手段。可以使用像 tcpdumpWireshark 这样的网络分析工具来捕捉到服务器和客户端之间的包,并对包进行分析。 比如,使用 tcpdump 抓取 SSH 连接的数据包,可以使用如下命令:

root@localhost:~# tcpdump -i ens192 port 22 -vv

# 选项解释:
# -i ens192 表示抓取 ens192 网卡(请根据实际情况选择正确的网卡)的数据包
# port 22 表示抓取目标端口为 22 的数据包。

抓包可以提供详细的 SSH 连接过程中的数据信息,从而帮助你更深入地理解问题所在。然而,抓包信息通常比较复杂,需要一些网络知识来进行分析。

最后,如果还是不行,大概率可以拉着负责网络的同学一起卷一下这个问题,看看是不是路由器或者 Modem 阻止一些特定的连接。或者可能是东西向、南北向的 ACL 防火墙策略对连接有所限制。

最最最后,如果问题依然存在,只有祭出我们的杀手锏 ———— 万能重启大法,剩下的就祈祷下吧!