Skip to content

Go 主机安全面试:Linux 异常监听端口与后门服务检测

Linux 主机被入侵后,攻击者可能启动后门服务、绑定隐藏端口、复用业务进程做命令通道,或者通过端口转发暴露内网服务。面试官常会追问:Go Agent 怎么发现异常监听?如何把端口和进程对应起来?怎么避免把正常业务服务报成后门?

岗位场景

text
Linux 主机
  -> 采集监听端口、socket inode、进程 fd、启动命令和服务来源
  -> 关联登录、Web RCE、文件落地、提权和异常外联
  -> 识别后门服务、端口转发、临时调试服务和未知暴露面
  -> 输出可解释证据,支持客户排障和攻击链复盘

这类题考的是 Linux 网络栈视图、/proc 文件系统、进程画像、资产基线、误报治理和 Go 侧低开销采集设计。

高频面试题

1. HIDS/EDR 为什么要检测异常监听端口?

简洁答案:监听端口代表主机暴露了新的入口,攻击者可以用它维持后门、做端口转发、接收控制指令或把内网服务代理出去。

关键知识点:

  • 正常监听常见于业务服务、SSH、数据库、监控 Agent 和本地 sidecar。
  • 可疑监听可能来自 Web RCE 后启动的 ncsocat、Python HTTP 服务、代理工具或自定义后门。
  • 端口本身不是恶意证据,关键是“谁启动、从哪来、什么时候出现、和哪条攻击链相关”。

Go 落地思路:

  • 周期采集 TCP/UDP 监听快照,重点关注新增、消失和进程归属变化。
  • 标准化字段至少包含 protolocal_addrportstateinodepidexecmdline
  • 把异常监听作为攻击链节点,不要只靠端口号直接判恶意。

2. Linux 上有哪些方式可以采集监听端口?

简洁答案:低依赖方案是读取 /proc/net/tcp/proc/net/tcp6/proc/net/udp/proc/net/udp6,再用 /proc/<pid>/fd 里的 socket inode 反查进程。

常见来源:

text
/proc/net/tcp
/proc/net/tcp6
/proc/net/udp
/proc/net/udp6
/proc/<pid>/fd/socket:[inode]
/proc/<pid>/exe
/proc/<pid>/cmdline
systemd unit / crontab / shell history / auditd execve

关键知识点:

  • ss -lntup 输出直观,但它本质也来自内核网络视图和进程 fd 映射。
  • Agent 不应依赖外部命令;命令可能不存在、被替换,执行也有额外开销。
  • /proc/net/tcp 里的地址和端口是十六进制,需要正确处理字节序。

Go 落地思路:

  • 优先直接读 /proc,减少外部命令依赖。
  • 先解析 socket 表,再扫描 /proc/<pid>/fd 建立 inode -> pid 映射。
  • 进程短生命周期导致映射失败时,保留端口事件并标记 process_missing
go
func isTCPListen(state string) bool {
	return state == "0A"
}

3. 怎么把监听端口映射到进程?

