跳转至

14 - 端口与服务映射及安全扫描

前提条件

  • 已完成 SSH 端口 2222 配置、fail2ban、AppArmor、nftables/ufw 防火墙
  • 系统只暴露必要端口(当前仅 2222/tcp 允许入站)
  • 以 root 身份登录,或 ops 用户执行 sudo -i 切换至 root 环境
  • 虚拟机环境:VMware Workstation Pro(建议桥接网络,便于从宿主机扫描)

全局参数

主机名 linuxdc,IP 192.168.1.100/24,SSH 端口 2222,运维用户 ops

详细步骤

1. 本地端口与服务自查

查看当前监听端口和服务映射:

ss -tulnjp                       # 监听端口 + 进程 PID / 名称(推荐)
ss -tunap                        # 所有连接状态 + 进程信息
lsof -i -P -n | grep LISTEN      # 进程视角查看监听端口

预期输出示例(最小化安全系统):

Netid  State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port  Process
tcp    LISTEN  0       128     0.0.0.0:2222         0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
tcp    LISTEN  0       128     [::]:2222            [::]:*             users:(("sshd",pid=1234,fd=4))

检查点

ss -tulnjp 输出中除 2222 端口外,不应出现任何其他对外监听的端口127.0.0.1 上的本地监听可以有,如 systemd-resolved 的 53)。

2. 安装扫描工具

apt update
apt install -y nmap

3. 本地扫描自身(快速自检)

# TCP 连接扫描(不需要 root)
nmap -sT localhost

# SYN 半连接扫描全端口(需要 root,更快、更隐蔽)
nmap -sS -p- localhost

# 服务版本探测
nmap -sV -p 1-65535 localhost

# 运行安全脚本(无破坏性,适合自检)
nmap --script safe localhost

sS 与 sT 的区别

-sT(TCP connect scan)完成完整的三次握手,日志清晰但速度慢,会在目标日志留下连接记录。-sS(SYN scan)只发送 SYN 包,收到 SYN-ACK 后立即发 RST 终止,速度更快,日志较少。-sS 需要 root 权限(原始套接字)。

4. 从宿主机扫描虚拟机(外部视角验证)

在宿主机(Windows/Mac/Linux)安装 nmap 后执行:

# 快速扫描常用端口
nmap -sS -p 1-10000 192.168.1.100

# 服务版本 + 操作系统指纹
nmap -sV -O 192.168.1.100

# 全面扫描(OS、服务、默认脚本,速度较慢)
nmap -A 192.168.1.100

预期结果(安全配置正确时):

PORT     STATE    SERVICE
2222/tcp open     ssh
# 其他端口显示 filtered 或 closed

检查点

宿主机扫描结果中,2222/tcp 显示 open,其他端口均为 filteredclosed。若出现其他 open 端口,需立即排查是否为未授权服务。

5. 自动化定期端口扫描脚本

创建巡检脚本:

mkdir -p /opt/security
vim /opt/security/port-scan.sh

脚本内容:

#!/bin/bash
# 端口巡检脚本 - 定期扫描本机开放端口并记录日志

LOGFILE="/var/log/port-scan.log"
ALERT_MAIL="root"
EXPECTED_PORTS="2222"     # 预期开放的端口列表(逗号分隔)
TARGET="192.168.1.100"

DATE=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$DATE] 开始端口扫描 - 目标: ${TARGET}" >> "${LOGFILE}"

# 扫描并记录开放端口
OPEN_PORTS=$(nmap -sT -p- --open "${TARGET}" 2>/dev/null | grep "^[0-9]" | awk -F'/' '{print $1}' | tr '\n' ',')

echo "[$DATE] 开放端口: ${OPEN_PORTS:-}" >> "${LOGFILE}"

# 检查是否有意外开放端口
UNEXPECTED=$(echo "${OPEN_PORTS}" | tr ',' '\n' | grep -vE "^(${EXPECTED_PORTS})$" | grep -v '^$')
if [ -n "${UNEXPECTED}" ]; then
    echo "[$DATE] 警告:发现意外开放端口: ${UNEXPECTED}" >> "${LOGFILE}"
    echo "主机 ${TARGET} 发现意外开放端口: ${UNEXPECTED}" | mail -s "端口巡检告警" "${ALERT_MAIL}" 2>/dev/null
