2.6 网络面试问题
tcp 与 udp的区别
1.tcp 是基于连接的 UDP是基于数据包
2.处理并发的方式不通
a.tcp用epoll进行监听的
b. udp是模拟tcp的连接过程,服务端开放一个IP端口,收到连接后,服务端用另一个IP和端口发包给客户端。
3.tcp根据协议MTU黏包及分片 或 默认30ms的延迟发送黏包及分片, 接收端则需要分包,分包有两种分包方案。
tcp分包方案1:可以给包头(用户数据的头)前几个字节(自己定)存放包长,接收端先解析长度,一次性接收整包长度后再接收下一包。
tcp分包方案2:包的末尾可以加分割符 ,比如\r\n\r\n, 检索分隔符以确认分包的位置。
tcp 的两种方案都是基于tcp的有序接收来处理的。
udp是无序的,发送端没有黏包。每包的最大长度就是MTU的值。如果接收端需要有序接收则需要发送端给每个包编上号码,接收端则重新排序。
4.使用场景不同 tcp因为有延迟确认,注定了tcp无法应用到快速响应场景中,游戏,直播。UDP则可以
5.tcp适合长连接,因为有握手和挥手。udp适合短连接,一次发送 一次响应的那种,比如DNS请求
DNS 请求报文通常使用 UDP 协议,并且使用端口号 53。UDP 协议适用于 DNS 因为它简单且开销低,适合快速的请求和响应场景。
但在某些情况下,DNS 也会使用 TCP 协议:
- 响应数据大于 512 字节:如果 DNS 响应的内容较多(如包含许多记录或 DNSSEC 数据),UDP 数据包无法容纳,客户端会通过 TCP 重新请求。
- 区域传送 (Zone Transfer):区域传送(如在主从 DNS 服务器之间同步区域数据)使用 TCP 协议。
- EDNS(扩展 DNS):启用 EDNS 后,UDP 包的大小上限可以增加,但如果数据依然超出,仍然会切换到 TCP。
总结来说,常规 DNS 查询使用 UDP,大数据或特殊情况切换到 TCP。
MTU的讨论
----------------------------------------------------------------------------------------------
MTU(Maximum Transmission Unit,最大传输单元)限制的是网络数据帧中 有效负载(payload) 的最大字节长度,即 IP 数据包中的数据部分的最大大小。
通常,MTU 的限制包括以下内容:
- IP 层数据:对于 IPv4 网络,标准的以太网 MTU 为 1500 字节,这表示 IP 数据包的最大大小(包括 IP 头部和数据部分)不能超过 1500 字节。
- 链路层帧:以太网帧的总大小会包含以太网头部(通常为 14 字节)和 CRC 校验部分(通常为 4 字节),因此,最终传输的以太网帧总长度为 1500 + 14 + 4 = 1518 字节(如果启用了 VLAN,额外增加 4 字节)。
MTU 限制的关键点
- 应用层数据:在传输时会被拆分成更小的 IP 数据包片段,以适应 MTU 限制。
- IP 分片:如果数据包大于 MTU,会在传输时分片。
-------------------------------------------------------------------------------------------
在已知 MTU 的情况下,TCP 和 UDP 的 IP 头部长度、TCP/UDP 头部长度都是固定的,因此可以计算出用户负载(payload)的数据长度。
具体计算方法
假设标准的以太网 MTU 为 1500 字节,并且我们在 IPv4 环境下:
1. IP 头部
- IPv4 头部长度:通常为 20 字节(无选项字段时)。
- IPv6 头部长度:固定为 40 字节(无选项字段时)。
2. TCP 和 UDP 头部
- TCP 头部长度:通常为 20 字节(无选项字段时)。
- UDP 头部长度:固定为 8 字节。
计算用户负载长度
1. TCP 数据包的有效负载(以 IPv4 为例)
- 总 MTU 为 1500 字节。
- 减去 IP 头部(20 字节)和 TCP 头部(20 字节): 1500−20−20=1460 字节1500 - 20 - 20 = 1460 \text{ 字节}1500−20−20=1460 字节
- 因此,对于标准的 IPv4 TCP 包,用户数据的最大长度是 1460 字节。
2. UDP 数据包的有效负载(以 IPv4 为例)
- 总 MTU 为 1500 字节。
- 减去 IP 头部(20 字节)和 UDP 头部(8 字节): 1500−20−8=1472 字节1500 - 20 - 8 = 1472 \text{ 字节}1500−20−8=1472 字节
- 因此,对于标准的 IPv4 UDP 包,用户数据的最大长度是 1472 字节。
结果总结
在 IPv4 环境下:
- TCP:用户数据最大为 1460 字节。
- UDP:用户数据最大为 1472 字节。
这种计算方式依赖于默认的头部大小,如果有其他选项字段(如 IP 选项、TCP 选项),则用户数据的最大长度会相应减少。
IP头和TCP的选项字段一般都有可能是什么
在 IP 和 TCP 协议中,选项字段是可选的附加字段,通常用于扩展功能或优化网络性能。以下是 IP 和 TCP 中常见的选项字段:
1. IP 头部选项字段
IP 头部选项字段通常在 IPv4 中使用较多,IPv6 则使用扩展头来处理类似功能。IPv4 的 IP 头部选项字段的最大长度是 40 字节,一般包括以下内容:
- 记录路由 (Record Route, RR):记录数据包在经过的路由器的 IP 地址,以帮助网络诊断和追踪路径。通常限制最多记录 9 个路由器地址。
- 时间戳 (Timestamp):记录数据包经过的每个路由器的时间戳,用于网络时延测量。
- 松散源路由 (Loose Source Routing, LSR):允许发送方指定数据包经过的部分路由节点,其他节点则由路由器自动选择。该选项有助于绕过拥塞路由,但较少使用。
- 严格源路由 (Strict Source Routing, SSR):要求数据包必须严格按照指定的路由节点传输,不允许自动选择其他路径。
- 安全 (Security):用于标记数据包的安全级别,适用于军事或其他高安全要求的环境,但在实际网络中应用较少。
2. TCP 头部选项字段
TCP 头部选项字段主要用于优化传输性能,通常 TCP 头部选项的最大长度是 40 字节。以下是常见的 TCP 选项:
- 最大段大小 (Maximum Segment Size, MSS):由客户端和服务器在建立连接时交换,表示每个 TCP 段的最大数据负载大小,常用于避免 IP 分片。
- 窗口缩放 (Window Scale):允许 TCP 窗口大小扩大,以支持更大的窗口,优化高带宽、高延迟的网络传输。
- 选择性确认 (Selective Acknowledgment, SACK):允许接收方确认非连续接收到的数据段,优化丢包恢复,减少重传的数据量。
- 时间戳 (Timestamp):用于 RTT(Round Trip Time)计算,帮助更精准地管理数据传输时间,并有助于防止旧数据包重传引起的干扰(防止重播攻击)。
- NOP(No Operation):填充选项,不执行操作,通常用于对齐字段,确保其他选项按 4 字节对齐。
- 快速打开 (TCP Fast Open, TFO):通过保存加密的 Cookie 进行快速的 TCP 连接重用,减少三次握手延迟,提升传输效率。
总结
- IP 头选项字段:主要用于网络路径跟踪、路由控制和安全标记,虽然具备强大功能,但实际应用较少。
- TCP 头选项字段:广泛用于优化传输,特别是在现代网络中,MSS、窗口缩放和 SACK 是最常见的选项。
MTU的值在哪修改
在操作系统中,可以通过命令来修改网络接口的 MTU 值。不同系统的修改方式略有差异,以下是常见方法:
### 1. **Linux**
在 Linux 上,可以使用 `ip` 或 `ifconfig` 命令来修改 MTU 值。
- 使用 `ip` 命令:
```bash
sudo ip link set dev <interface> mtu <value>
例如,设置 `eth0` 接口的 MTU 为 1400 字节:
```bash
sudo ip link set dev eth0 mtu 1400
- 使用 `ifconfig` 命令:
```bash
sudo ifconfig <interface> mtu <value> up
```
例如:
```bash
sudo ifconfig eth0 mtu 1400 up
```
### 2. **Windows**
在 Windows 上,可以通过 `netsh` 命令修改 MTU 值:
- 打开命令提示符或 PowerShell(以管理员身份运行),然后输入以下命令:
```powershell
netsh interface ipv4 set subinterface "<interface_name>" mtu=<value> store=persistent
```
例如,将接口名为 `Ethernet` 的 MTU 设置为 1400:
```powershell
netsh interface ipv4 set subinterface "Ethernet" mtu=1400 store=persistent
```
### 3. **macOS**
在 macOS 上,可以使用 `ifconfig` 命令:
```bash
sudo ifconfig <interface> mtu <value>
```
例如,设置 `en0` 接口的 MTU 为 1400:
```bash
sudo ifconfig en0 mtu 1400
```
### 4. **路由器**
在路由器上,MTU 设置通常在 **管理界面**的网络接口或 WAN 设置中。不同的路由器管理界面略有不同,通常在**高级设置**或**网络设置**中找到 MTU 配置选项。
### 注意事项
- 修改 MTU 值可能会影响网络性能,应根据具体网络环境和需求进行调整。
- 调整 MTU 值后,通常无需重启网络接口,但某些网络配置可能需要重启。
MSS、窗口缩放和 SACK 这几个功能的具体讲解
1. MSS(Maximum Segment Size,最大段大小)
MSS 是 TCP 连接在三次握手过程中由客户端和服务器协商决定的一个参数,它定义了每个 TCP 数据段中用户数据部分(不含 TCP/IP 头部)的最大大小。
- 工作原理:
- MSS 的值是基于 MTU(最大传输单元)计算得出,通常为 MTU - IP头长度 - TCP头长度。在以太网上,典型 MTU 是 1500 字节,去掉 IP(20 字节)和 TCP 头部(20 字节)后,MSS 通常是 1460 字节。
- 通过协商 MSS 值,发送方和接收方知道每个数据段最大可以发送多少字节的有效数据,避免了过大的数据段导致 IP 分片,提高了传输效率。
- 优点:
- 避免了 IP 分片:确保数据段大小不超过路径上的 MTU。
- 提高传输效率:减少分片的可能性,降低重传的开销。
2. 窗口缩放(Window Scale)
TCP 的窗口缩放是一个选项,用于支持更大的 TCP 窗口大小。它解决了默认 TCP 窗口大小的限制,允许在高带宽、长延迟(高 BDP)网络中更高效地传输数据。
- 背景:
- TCP 的窗口大小字段默认只能容纳 16 位数值,最大窗口大小为 65535 字节(64 KB)。
- 在高带宽、长延迟的网络中(如卫星网络或光纤链路),64 KB 的窗口不足以发挥带宽优势。
- 工作原理:
- 窗口缩放选项在三次握手期间协商,它是一个 8 位值,表示对窗口大小进行的左移位数,最大值为 14。
- 通过窗口缩放,可以将窗口大小扩大到 65535 * 2^14 = 1 GB,以支持大带宽延迟积 (BDP) 网络。
- 优点:
- 允许更大的窗口大小,提高了数据流传输的效率。
- 有助于在高带宽、高延迟的网络中充分利用链路。
3. SACK(Selective Acknowledgment,选择性确认)
SACK 是一种数据丢失恢复机制,允许接收方只确认丢失的特定数据段,而非重新传输已成功接收的所有数据段。TCP 默认的确认机制是累计确认(Cumulative Acknowledgment),只能确认所有连续收到的数据。这种方式在数据丢包时会导致大量数据重传,而 SACK 则可以减少这种冗余。
- 工作原理:
- SACK 在 TCP 头中增加一个选项字段,接收方可以通过该选项告诉发送方哪些数据段已成功接收,哪些数据段丢失。
- 当发送方收到 SACK 信息后,只重传丢失的数据段,避免重传已成功接收的数据。
- 优点:
- 减少重传数据量,降低网络负担,尤其在高丢包环境中更为有效。
- 提高了网络传输的效率和可靠性,加快了丢包恢复速度。
总结
- MSS:限制每个 TCP 数据段的最大数据大小,避免 IP 分片。
- 窗口缩放:允许更大窗口大小,以支持高带宽、高延迟网络,充分利用网络资源。
- SACK:提供精确的丢包信息,减少不必要的重传,提高丢包恢复效率。
这些选项广泛应用于现代 TCP 连接中,尤其在高带宽和高延迟的网络环境中,有效提升了网络的整体传输性能。
窗口缩放的选项段是否会被攻击,假如被人设置为3,则会反复重传?
窗口缩放选项确实存在被攻击的可能性,称为 窗口缩放攻击。在这种攻击中,恶意方可以在 TCP 连接建立过程中篡改或伪造窗口缩放因子,将其设置为较小的值,比如 1 或 3。这样会导致 TCP 发送方的窗口大小严重受限,传输效率大幅降低,甚至可能导致大量的 重传 或 带宽浪费。
窗口缩放攻击的具体原理
窗口缩放因子是在 TCP 三次握手期间协商的,因此恶意方可以在这一过程中进行中间人攻击(MITM),将窗口缩放因子修改为非常小的值。这样会导致以下问题:
- 窗口大小受限:TCP 窗口大小由 窗口大小 = 初始窗口大小 × 2^缩放因子 计算得到。若缩放因子被恶意设置为 1 或 3,那么窗口大小可能会被限制在很小的范围(例如几 KB),导致数据传输受到严重限制。
- 频繁等待和超时:由于窗口大小限制,发送方每次只能发送少量数据,并在接收方确认后才能继续发送。这会导致频繁等待,降低吞吐量,增加 RTT。
- 频繁重传:在窗口缩放因子非常小时,发送方在高延迟网络环境中可能会频繁触发超时重传,进一步加剧网络拥塞,影响传输稳定性。
如何防范窗口缩放攻击
- 验证三次握手数据:在 TCP 连接建立时,可以通过防火墙或安全网关对三次握手包进行完整性检查,确保窗口缩放因子未被篡改。
- 限制最小窗口缩放因子:可以通过网络配置或安全策略,设置一个合理的窗口缩放因子的最小值。例如,设定最小值为 6(窗口扩大到至少 64 KB),避免过小的因子影响性能。
- 使用加密协议:通过加密手段(如 TLS)建立安全通道,确保 TCP 三次握手过程中交换的选项字段不易被篡改。
- 监测网络性能异常:网络设备可以设置监控和告警机制,当发现窗口大小异常小或出现频繁超时重传时,自动触发告警并进一步检查原因。
总结
窗口缩放确实可能被恶意攻击者利用来影响连接性能,但通过加密、网络监控和合理配置,可以有效降低此类攻击的风险。
如何在用户层获取 MSS
对于TCP而言 协议中没有MTU的值的确认,MSS其实就是MTU算出的一个值,一般由内核自己管理。
通过 getsockopt 函数,可以在用户层获得当前 TCP 连接的 MSS 值。这是通过查询套接字的 TCP_MAXSEG 选项来实现的,例如:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/tcp.h> // TCP_MAXSEG
#include <arpa/inet.h>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("Socket creation failed");
return -1;
}
// 设置服务器地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80); // 使用 HTTP 端口
inet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr); // 目标IP
// 连接服务器
if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Connect failed");
return -1;
}
// 获取 MSS 值
int mss;
socklen_t len = sizeof(mss);
if (getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &mss, &len) == 0) {
printf("MSS value: %d\n", mss);
} else {
perror("Failed to get MSS");
}
close(sock);
return 0;
}
为什么 MSS 设置由系统控制
- MSS 受路径 MTU 决定:MSS 通常是通过路径上的 MTU 减去 IP 和 TCP 头部长度来自动确定的,防止了路径上数据包被分片,确保传输效率。
- 自动调整传输大小:操作系统内核会依据 MSS 值调整 TCP 发送缓冲区的分片大小,确保不会发送超过 MSS 的数据包,从而避免 IP 层的分片处理,提升网络性能。
- 用户层应用程序不必担心分片:通过 send 或 write 的数据长度可以任意,但 TCP 会在内核中自动分段,因此用户层应用程序无需直接控制分片过程。
因此,通过 getsockopt 获取 MSS 后,用户层应用程序可以大致控制发送数据的长度,防止接近或超过 MSS,以最大化数据传输效率。
Sign in · GitLab