第28章 原始IP
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述原始IP(Raw IP)套接字的实现,包括原始IP的输出、输入、用途和安全考虑。
28.1 引言
什么是原始IP
原始IP(Raw IP):
- SOCK_RAW类型的套接字
- 直接读写IP数据报
- 不经过TCP/UDP处理
- 需要特殊权限(通常是root)
原始套接字给用户态直接访问IP层的能力。
原始IP的用途
主要用途:
-
诊断工具
- ping:发送ICMP回显请求
- traceroute:探测路径
- 各种网络诊断工具
-
实现新协议
- 在用户态实现新的传输层协议
- 不需要修改内核
- 快速原型开发
-
安全工具
- 端口扫描
- 漏洞扫描
- 安全测试
-
研究和实验
- 网络协议研究
- 性能测试
- 实验新特性
原始套接字是网络研究和诊断的重要工具。
28.2 原始IP的输出
输出过程
原始IP的输出过程:
应用程序
|
v
构造数据(或IP首部+数据)
|
v
sendto / sendmsg
|
v
内核处理
|
+---> IP_HDRINCL设置?
| |
| +---> 是 → 用户提供完整IP首部
| |
| +---> 否 → 内核构造IP首部
|
v
IP层发送
|
v
接口输出
IP_HDRINCL选项
IP_HDRINCL套接字选项:
| 值 | 说明 |
|---|---|
| 0(默认) | 内核构造IP首部,用户只提供数据 |
| 1 | 用户提供完整IP首部,内核不构造 |
默认情况(IP_HDRINCL=0):
- 用户只提供数据部分
- 内核构造IP首部
- 内核填充:版本、首部长度、TOS、总长度、标识、标志、偏移、TTL、协议、校验和、源地址、目的地址
- 源地址可以用IP_OPTIONS等选项控制
设置IP_HDRINCL=1:
- 用户提供完整的IP首部
- 内核基本不修改
- 用户可以控制所有字段
- 校验和可能还是内核计算
IP_HDRINCL让用户可以完全控制IP首部。
输出的细节
源地址选择:
- 默认用输出接口的地址
- 可以用IP_SRCADDR选项指定
- IP_HDRINCL时用户自己填
目的地址:
- 由sendto的参数指定
- IP_HDRINCL时从首部取
协议号:
- socket的protocol参数
- IP_HDRINCL时用户自己填
校验和:
- 内核计算IP首部校验和
- 不管IP_HDRINCL是否设置
内核还是会做一些基本处理。
28.3 原始IP的输入
输入过程
原始IP的输入过程:
网卡接收
|
v
IP层处理
|
v
检查协议号
|
+---> 匹配TCP? → 交给TCP
|
+---> 匹配UDP? → 交给UDP
|
+---> 匹配ICMP? → 交给ICMP
|
+---> 都不匹配? → 检查原始套接字
|
v
遍历原始套接字
|
+---> 协议号匹配?
| |
| +---> 是 → 复制一份给它
|
v
都不匹配?
|
+---> 是 → 丢弃,发ICMP协议不可达
匹配规则
原始套接字的匹配规则:
-
协议号匹配
- socket的protocol参数
- 和IP首部的协议字段比较
- 必须匹配
-
本地地址匹配(可选)
- 如果套接字bind了本地地址
- 目的地址要匹配
-
外部地址匹配(可选)
- 如果套接字connect了对端地址
- 源地址要匹配
协议号必须匹配,地址可选匹配。
多个原始套接字
多个原始套接字的情况:
- 一个数据报可能匹配多个原始套接字
- 每个匹配的套接字都收到一份拷贝
- 数据报被复制多份
- 每个套接字独立处理
多个原始套接字可以同时收到同一个数据报。
不匹配的情况
没有匹配的原始套接字:
- 内核丢弃数据报
- 发送ICMP协议不可达
- 告诉发送方协议不支持
未知协议会返回ICMP错误。
28.4 原始套接字的用途
ping
ping程序:
- 用原始套接字发送ICMP回显请求
- 接收ICMP回显应答
- 测量往返时间
- 测试连通性
为什么用原始套接字:
- ICMP是网络层协议
- 没有对应的传输层
- 需要直接访问IP层
ping是最经典的原始套接字应用。
traceroute
traceroute程序:
- 用原始套接字发送UDP或ICMP
- 逐渐增加TTL
- 接收ICMP超时消息
- 追踪路径上的路由器
为什么用原始套接字:
- 需要接收ICMP错误消息
- 需要控制TTL
- 普通套接字做不到
traceroute也是原始套接字的经典应用。
其他用途
自定义协议:
- 在用户态实现新协议
- 不需要修改内核
- 快速开发和测试
网络扫描:
- 端口扫描
- 主机发现
- 安全审计
协议研究:
- 研究协议行为
- 测试各种场景
- 性能分析
原始套接字的用途非常广泛。
28.5 安全考虑
原始套接字的安全风险
安全风险:
-
伪造IP首部
- 可以伪造源地址
- 可以伪造各种字段
- 可能用于攻击
-
发送任意协议
- 可以发送任何协议的报文
- 可以构造各种攻击报文
- 可能被滥用
-
接收敏感数据
- 可以收到所有不匹配的IP数据报
- 可能窃听
- 安全隐患
-
拒绝服务
- 发送大量伪造报文
- 消耗目标资源
- DoS/DDoS攻击
原始套接字功能强大,也有安全风险。
安全措施
常见的安全措施:
-
权限限制
- 需要root权限
- 普通用户不能创建
- 最基本的保护
-
特权分离
- 只给需要的程序权限
- 最小权限原则
- 降低风险
-
网络过滤
- 防火墙过滤
- 限制出站报文
- 防止伪造
-
监控和审计
- 监控原始套接字的使用
- 记录可疑行为
- 及时发现攻击
权限限制是最基本的安全措施。
不同系统的差异
不同系统的实现差异:
| 系统 | 权限要求 | 说明 |
|---|---|---|
| BSD | root | 需要超级用户 |
| Linux | root | 需要超级用户,也可以用能力 |
| Windows | Administrator | 需要管理员权限 |
基本都需要特殊权限。
28.6 小结
原始IP概述
-
什么是原始IP
- SOCK_RAW类型
- 直接读写IP数据报
- 不经过TCP/UDP
-
用途
- 诊断工具(ping、traceroute)
- 实现新协议
- 安全工具
- 研究实验
原始IP的输出
-
输出过程
- 应用构造数据
- 内核处理
- IP层发送
-
IP_HDRINCL选项
- 0:内核构造首部
- 1:用户提供首部
- 控制粒度不同
-
输出细节
- 源地址选择
- 目的地址
- 协议号
- 校验和
原始IP的输入
-
输入过程
- IP层分用
- 不匹配已知协议的交给原始套接字
- 遍历匹配
-
匹配规则
- 协议号必须匹配
- 本地地址可选匹配
- 外部地址可选匹配
-
多个套接字
- 每个匹配的都收到一份
- 复制多份
-
不匹配
- 丢弃
- 发ICMP协议不可达
原始套接字的用途
-
ping
- ICMP回显
- 测试连通性
-
traceroute
- 追踪路径
- 接收ICMP超时
-
其他
- 自定义协议
- 网络扫描
- 协议研究
安全考虑
-
安全风险
- 伪造IP首部
- 发送任意协议
- 接收敏感数据
- 拒绝服务
-
安全措施
- 权限限制
- 特权分离
- 网络过滤
- 监控审计
-
系统差异
- 都需要特殊权限
- 实现略有不同
关键概念
-
原始IP套接字
- SOCK_RAW
- 直接访问IP层
- 功能强大
-
IP_HDRINCL
- 控制谁构造IP首部
- 用户可以完全控制
-
输入匹配
- 协议号匹配
- 多个套接字可以同时收到
- 不匹配返回ICMP错误
-
安全
- 需要特殊权限
- 有安全风险
- 合理使用