Android 网络栈中的 NAT 实现原理与 Netfilter 钩子机制

155 阅读4分钟

本内容覆盖了 NAT 的基本概念、Android 实现方式、连接跟踪机制(conntrack)及具体的示例流程。


Android 网络栈中的 NAT 实现原理与 Netfilter 钩子机制

🧭 前言

NAT(Network Address Translation)是现代网络中最常见的技术之一,广泛用于家庭、企业和云服务网络场景中。在 Linux 中,NAT 是通过 Netfilter 框架实现的,它结合了多层钩子点(hooks)与连接跟踪(conntrack)系统,实现了完整、灵活且强大的网络地址转换功能。

本篇文章将从 NAT 的核心原理出发,结合 Linux 内核的钩子机制(PREROUTING、POSTROUTING 等),并配合具体示例深入剖析 Linux 是如何完成 NAT 操作的。


📌 第一部分:NAT 基本概念简述

🔶 什么是 NAT?

NAT 是一种 IP 层的地址转换技术,它的主要作用是在网络边界上修改 IP 数据包中的源地址或目标地址。常见有两种形式:

  • SNAT(Source NAT) :修改源地址,常用于“内网设备访问外网”场景。
  • DNAT(Destination NAT) :修改目标地址,常用于“外网访问内网服务”场景。

🔷 NAT 的典型应用

场景使用 NAT 类型示例说明
内网电脑访问外网网站SNAT192.168.1.100 → 203.0.113.5
外网访问家庭摄像头DNAT203.0.113.5:8080 → 192.168.1.100:80
负载均衡流量转发(LVS)DNAT/SNAT网关代理连接并重定向流量

NAT的目标是什么

无论是家用路由器、企业防火墙还是 Linux 系统,NAT 的核心目标都是:

  • SNAT(Source NAT) :修改源 IP,用于内网机器访问外网时,伪装为网关的公网 IP。
  • DNAT(Destination NAT) :修改目标 IP,用于外网访问内网服务时,转发到真实内网主机。
  • 连接跟踪(conntrack) :对 NAT 后的连接进行状态跟踪,确保响应包能够正确返回。

这些 NAT 类型在路由器和 Linux 中都有体现,属于 “网络层的地址转换”

NAT工作在哪一层

因为NAT会修改IP头、TCP头、UDP头、ICMP头等,所以NAT工作在传输层和网络层


🔍 第二部分:Linux 中 NAT 的实现基础 - Netfilter 框架

Linux 实现 NAT 是基于 Netfilter 框架完成的。Netfilter 提供了一套钩子点机制,让内核模块(如 iptables/nftables)可以在数据包处理路径的多个阶段挂接逻辑。

📌 Netfilter 的五个主要钩子点(hooks)

钩子链名称处理阶段常见用途
PREROUTING数据包刚进入网卡主要用于 DNAT
INPUT数据包即将进入本机本地服务的接收处理
FORWARD数据包被转发(非本机)路由转发控制
POSTROUTING数据包将离开发送出网卡前主要用于 SNAT
OUTPUT本地进程发出的包本地 NAT 也可能在此

🧠 NAT 是工作在 PREROUTING 和 POSTROUTING 上的逻辑(DNAT 和 SNAT)


🧠 第三部分:连接跟踪(conntrack)系统

🔸 conntrack 简介

NAT 的核心难点在于:如果修改了地址,响应包还能回来吗?
Linux 使用 conntrack 模块解决这一问题。它会为每条连接维护状态记录和 NAT 映射。

比如:

tcp      6 431999 ESTABLISHED src=192.168.1.100 dst=8.8.8.8 sport=54321 dport=443 [UNREPLIED]

conntrack 在第一次请求时建立记录,并在后续包中引用这条记录,完成 NAT 转换的对称性。


🔧 第四部分:NAT 数据包流程示例(家庭网络)

我们用一个家庭路由器为例,演示内网主机访问公网、外网主机回包的整个 NAT 过程。


✅ 情景:内网主机访问外网网站(SNAT)

前提:
  • 内网主机:192.168.1.100
  • 路由器公网地址:203.0.113.5
  • 外网服务器:8.8.8.8
流程如下:
  1. 内网主机发送请求:
src=192.168.1.100:54321 → dst=8.8.8.8:443
  1. 包进入 Netfilter PREROUTING → 被允许通过 → 路由决定出接口为 eth0
  2. 到达 POSTROUTING:执行 SNAT(MASQUERADE)
src=203.0.113.5:40000 → dst=8.8.8.8:443
  1. conntrack 创建映射:记录 src 原地址
  2. 包被发送到 eth0 出口,发往公网

🔁 外网回包过程(DNAT via conntrack)

  1. 外网服务器回应包:
src=8.8.8.8:443 → dst=203.0.113.5:40000
  1. 包进入 PREROUTING
  2. conntrack 识别该连接,执行 DNAT:
dst 修改为:192.168.1.100:54321
  1. 包进入 FORWARD 链,路由表找到目标为内网主机
  2. 最终送达主机

📘 附:iptables NAT 规则示例

# 1. 启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# 2. 配置 SNAT(公网固定 IP)
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 203.0.113.5

# 3. 或配置 MASQUERADE(动态 IP 场景)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 4. 配置 DNAT(端口转发)
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80

🧩 小结

模块功能
Netfilter提供钩子点供模块在各阶段处理网络包
NAT 表定义 SNAT、DNAT 行为
conntrack跟踪连接状态和 NAT 映射关系
iptables用户态配置接口,用于管理 Netfilter 规则