fi

echo "[$DATE] 扫描完成" >> "${LOGFILE}"
echo "------------------------------" >> "${LOGFILE}"

赋予权限并测试:

chmod +x /opt/security/port-scan.sh
/opt/security/port-scan.sh
tail /var/log/port-scan.log

检查点

/var/log/port-scan.log 中显示只有 2222 为开放端口,无"意外开放端口"告警。

添加到 systemd timer(推荐,比 cron 更现代):

vim /etc/systemd/system/port-scan.service
[Unit]
Description=Daily Port Scan

[Service]
Type=oneshot
ExecStart=/opt/security/port-scan.sh
vim /etc/systemd/system/port-scan.timer
[Unit]
Description=Daily Port Scan Timer

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now port-scan.timer
systemctl list-timers | grep port-scan

6. 系统安全审计工具(可选)

# 综合安全审计(覆盖账号、文件权限、SSH 配置、内核参数等)
apt install -y lynis
lynis audit system

# 查看审计评分和建议
cat /var/log/lynis.log | grep "Suggestion\|Warning" | head -30

实践任务

  1. ss -tulnjp 确认当前系统只监听 2222/tcp(及本地回环上的其他端口)
  2. 在虚拟机内运行 nmap -sV localhost,记录输出
  3. 从宿主机用 nmap 扫描虚拟机 IP,确认只有 2222 端口开放
  4. 创建 port-scan.sh 脚本并手动运行一次,查看日志是否显示预期结果

自测问题

1. ss -tulnnmap localhost 的输出区别是什么?

ss -tuln系统内部视图:直接读取内核套接字表,显示所有监听端口(包括只绑定在 127.0.0.1 的本地端口),无需网络通信,速度极快,结果绝对准确,但只能在本机执行。nmap localhost网络探测视图:模拟外部客户端发起 TCP/UDP 探测,只能看到网络层可达的端口,受防火墙规则影响(本地回环通常不受 nftables 过滤),速度较慢。生产审计时两者配合使用:ss 查本机完整监听,nmap 从宿主机确认外部可见的暴露面。

2. 为什么生产环境中推荐使用 -sS(SYN scan)而非 -sT(TCP connect)?

-sT 完成完整的三次握手,每次扫描都在目标的连接日志中留下完整记录,速度慢,且会消耗目标的连接资源(可能触发 fail2ban)。-sS 发送 SYN 后收到 SYN-ACK 就立即发 RST 终止,不完成握手,对目标系统的影响最小,扫描速度更快(不需要等待连接超时),日志噪音更少。在对自身系统做安全巡检时,-sS 是更专业的选择;但要注意 -sS 需要 root 权限,-sT 普通用户也可运行。

3. 如果 nmap 显示某个端口 "filtered" 而非 "closed",代表什么情况?

closed:端口可达,目标主机发回了 TCP RST 包,表示该端口没有服务监听,但防火墙放行了探测包。filtered:nmap 发出的探测包被丢弃(没有任何响应),通常意味着防火墙在该端口上配置了 DROP 而非 REJECT 规则。生产环境推荐将非授权端口设为 filtered(防火墙 drop),而非 closed(防火墙 reject),前者不向扫描者透露系统存在,后者会返回 RST/ICMP unreachable,泄露系统信息。

4. 如何快速判断系统是否意外暴露了不该开的端口?

三步闭环检查:

# 步骤一:本机内部视图(无防火墙影响)
ss -tulnjp | grep LISTEN

# 步骤二:防火墙外部视图(模拟攻击者视角)
nmap -sS -p- 192.168.1.100   # 从宿主机执行

# 步骤三:对比预期端口列表
# 预期:只有 2222/tcp
# 如有其他 open 端口立即排查:systemctl status <对应服务>

若两者结果不一致(内部有监听但外部看不到),说明防火墙正确过滤;若外部能看到内部未预期的端口,说明有新服务启动且防火墙未拦截,需立即处理。

总结

定期端口扫描是发现配置漂移、未授权服务暴露的第一道警戒线。结合防火墙"默认拒绝 + 只开必要端口"原则,通过 nmap 自检 + 外部验证 + 自动化巡检脚本,形成闭环安全监控。后续每新增一个业务服务并开放端口后,都应立即执行本章的扫描流程验证暴露情况。