Linux 进程管理与端口探测
服务进程端口信息
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 命令
使用 netstat(net-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
格式化输出系统中所有 TCP 和 UDP 监听端口及其对应的服务名称:
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 用户群组管理
创建群组
创建 "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 逻辑卷管理
手动扩容变更方案
# 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 系统救援
系统救援方式
单用户模式救援系统
重新启动,进入单人维护模式,系统会主动的给予 root 权限的 bash 接口,此时再以 passwd 修改密码即可。
- 开机重启
- 悬停在选择
Kernel的界面,选择默认的Grab引导装载程序条目,键入e来进入编辑模式
- 在
Kernel启动命令行参数末尾加上init=/bin/bash
- 键入
F10进行引导
- 获得单用户下的
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 加密串,再重新启动后,输入指定的账号密码即可。
- 挂载虚拟
ISO(Live CD)
- 开机重启
- 选择进入
Live CD系统
- 打开
Terminal终端
- 切换到
root,查看设备文件
- 挂载原根文件系统
- 将挂载的
/mnt根路径切换到/路径
- 设置一个新的
root密码
- 重启操作系统
更改 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无法登录的问题,以下是较为完整的排查思路。
通用的排障思路
- 网络连接验证:首先验证你的网络是否可以正常访问目标服务器,可以通过
ping命令来测试网络连接。 SSH服务检查:使用ps -ef | grep sshd命令确认SSH服务是否正在运行。如果SSH服务没有运行,你需要启动它。- 端口验证:
SSH默认使用22端口,确认服务器端的SSH是否更改了端口,如果更改了,那么客户端在连接的时候也需要指定相应的端口。 - 主机防火墙:服务器或客户端的防火墙可能阻止了
SSH连接,为了检查这个问题,你可以查看防火墙的规则是否可能影响到SSH连接,也可以尝试暂时关闭防火墙来测试连接。- 对于
Iptables,可以使用iptables -nL命令来列出当前所有生效的规则。 - 对于
Nftables(替代iptables),需要使用nft list ruleset命令来查看所有的规则集。 - 对于
Firewalld(centos系列),可以通过firewall-cmd --list-all-zones命令来显示所有区域的信息。 - 对于
UFW(debian系列),可以通过ufw status verbose命令来获取详细的规则状态信息。
- 对于
- 认证问题:如果你使用密钥对进行身份验证,确认你的私钥和服务器上保存的公钥是配对的。
- 权限问题:检查
.ssh目录以及密钥文件的权限,用户的.ssh目录权限应设置为700,密钥权限应为600。可以使用chmod命令修正权限。 - 日志监查:为了了解连接失败的原因,应查看
SSH的客户端和服务器端日志。在客户端,使用SSH命令加上-vvv选项可以获取详细的输出,例:ssh -vvv user@hostname; 在服务器端,查看/var/log/auth.log或/var/log/secure文件来获取更多信息,可以通过命令tail -f /var/log/auth.log或tail -f /var/log/secure查看最近的日志信息。 PAM模块问题:如果配置了PAM模块的认证,比如配置了两步验证(2FA/MFA)等,且客户端没有正确响应,也会导致登录失败。你需要查看服务器端的PAM模块配置(通常在/etc/pam.d/sshd下),并相应地调整你的登录方式。Selinux的策略:在某些系统中,如Red Hat或CentOS,Selinux安全模块可能会阻止SSH服务的正常运行。需要查看Selinux的状态,并确认其配置是否允许SSH服务的连接,或者禁用Selinux功能。
针对不同的用户
- 对于
root用户:需要确认/etc/ssh/sshd_config文件中的PermitRootLogin选项是否允许root登录。如果这个选项被设置成no或者prohibit-password,root用户将无法通过SSH登录。可以将此选项修改为yes并重启SSH服务以允许root登录。 - 对于普通用户:确认用户账号是否存在,并且如果
/etc/ssh/sshd_config文件中有AllowUsers列表的话,确认该用户被包含在列表中。
网络定位问题
以上基本能覆盖 90% 以上的问题了。当然,如果上述方法都无法确定问题的原因,那么抓包分析肯定是一个非常有效的手段。可以使用像 tcpdump 或 Wireshark 这样的网络分析工具来捕捉到服务器和客户端之间的包,并对包进行分析。
比如,使用 tcpdump 抓取 SSH 连接的数据包,可以使用如下命令:
root@localhost:~# tcpdump -i ens192 port 22 -vv
# 选项解释:
# -i ens192 表示抓取 ens192 网卡(请根据实际情况选择正确的网卡)的数据包
# port 22 表示抓取目标端口为 22 的数据包。
抓包可以提供详细的 SSH 连接过程中的数据信息,从而帮助你更深入地理解问题所在。然而,抓包信息通常比较复杂,需要一些网络知识来进行分析。
最后,如果还是不行,大概率可以拉着负责网络的同学一起卷一下这个问题,看看是不是路由器或者 Modem 阻止一些特定的连接。或者可能是东西向、南北向的 ACL 防火墙策略对连接有所限制。
最最最后,如果问题依然存在,只有祭出我们的杀手锏 ———— 万能重启大法,剩下的就祈祷下吧!