Go 主机安全面试:Linux 防火墙与路由篡改检测
攻击者拿到 Linux 主机权限后,不一定只做进程隐藏或文件持久化,也可能修改 iptables、nftables、路由表、策略路由或内核网络参数,让反连流量绕过审计、把本地服务转发到外部、阻断安全 Agent 上报,或者给后续横向移动打开通道。面试官通常会追问:防火墙和路由变化为什么属于主机安全证据?Go Agent 怎么采?怎样区分 Docker、Kubernetes、firewalld 和真实攻击?
岗位场景
Linux 主机
-> 采集 iptables/nftables 命令执行、规则快照、netlink 路由变更和关键配置文件
-> 识别异常 ACCEPT/DROP、NAT/REDIRECT、默认路由、策略路由和转发参数变化
-> 关联 Web RCE、提权、反弹 shell、C2 外联、Agent 上报失败和日志清理
-> 区分容器运行时、云初始化、VPN、负载均衡、运维变更和恶意篡改
-> 输出可解释差异,而不是只告警“网络配置改变”这类题考的是 Linux 网络控制面、Netfilter/nftables、netlink、系统命令审计、文件基线、误报治理,以及 Go Agent 的状态快照和差异计算能力。
高频面试题
1. 为什么主机安全要关注防火墙和路由篡改?
简洁答案:防火墙和路由决定主机流量能不能出去、从哪里出去、是否被转发或重定向。攻击者修改这些配置后,可以隐藏通信、建立代理、绕过访问控制,甚至让安全 Agent 无法上报,所以它们是攻击链中的关键控制面证据。
关键知识点:
iptables、nftables、ip route、ip rule、sysctl都可能改变主机网络行为。- 恶意变更常见目标包括放通端口、删除 DROP 规则、增加 NAT、开启 IP 转发、修改默认路由。
- 单次规则变化不一定恶意,必须结合执行进程、用户、主机角色、变更窗口和后续网络行为判断。
- 容器、Service Mesh、VPN、云厂商 Agent 也会频繁改网络规则,是主要误报来源。
- 告警价值在于说明“谁改了什么、改前改后差异、造成什么风险”。
Go 落地思路:
- 事件模型里同时保留执行命令、规则快照、路由差异和发起进程。
- 对高危变更输出结构化 diff,避免只保存一整段不可检索的规则文本。
- 把网络控制面变化和进程、文件、外联、上报失败事件放入同一攻击链窗口。
2. iptables 和 nftables 检测要看哪些高危变化?
简洁答案:重点看默认策略变化、删除拒绝规则、放通管理端口、增加 NAT/REDIRECT、修改 OUTPUT 链、异常 owner/cgroup 匹配,以及把流量转发到陌生地址的规则。
关键知识点:
| 变化类型 | 风险解释 | 常见证据 |
|---|---|---|
DROP -> ACCEPT | 放宽入口或出口控制 | chain policy diff |
| 删除安全规则 | 关闭原有防护 | rule handle 或行号变化 |
DNAT/SNAT/MASQUERADE | 转发或隐藏真实来源 | nat table diff |
REDIRECT/TPROXY | 本地流量劫持到代理 | 目标端口和进程 |
| OUTPUT 放通 | 让恶意进程外联 | 目标网段、端口、owner |
| flush ruleset | 一次性清空防护 | iptables -F、nft flush ruleset |
Go 落地思路:
- 不要只匹配命令字符串,要把规则解析为
table/chain/action/proto/src/dst/port/comment。 - 同时支持
iptables-save风格和nft -j list ruleset的结构化读取。 - 对无法解析的规则保留原文摘要和 hash,用于后续排障。
3. 路由表和策略路由被改会带来什么安全风险?
简洁答案:路由表决定流量走哪张网卡和哪个网关;策略路由还能按源地址、fwmark、UID 或表号分流。攻击者可以把流量导向代理、旁路审计网关、访问隔离网段,或者把安全产品上报流量黑洞掉。
关键知识点:
- 默认路由被替换,会影响整台主机的出入口路径。
- 新增更精确的网段路由,可能只劫持安全平台、数据库或内网网段。
ip rule可以让特定源地址、mark 或 UID 使用不同路由表。blackhole、unreachable、prohibit路由可能用于阻断安全上报。- 多网卡、VPN、云 VPC、容器网络都会产生合法路由变化,不能只靠“新增路由”告警。
Go 落地思路:
type RouteChange struct {
Op string // add, del, replace
Dst string
Gateway string
Dev string
Table int
Priority int
ActorPID int
}- 用 netlink 监听
RTM_NEWROUTE、RTM_DELROUTE、RTM_NEWRULE等事件。 - 对默认路由、平台上报地址、内网关键网段维护高风险目标集合。
- 事件里记录
network_namespace,避免把容器内路由误判成宿主机路由篡改。
4. 如何把“配置变化”归因到具体进程?
简洁答案:最可靠的方式是把进程执行事件、审计事件和网络状态变化按时间窗口关联。看到 iptables、nft、ip、route、sysctl 执行后,在短时间内规则或路由快照发生对应变化,就能给出较强归因。
关键知识点:
- 只有 netlink 变化不一定知道是谁改的,需要补充 exec/audit/eBPF 证据。
sudo iptables ...的原始登录用户要看auid、session、父进程链。- 脚本或配置管理工具可能间接执行命令,要追到脚本路径、hash 和发布系统。
- 进程很快退出时,要用
pid + start_time + boot_id避免 PID 复用误关联。 - 时间窗口过宽会误报,过窄会漏掉批量脚本和异步应用配置。
Go 落地思路:
- 维护最近 30 到 120 秒的网络配置命令环形缓存。
- 关联键包含
pid、start_time、user、cmdline、cwd、container_id。 - 无法归因时也要输出“未知发起者”,但风险等级应低于可确认恶意进程链。
5. 如何区分 Docker/Kubernetes 正常规则和恶意篡改?
简洁答案:正常容器网络规则通常有稳定链名、固定前缀、运行时进程来源和可解释生命周期;恶意篡改更常来自异常 shell、临时目录脚本、Web 服务用户、未知二进制或手工命令,并且改动目标偏向放通、转发、劫持或阻断安全流量。
关键知识点:
- Docker 常见
DOCKER、DOCKER-USER、POSTROUTING MASQUERADE等链和规则。 - Kubernetes 节点会有 kube-proxy、CNI 插件、Service/Pod 网络相关规则。
- firewalld、ufw、VPN、云初始化脚本都会合法改规则。
- 白名单不能只按进程名放行,要绑定路径、hash、签名、用户、主机角色和变更类型。
- 对容器节点要先建立基线,再关注偏离基线的高危 diff。
Go 落地思路:
- 给规则变化打标签:
container_runtime、orchestrator、vpn、security_agent、unknown。 - 基线维度至少包含主机组、链名前缀、执行进程、规则动作和目标网段。
- 对“容器运行时进程新增常规 NAT”降级;对“Web 子进程 flush ruleset”直接升级。
6. 防火墙篡改和 Agent 上报失败如何关联?
简洁答案:如果防火墙或路由变化后,Agent 到安全平台的连接失败、重试增加或心跳断开,就要考虑安全产品被阻断。这个链路比单独的上报失败更有解释力。
关键知识点:
- 攻击者可能 DROP 平台地址、增加黑洞路由、改 DNS、改默认网关或阻断 443。
- 上报失败也可能是网络故障、平台维护或代理变更,不能直接归因攻击。
- 关键是时间顺序:网络控制面变化先发生,上报错误随后出现。
- 需要记录目标地址、错误类型、重试次数、最近一次成功时间和本机配置 diff。
- 告警应支持客户排障:给出具体被影响的 endpoint 和规则。
Go 落地思路:
- Agent 自身健康指标记录
upload_failed_total、last_success_at、last_error。 - 规则引擎把
network_config_change -> upload_failure放入短窗口关联。 - 对安全平台域名和 IP 做脱敏或分类,避免泄露内部平台地址。
7. 如何设计低开销的规则快照与 diff?
简洁答案:不要高频全量扫描所有规则。更务实的做法是事件触发加低频校验:监听 netlink 和敏感命令执行,触发局部快照;再用低频全量快照兜底,比较规范化后的规则指纹。
关键知识点:
- 规则文本顺序、计数器、handle id 可能变化,直接字符串 diff 容易误报。
- 高价值字段是 table、chain、hook、priority、action、match 条件和 target。
- 计数器类字段通常不应参与稳定指纹。
- 快照失败要区分命令不存在、权限不足、超时、输出过大和解析失败。
- 大规模主机上,快照频率和输出大小必须受控。
Go 落地思路:
- 使用
context.WithTimeout限制外部命令快照耗时。 - 对规则规范化后计算 hash,只在 hash 变化时保存 diff。
- 对超大 ruleset 设置行数和字节数上限,保留截断标记和错误计数。
8. 客户反馈“告警后业务网络断了”,你怎么排查?
简洁答案:先确认告警前后网络配置 diff,再查看是谁执行了变更、影响了哪些目标网段和端口、Agent 是否有上报失败,最后结合变更工单、容器事件和系统日志判断是正常变更、误报还是攻击。
关键知识点:
- 业务断网可能由防火墙 DROP、路由替换、DNS 变更、MTU 变化或网卡状态变化导致。
- 安全产品要能展示变更前后,而不是只展示最终状态。
- 需要保留本机时间线:命令执行、规则变化、连接失败、进程退出、服务重启。
- 如果规则阻断了 Agent,服务端只能看到心跳消失,本地诊断日志更重要。
- 误报复盘要沉淀成更窄的基线,而不是简单全局放行。
Go 落地思路:
- 提供本地诊断命令导出最近网络控制面事件和 Agent 健康指标。
- 支持离线 replay:把客户现场事件重新跑一遍当前规则,验证是否规则过宽。
- 把排障结论分成
expected_change、suspicious_change、insufficient_evidence。
通俗答案
可以把防火墙和路由理解成主机的“交通规则”。进程和文件告诉你“谁在做事”,网络连接告诉你“连了哪里”,而防火墙和路由告诉你“这些流量为什么能走、从哪里走、是否被拦截或转发”。攻击者如果改了交通规则,就可能让恶意通信更隐蔽,或者让安全产品看不见后续行为。
检测时不要把“规则变化”直接等同于攻击。长期可维护的方案是分三层:
- 采集层:记录敏感命令执行、netlink 路由事件、规则快照和配置文件变化。
- 规范化层:把不同来源统一成结构化 diff,过滤计数器和顺序噪声。
- 检测层:把高危 diff 与异常发起者、外联、Agent 上报失败、提权和持久化行为关联。
最值得告警的不是“Docker 加了一条 NAT”,而是“Web 服务用户拉起 shell 后执行 nft flush ruleset,随后安全平台连接失败”。
Go 落地要点
- 事件结构要包含
host_id、boot_id、netns、actor_process_key、change_type、before_hash、after_hash。 - 路由变化优先走 netlink,规则快照可以用受限命令或读取持久化配置兜底。
- 规则解析失败不能静默丢弃,要记录
parse_failed_total和原始摘要。 - 白名单绑定主机角色、进程路径、hash、用户、链名、目标网段和维护窗口。
- 对短时间大量规则变化做合并,避免一条批量脚本生成几十个重复告警。
- 对安全 Agent 自身通信目标做特殊保护,但注意脱敏和最小上报。
学习要点
| 方向 | 需要掌握 |
|---|---|
| Linux 网络控制面 | Netfilter、nftables、iptables、路由表、策略路由、sysctl |
| 采集能力 | exec/audit/eBPF、netlink route、规则快照、配置文件监控 |
| 攻击链还原 | Web RCE、提权、规则清空、流量转发、上报失败 |
| 误报治理 | Docker、Kubernetes、firewalld、VPN、云初始化、运维窗口 |
| Go 工程实现 | 有界缓存、规范化 diff、超时控制、错误计数、离线 replay |
小练习/复盘题
- 设计一个
FirewallRuleDiff结构体,要求能表达新增、删除和动作变化。 - 写一个函数判断
ip route变化是否影响安全平台上报地址,注意默认路由和更精确路由的优先级。 - 如果 Kubernetes 节点每分钟都有规则变化,你会怎样建立基线并降低噪声?
- 还原一条攻击链:Web RCE 后执行
iptables -F,随后下载 payload 并外联 C2,列出至少 6 个证据字段。 - 为什么规则计数器不适合作为稳定指纹?哪些字段更适合参与 hash?
- 客户说“这是 VPN 客户端正常改路由”,你会要求哪些字段来确认白名单范围是否足够窄?