简洁答案:/proc/net/* 给出 socket inode,/proc/<pid>/fd/* 的符号链接会出现 socket:[inode],用 inode 做 join 就能找到持有 socket 的进程。

关键知识点:

  • 一个进程可以监听多个端口,一个端口也可能被多个 worker 通过 SO_REUSEPORT 共享。
  • 权限不足时,普通用户可能看不到其他用户进程的 fd。
  • 进程退出、端口关闭和 fd 扫描之间存在竞态,采集器必须容忍不一致。

Go 落地思路:

  • inode 映射使用 map[string][]ProcessRef,不要假设一个 inode 只有一个进程。
  • fd 读取失败按 pid 记录错误原因,不让单个进程影响整轮采集。
  • 进程画像尽量补 execmdlineuidppid 和容器信息。

4. 异常监听端口有哪些高价值特征?

简洁答案:重点看新增端口、非基线路径、Web 进程派生、临时目录执行、弱认证服务、异常父进程和与攻击事件接近的时间窗口。

常见信号:

信号为什么可疑例子
临时目录执行攻击工具常落在可写目录/tmp/.x/socat
Web 父进程可能来自 Web RCEnginx -> sh -> python3 -m http.server
非业务端口新增暴露面变化新增 444431337
只监听公网地址可被外部访问0.0.0.0:9001
进程名伪装规避人工排查sshd kworker1

Go 落地思路:

  • 告警原因用列表表达,例如 new_public_listenertemp_path_execweb_parent
  • 端口基线按主机角色维护,不能把“非 80/443/22”简单视为恶意。
  • 对监听地址区分 127.0.0.1、内网地址和 0.0.0.0,公网暴露风险不同。

5. 如何检测 Web RCE 后启动的后门监听?

简洁答案:把 Web 进程派生命令、文件落地、端口监听和后续连接放进同一个时间窗口关联,链路完整时置信度更高。

关键知识点:

  • 攻击者可能用 nc -lsocat TCP-LISTENpython -m http.server 或自写 Go/Rust 后门。
  • 命令行可能被清空或伪装,仍可用父进程、exe 路径、hash 和端口变化补证据。
  • 单条端口事件容易误报,攻击链上下文更适合客户复盘。

Go 落地思路:

  • 维护短窗口事件缓存,例如 execve -> file_write -> listen -> accept/connect
  • 对 Web 进程族维护小名单:nginxapache2httpdphp-fpmtomcat
  • 规则输出链路:web_parent -> shell -> listener -> remote_peer

6. 如何降低正常服务带来的误报?

简洁答案:用资产角色、服务基线、systemd unit、包来源、签名/hash、变更窗口和监听地址共同判断。

关键知识点:

  • 数据库、中间件、监控、服务网格和运维工具都会新增监听端口。
  • 客户发布、扩容和灰度期间端口变化是正常现象。
  • 白名单必须有作用域,不能全局忽略某个端口或进程名。

Go 落地思路:

  • 首次上线建立端口基线,后续只关注新增或归属变化。
  • 白名单条件包含 host_roleportexe_hashunit_namelisten_addr 和过期时间。
  • 被压制的命中仍记录样例和计数,便于判断白名单是否过宽。

7. 采集监听端口有哪些性能和权限问题?

简洁答案:主要成本在扫描 /proc/<pid>/fd,主机进程多时要控制频率、超时和错误采样;权限不足时要明确能力降级。

关键知识点:

  • /proc/net 读取通常较轻,但 fd 目录扫描会随进程和 fd 数增长。
  • 容器环境里宿主机视图、容器 pid namespace 和 network namespace 可能不同。
  • 普通权限 Agent 可能无法读取所有进程的 fd、exe 和 cmdline。

Go 落地思路:

  • 采集间隔按资产风险配置,不需要毫秒级轮询。
  • 对 fd 扫描设置每轮上限和耗时指标,例如 scan_duration_msfd_read_errors
  • 上报 capability:can_read_all_proc_fdnetns_scopeprocess_enrich_level

8. 客户反馈异常监听告警误报,你会怎么排查?

简洁答案:先确认端口和进程归属,再看服务来源、启动链路、变更窗口、监听地址、远端连接和规则命中原因。

排查顺序:

  1. 确认 portlisten_addrpidexecmdlineuid 和主机角色。
  2. 查看进程父链,判断是否来自 systemd、运维终端、Web 进程或脚本任务。
  3. 核对 systemd unit、包来源、文件 hash、创建时间和最近发布记录。
  4. 查看是否伴随 Web RCE、可疑文件落地、提权、反弹连接或登录异常。
  5. 如果是正常服务,补充窄作用域白名单和基线;如果证据不足,降低规则置信度。

Go 落地思路:

  • 告警详情直接展示命中规则、端口变化、进程链和采集能力,减少来回查日志。
  • 保留原始 /proc/net 行号、socket inode 和进程快照时间,方便定位采集竞态。
  • 误报样本回流到规则测试集,避免下次发布重新引入同类问题。

通俗答案

异常监听端口检测不是“看到陌生端口就报警”,而是回答三个问题:

text
新入口是谁开的?
入口是不是应该存在?
它是否和攻击链上的其他行为连在一起?

Go Agent 的工作是用最低依赖把端口、socket inode、进程、父子链和服务来源串起来。规则层再结合主机角色、基线、变更窗口和攻击链上下文判断风险。

Go 落地设计要点

  • 采集层:直接读 /proc/net/*/proc/<pid>/fd,避免依赖 netstatlsofss
  • 标准化层:统一 TCP/UDP、IPv4/IPv6、监听地址、端口、inode 和进程画像。
  • 检测层:关注新增公网监听、临时目录进程、Web 父进程、非基线路径和攻击链时间窗口。
  • 降噪层:基线按主机角色和服务来源收敛,白名单必须带 hash、路径、端口和过期时间。
  • 可观测性:记录扫描耗时、fd 读取失败、进程映射缺失和被压制告警数量。

学习要点

  • 理解 /proc/net/tcp、socket inode、/proc/<pid>/fd 之间的关系。
  • 熟悉 TCP 状态码,知道 0A 表示 LISTEN
  • 能说明为什么不能只匹配端口号或进程名。
  • 能把监听端口和 Web RCE、文件落地、提权、外联放进攻击链。
  • 能设计有上限的采集器,避免 fd 扫描拖慢客户主机。
  • 能用基线、服务来源和变更窗口降低误报。

小练习/复盘题

  1. 写一个只读函数,解析 /proc/net/tcp 中处于 LISTEN 状态的本地端口。
  2. 设计一个 ListenerEvent 结构体,字段要能表达端口、地址、inode、进程和采集能力。
  3. 如果 /proc/net/tcp 看到端口,但找不到 pid,你会如何标记事件?
  4. 为什么 0.0.0.0:8080127.0.0.1:8080 的风险不同?
  5. 客户的 Java 服务新增监听端口被误报,你需要哪些证据才能收敛规则?
  6. 如何把 “nginx -> sh -> socat TCP-LISTEN” 设计成可解释的攻击链告警?
最近更新